end of day commit
This commit is contained in:
@@ -30,7 +30,7 @@ gem 'simply_stored' , :git => 'git://github.com/bterkuile/simply_stored.git'
|
|||||||
gem 'devise', '2.0.4'
|
gem 'devise', '2.0.4'
|
||||||
gem 'devise_simply_stored'
|
gem 'devise_simply_stored'
|
||||||
|
|
||||||
gem 'rqrcode-rails3'
|
gem 'rqrcode'
|
||||||
gem 'mini_magick'
|
gem 'mini_magick'
|
||||||
#gem "less-rails-bootstrap-devise", :git => 'git://github.com/bigbento/less-rails-bootstrap-devise.git'
|
#gem "less-rails-bootstrap-devise", :git => 'git://github.com/bigbento/less-rails-bootstrap-devise.git'
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -157,8 +157,6 @@ GEM
|
|||||||
rest-client (1.6.7)
|
rest-client (1.6.7)
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
rqrcode (0.4.2)
|
rqrcode (0.4.2)
|
||||||
rqrcode-rails3 (0.1.5)
|
|
||||||
rqrcode (>= 0.4.2)
|
|
||||||
rspec (2.11.0)
|
rspec (2.11.0)
|
||||||
rspec-core (~> 2.11.0)
|
rspec-core (~> 2.11.0)
|
||||||
rspec-expectations (~> 2.11.0)
|
rspec-expectations (~> 2.11.0)
|
||||||
@@ -240,7 +238,7 @@ DEPENDENCIES
|
|||||||
mini_magick
|
mini_magick
|
||||||
pry
|
pry
|
||||||
rails (= 3.2.8)
|
rails (= 3.2.8)
|
||||||
rqrcode-rails3
|
rqrcode
|
||||||
rspec-rails
|
rspec-rails
|
||||||
sass-rails (~> 3.2.3)
|
sass-rails (~> 3.2.3)
|
||||||
selenium-webdriver
|
selenium-webdriver
|
||||||
|
|||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
<map version="0.9.0">
|
||||||
|
<!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net -->
|
||||||
|
<node COLOR="#000000" CREATED="1346248504629" ID="ID_685891399" MODIFIED="1346249525729" TEXT="Qr scan">
|
||||||
|
<font NAME="SansSerif" SIZE="20"/>
|
||||||
|
<hook NAME="accessories/plugins/AutomaticLayout.properties"/>
|
||||||
|
<node COLOR="#0033ff" CREATED="1346248520045" ID="ID_454905514" MODIFIED="1346249526866" POSITION="right" TEXT="I already have an open list">
|
||||||
|
<edge STYLE="sharp_bezier" WIDTH="8"/>
|
||||||
|
<font NAME="SansSerif" SIZE="18"/>
|
||||||
|
<node COLOR="#00b439" CREATED="1346248563729" ID="ID_733708643" MODIFIED="1346249526869" TEXT="Table is from same supplier">
|
||||||
|
<edge STYLE="bezier" WIDTH="thin"/>
|
||||||
|
<font NAME="SansSerif" SIZE="16"/>
|
||||||
|
<node COLOR="#990000" CREATED="1346248693439" ID="ID_916776491" MODIFIED="1346249526871" TEXT="Offer to move table">
|
||||||
|
<font NAME="SansSerif" SIZE="14"/>
|
||||||
|
<node COLOR="#111111" CREATED="1346248699370" ID="ID_1684994680" MODIFIED="1346252084515" TEXT="If yes, move table and show product"/>
|
||||||
|
<node COLOR="#111111" CREATED="1346248725406" ID="ID_10610841" MODIFIED="1346252095940" TEXT="If no, show products"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#00b439" CREATED="1346248579841" ID="ID_227890554" MODIFIED="1346249526872" TEXT="Table is from other supplier">
|
||||||
|
<edge STYLE="bezier" WIDTH="thin"/>
|
||||||
|
<font NAME="SansSerif" SIZE="16"/>
|
||||||
|
<node COLOR="#990000" CREATED="1346248754701" ID="ID_1748068243" MODIFIED="1346249459783" TEXT="Warning, cannot do with open list">
|
||||||
|
<font NAME="SansSerif" SIZE="14"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#00b439" CREATED="1346248860563" ID="ID_141169907" MODIFIED="1346249526873" TEXT="Table is your current table">
|
||||||
|
<edge STYLE="bezier" WIDTH="thin"/>
|
||||||
|
<font NAME="SansSerif" SIZE="16"/>
|
||||||
|
<node COLOR="#990000" CREATED="1346248869002" ID="ID_418218218" MODIFIED="1346249459784" TEXT="Do nothing!">
|
||||||
|
<font NAME="SansSerif" SIZE="14"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#0033ff" CREATED="1346248530523" ID="ID_1378676144" MODIFIED="1346249526875" POSITION="left" TEXT="I do not have an open list">
|
||||||
|
<edge STYLE="sharp_bezier" WIDTH="8"/>
|
||||||
|
<font NAME="SansSerif" SIZE="18"/>
|
||||||
|
<node COLOR="#00b439" CREATED="1346248595465" ID="ID_313049528" MODIFIED="1346249526877" TEXT="Table is occupied by other user">
|
||||||
|
<edge STYLE="bezier" WIDTH="thin"/>
|
||||||
|
<font NAME="SansSerif" SIZE="16"/>
|
||||||
|
<node COLOR="#990000" CREATED="1346248635520" ID="ID_1246071370" MODIFIED="1346249459786" TEXT="Option: Join this table">
|
||||||
|
<font NAME="SansSerif" SIZE="14"/>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#990000" CREATED="1346249385937" ID="ID_146376441" MODIFIED="1346249526878" TEXT="Option: Show products">
|
||||||
|
<font NAME="SansSerif" SIZE="14"/>
|
||||||
|
<node COLOR="#111111" CREATED="1346249395535" ID="ID_152885983" MODIFIED="1346249459786" TEXT="Show products without ordering options"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#00b439" CREATED="1346248619233" ID="ID_1502347679" MODIFIED="1346249526883" TEXT="Table is not occupied by other user">
|
||||||
|
<edge STYLE="bezier" WIDTH="thin"/>
|
||||||
|
<font NAME="SansSerif" SIZE="16"/>
|
||||||
|
<node COLOR="#990000" CREATED="1346248629824" ID="ID_1685359507" MODIFIED="1346249459791">
|
||||||
|
<richcontent TYPE="NODE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Show products with ordering options
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
<font NAME="SansSerif" SIZE="14"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</map>
|
||||||
@@ -2,3 +2,11 @@ jQuery ->
|
|||||||
$("a[rel=popover]").popover()
|
$("a[rel=popover]").popover()
|
||||||
$(".tooltip").tooltip()
|
$(".tooltip").tooltip()
|
||||||
$("a[rel=tooltip]").tooltip()
|
$("a[rel=tooltip]").tooltip()
|
||||||
|
$('input.currency').each(->
|
||||||
|
obj = $(this)
|
||||||
|
original_width = obj.width()
|
||||||
|
obj.wrap("<div class='input-prepend'>")
|
||||||
|
currency_sign = $("<span class='add-on'>€</span>")
|
||||||
|
obj.before(currency_sign)
|
||||||
|
obj.css('width', (original_width - currency_sign.outerWidth())+'px')
|
||||||
|
)
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* Cookie plugin
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
|
||||||
|
* Dual licensed under the MIT and GPL licenses:
|
||||||
|
* http://www.opensource.org/licenses/mit-license.php
|
||||||
|
* http://www.gnu.org/licenses/gpl.html
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a cookie with the given name and value and other optional parameters.
|
||||||
|
*
|
||||||
|
* @example $.cookie('the_cookie', 'the_value');
|
||||||
|
* @desc Set the value of a cookie.
|
||||||
|
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
|
||||||
|
* @desc Create a cookie with all available options.
|
||||||
|
* @example $.cookie('the_cookie', 'the_value');
|
||||||
|
* @desc Create a session cookie.
|
||||||
|
* @example $.cookie('the_cookie', null);
|
||||||
|
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
|
||||||
|
* used when the cookie was set.
|
||||||
|
*
|
||||||
|
* @param String name The name of the cookie.
|
||||||
|
* @param String value The value of the cookie.
|
||||||
|
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
|
||||||
|
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
|
||||||
|
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
|
||||||
|
* If set to null or omitted, the cookie will be a session cookie and will not be retained
|
||||||
|
* when the the browser exits.
|
||||||
|
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
|
||||||
|
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
|
||||||
|
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
|
||||||
|
* require a secure protocol (like HTTPS).
|
||||||
|
* @type undefined
|
||||||
|
*
|
||||||
|
* @name $.cookie
|
||||||
|
* @cat Plugins/Cookie
|
||||||
|
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a cookie with the given name.
|
||||||
|
*
|
||||||
|
* @example $.cookie('the_cookie');
|
||||||
|
* @desc Get the value of a cookie.
|
||||||
|
*
|
||||||
|
* @param String name The name of the cookie.
|
||||||
|
* @return The value of the cookie.
|
||||||
|
* @type String
|
||||||
|
*
|
||||||
|
* @name $.cookie
|
||||||
|
* @cat Plugins/Cookie
|
||||||
|
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||||
|
*/
|
||||||
|
jQuery.cookie = function(name, value, options) {
|
||||||
|
if (typeof value != 'undefined') { // name and value given, set cookie
|
||||||
|
options = options || {};
|
||||||
|
if (value === null) {
|
||||||
|
value = '';
|
||||||
|
options.expires = -1;
|
||||||
|
}
|
||||||
|
var expires = '';
|
||||||
|
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
|
||||||
|
var date;
|
||||||
|
if (typeof options.expires == 'number') {
|
||||||
|
date = new Date();
|
||||||
|
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
|
||||||
|
} else {
|
||||||
|
date = options.expires;
|
||||||
|
}
|
||||||
|
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
|
||||||
|
}
|
||||||
|
// CAUTION: Needed to parenthesize options.path and options.domain
|
||||||
|
// in the following expressions, otherwise they evaluate to undefined
|
||||||
|
// in the packed version for some reason...
|
||||||
|
var path = options.path ? '; path=' + (options.path) : '';
|
||||||
|
var domain = options.domain ? '; domain=' + (options.domain) : '';
|
||||||
|
var secure = options.secure ? '; secure' : '';
|
||||||
|
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
|
||||||
|
} else { // only name given, get cookie
|
||||||
|
var cookieValue = null;
|
||||||
|
if (document.cookie && document.cookie != '') {
|
||||||
|
var cookies = document.cookie.split(';');
|
||||||
|
for (var i = 0; i < cookies.length; i++) {
|
||||||
|
var cookie = jQuery.trim(cookies[i]);
|
||||||
|
// Does this cookie string begin with the name we want?
|
||||||
|
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookieValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -59,8 +59,8 @@ root.Quser=
|
|||||||
row.append($('<td class="currency"></td>').html(Qrammer.currency(order.total_amount)))
|
row.append($('<td class="currency"></td>').html(Qrammer.currency(order.total_amount)))
|
||||||
foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>')
|
foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>')
|
||||||
)
|
)
|
||||||
order_selected_products: ()->
|
order_selected_products: (h)->
|
||||||
h = {}
|
h ||= {}
|
||||||
for product_id, info of window.active_products_list
|
for product_id, info of window.active_products_list
|
||||||
h['products['+product_id+']'] = info.number
|
h['products['+product_id+']'] = info.number
|
||||||
$.post('/user/order_selected_products', h, ((res) -> Quser.handle_response(res)), 'json')
|
$.post('/user/order_selected_products', h, ((res) -> Quser.handle_response(res)), 'json')
|
||||||
@@ -92,48 +92,67 @@ root.Quser=
|
|||||||
table.show()
|
table.show()
|
||||||
|
|
||||||
load_active_list_products: ->
|
load_active_list_products: ->
|
||||||
$.get('/user/list_products.json', (res) ->
|
Quser.populate_products_table('/user/list_products.json', true)
|
||||||
window.products = res
|
load_table_products: (table_id, occupied)->
|
||||||
|
Quser.populate_products_table('/user/list_products_for_table.json?table_id='+table_id, !occupied)
|
||||||
|
populate_products_table: (src, include_order_buttons)->
|
||||||
|
$.get(src, (res) ->
|
||||||
body = $('#products-table tbody')
|
body = $('#products-table tbody')
|
||||||
for category, products of window.products
|
for category, products of res
|
||||||
body.append('<tr><td colspan="4"><h4>'+category+'<h4></td></tr>')
|
body.append('<tr><td colspan="4"><h4>'+category+'<h4></td></tr>')
|
||||||
for product in products
|
for product in products
|
||||||
row = $('<tr></tr>')
|
row = $('<tr></tr>')
|
||||||
button = $('<button class="btn btn-mini btn-primary">Add</button>')
|
|
||||||
callback = ((prod) ->
|
|
||||||
->
|
|
||||||
product_count_holder = $('#order-product-count-'+prod._id)
|
|
||||||
count = parseInt(product_count_holder.text())
|
|
||||||
product_count_holder.text(1)
|
|
||||||
Quser.add_product(prod, count)
|
|
||||||
)(product)
|
|
||||||
button.click(callback)
|
|
||||||
row.append('<td>'+product.name+'</td>')
|
row.append('<td>'+product.name+'</td>')
|
||||||
order_product_count = $('<span id="order-product-count-'+product._id+'" class="order-product-count">1</span>')
|
if include_order_buttons
|
||||||
order_count_minus = $('<span class="btn btn-info btn-mini">-</span>')
|
button = $('<button class="btn btn-mini btn-primary">Add</button>')
|
||||||
order_count_minus.click(->
|
callback = ((prod) ->
|
||||||
val_holder = $(this).siblings('.order-product-count')
|
->
|
||||||
val = parseInt(val_holder.text())
|
product_count_holder = $('#order-product-count-'+prod._id)
|
||||||
val_holder.text(val - 1) if val > 1
|
count = parseInt(product_count_holder.text())
|
||||||
)
|
product_count_holder.text(1)
|
||||||
order_count_plus = $('<span class="btn btn-info btn-mini">+</span>')
|
Quser.add_product(prod, count)
|
||||||
order_count_plus.click(->
|
)(product)
|
||||||
val_holder = $(this).siblings('.order-product-count')
|
button.click(callback)
|
||||||
val = parseInt(val_holder.text())
|
order_product_count = $('<span id="order-product-count-'+product._id+'" class="order-product-count">1</span>')
|
||||||
val_holder.text(val + 1)
|
order_count_minus = $('<span class="btn btn-info btn-mini">-</span>')
|
||||||
)
|
order_count_minus.click(->
|
||||||
row.append($('<td class="order-count-cell"></td>').append(order_count_minus).append(' ').append(order_product_count).append(' ').append(order_count_plus))
|
val_holder = $(this).siblings('.order-product-count')
|
||||||
|
val = parseInt(val_holder.text())
|
||||||
|
val_holder.text(val - 1) if val > 1
|
||||||
|
)
|
||||||
|
order_count_plus = $('<span class="btn btn-info btn-mini">+</span>')
|
||||||
|
order_count_plus.click(->
|
||||||
|
val_holder = $(this).siblings('.order-product-count')
|
||||||
|
val = parseInt(val_holder.text())
|
||||||
|
val_holder.text(val + 1)
|
||||||
|
)
|
||||||
|
row.append($('<td class="order-count-cell"></td>').append(order_count_minus).append(' ').append(order_product_count).append(' ').append(order_count_plus))
|
||||||
row.append('<td>'+Qrammer.currency(product.price)+'</td>')
|
row.append('<td>'+Qrammer.currency(product.price)+'</td>')
|
||||||
row.append($('<td></td>').append(button))
|
row.append($('<td></td>').append(button)) if include_order_buttons
|
||||||
body.append(row)
|
body.append(row)
|
||||||
)
|
)
|
||||||
|
actions_for_table: (table)->
|
||||||
actions_for_table: (table_id)->
|
table = JSON.parse(table) if typeof(table) == 'string'
|
||||||
$.get('/user/table_info.json?table_id='+table_id, (res)->
|
$.get('/user/table_info.json?table_id='+table.table_id, (res)->
|
||||||
if res.occupied
|
if res.occupied
|
||||||
alert('Table is occupied')
|
alert('Table is occupied')
|
||||||
else
|
else
|
||||||
$.post('/user/create_list.json', {table_id: table_id}, (res)-> Quser.handle_response(res))
|
if res.other_supplier
|
||||||
|
#TODO cannot do something with other supplier when list is active
|
||||||
|
else if res.current_table_id && res.current_table_id == table.table_id
|
||||||
|
#nothing has changed, show product list
|
||||||
|
window.location = '/user/list_products'
|
||||||
|
else if res.current_table_id && res.current_table_id != table.table_id
|
||||||
|
#TODO Offer to move table
|
||||||
|
$.post('/user/move_table', {table_id: table.table_id}, (res2)->
|
||||||
|
if res2.occupied
|
||||||
|
alert('Cannot move to occupied table')
|
||||||
|
else
|
||||||
|
window.location = '/user/list_products'
|
||||||
|
)
|
||||||
|
else
|
||||||
|
#$.post('/user/create_list.json', {table_id: table.table_id}, (res)-> Quser.handle_response(res))
|
||||||
|
window.location = '/user/list_products_for_table?table_id='+table.table_id
|
||||||
, 'json')
|
, 'json')
|
||||||
add_product: (product, count) ->
|
add_product: (product, count) ->
|
||||||
count ||= 1
|
count ||= 1
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
form
|
||||||
|
input.currency
|
||||||
|
text-align: right
|
||||||
@@ -79,3 +79,5 @@ table
|
|||||||
list-style: none
|
list-style: none
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
|
li
|
||||||
|
float: left
|
||||||
|
|||||||
@@ -17,9 +17,16 @@ body
|
|||||||
height: 44px
|
height: 44px
|
||||||
background-repeat: no-repeat
|
background-repeat: no-repeat
|
||||||
width: 45px
|
width: 45px
|
||||||
background-image: image-url('icons/section-table.png')
|
//background-image: image-url('icons/section-table.png')
|
||||||
.table-number
|
.table-link
|
||||||
margin-top: -45px
|
margin-top: -45px
|
||||||
|
.table-number
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
line-height: 44px
|
||||||
|
width: 45px
|
||||||
|
font-size: 42px
|
||||||
|
text-align: center
|
||||||
.action-button-container
|
.action-button-container
|
||||||
margin-right: -20px
|
margin-right: -20px
|
||||||
&.section-tables-active
|
&.section-tables-active
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ class ApplicationController < ActionController::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
def check_active_list_state
|
def check_active_list_state
|
||||||
if session[:active_list_id]
|
if current_user.try(:active_list_id)
|
||||||
unless active_list.active?
|
unless active_list.active?
|
||||||
session[:active_list_id] = nil
|
current_user.list_is_closed!
|
||||||
redirect_to user_root_path, alert: t('messages.the_list_has_been_closed', list: List.model_name.human)
|
redirect_to user_root_path, alert: t('messages.the_list_has_been_closed', list: List.model_name.human)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -24,8 +24,8 @@ class ApplicationController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def active_list
|
def active_list
|
||||||
return nil unless session[:active_list_id].present?
|
return nil unless current_user.try(:active_list_id).present?
|
||||||
@active_list ||= List.find(session[:active_list_id])
|
@active_list ||= List.find(current_user.active_list_id)
|
||||||
end
|
end
|
||||||
alias :active_list_object :active_list
|
alias :active_list_object :active_list
|
||||||
helper_method :active_list_object
|
helper_method :active_list_object
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
class DashboardController < ApplicationController
|
class DashboardController < ApplicationController
|
||||||
|
|
||||||
before_filter :check_active_list_state, except: :home
|
|
||||||
def home
|
def home
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -16,9 +13,17 @@ class DashboardController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def supplier_home
|
# GET /select_qr_image
|
||||||
redirect_to active_orders_supplier_path(Supplier.first)
|
# GET /select_qr_image.png
|
||||||
|
# GET /select_qr_image.svg
|
||||||
|
def table_qr_image
|
||||||
|
@table = Table.find(params[:table_id])
|
||||||
|
code = {table_id: @table.id}.to_json
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.svg { render :qrcode => code, :level => :l, :unit => 10, table_number: @table.number }
|
||||||
|
format.png { render qrcode: code, table_number: @table.number }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
module Suppliers
|
module Suppliers
|
||||||
class ApplicationController < ::ApplicationController
|
class ApplicationController < ::ApplicationController
|
||||||
|
before_filter :authenticate_supplier!
|
||||||
layout 'tablet'
|
layout 'tablet'
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
module Suppliers
|
||||||
|
class ProductCategoriesController < Suppliers::ApplicationController
|
||||||
|
|
||||||
|
# GET /product_categories
|
||||||
|
# GET /product_categories.json
|
||||||
|
def index
|
||||||
|
@product_categories = current_supplier.product_categories
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # index.html.erb
|
||||||
|
format.json { render json: @product_categories }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /product_categories/1
|
||||||
|
# GET /product_categories/1.json
|
||||||
|
def show
|
||||||
|
@product_category = ProductCategory.find(params[:id])
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # show.html.erb
|
||||||
|
format.json { render json: @product_category }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /product_categories/new
|
||||||
|
# GET /product_categories/new.json
|
||||||
|
def new
|
||||||
|
@product_category = ProductCategory.new
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # new.html.erb
|
||||||
|
format.json { render json: @product_category }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /product_categories/1/edit
|
||||||
|
def edit
|
||||||
|
@product_category = ProductCategory.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /product_categories
|
||||||
|
# POST /product_categories.json
|
||||||
|
def create
|
||||||
|
@product_category = ProductCategory.new(params[:product_category])
|
||||||
|
@product_category.supplier = current_supplier
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @product_category.save
|
||||||
|
format.html { redirect_to [:suppliers, @product_category], notice: t('action.create.successfull', model: ProductCategory.model_name.human) }
|
||||||
|
format.json { render json: @product_category, status: :created, location: @product_category }
|
||||||
|
else
|
||||||
|
format.html { render action: "new" }
|
||||||
|
format.json { render json: @product_category.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PUT /product_categories/1
|
||||||
|
# PUT /product_categories/1.json
|
||||||
|
def update
|
||||||
|
@product_category = ProductCategory.find(params[:id])
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @product_category.update_attributes(params[:product_category])
|
||||||
|
format.html { redirect_to [:suppliers, @product_category], notice: t('action.update.successfull', model: ProductCategory.model_name.human) }
|
||||||
|
format.json { head :no_content }
|
||||||
|
else
|
||||||
|
format.html { render action: "edit" }
|
||||||
|
format.json { render json: @product_category.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /product_categories/1
|
||||||
|
# DELETE /product_categories/1.json
|
||||||
|
def destroy
|
||||||
|
@product_category = ProductCategory.find(params[:id])
|
||||||
|
@product_category.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to suppliers_product_categories_url, notice: t('action.destroy.successfull', model: ProductCategory.model_name.human) }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
module Suppliers
|
||||||
|
class ProductsController < Suppliers::ApplicationController
|
||||||
|
|
||||||
|
# GET /products
|
||||||
|
# GET /products.json
|
||||||
|
def index
|
||||||
|
@products = current_supplier.products
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # index.html.erb
|
||||||
|
format.json { render json: @products }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /products/1
|
||||||
|
# GET /products/1.json
|
||||||
|
def show
|
||||||
|
@product = Product.find(params[:id])
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # show.html.erb
|
||||||
|
format.json { render json: @product }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /products/new
|
||||||
|
# GET /products/new.json
|
||||||
|
def new
|
||||||
|
@product = Product.new
|
||||||
|
@product.product_category_id = params[:product_category_id].presence
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # new.html.erb
|
||||||
|
format.json { render json: @product }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /products/1/edit
|
||||||
|
def edit
|
||||||
|
@product = Product.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /products
|
||||||
|
# POST /products.json
|
||||||
|
def create
|
||||||
|
@product = Product.new(params[:product])
|
||||||
|
@product.supplier = current_supplier
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @product.save
|
||||||
|
format.html { redirect_to [:suppliers, @product], notice: t('action.create.successfull', model: Product.model_name.human) }
|
||||||
|
format.json { render json: @product, status: :created, location: @product }
|
||||||
|
else
|
||||||
|
format.html { render action: "new" }
|
||||||
|
format.json { render json: @product.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PUT /products/1
|
||||||
|
# PUT /products/1.json
|
||||||
|
def update
|
||||||
|
@product = Product.find(params[:id])
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @product.update_attributes(params[:product])
|
||||||
|
format.html { redirect_to [:suppliers, @product], notice: t('action.update.successfull', model: Product.model_name.human) }
|
||||||
|
format.json { head :no_content }
|
||||||
|
else
|
||||||
|
format.html { render action: "edit" }
|
||||||
|
format.json { render json: @product.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /products/1
|
||||||
|
# DELETE /products/1.json
|
||||||
|
def destroy
|
||||||
|
@product = Product.find(params[:id])
|
||||||
|
@product.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to suppliers_products_url, notice: t('action.destroy.successfull', model: Product.model_name.human) }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -82,19 +82,6 @@ class TablesController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /tables/qrcode
|
|
||||||
# GET /tables/qrcode.png
|
|
||||||
# GET /tables/qrcode.svg
|
|
||||||
def qrcode
|
|
||||||
@table = Table.find(params[:id])
|
|
||||||
code = @table.id
|
|
||||||
respond_to do |format|
|
|
||||||
format.html
|
|
||||||
format.svg { render :qrcode => code, :level => :l, :unit => 10 }
|
|
||||||
format.png { render qrcode: code }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_relation_options
|
def set_relation_options
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class UserController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
# POST /user/create_list {table_id: 1234}
|
# POST /user/create_list {table_id: 1234}
|
||||||
|
#DEPRICATED
|
||||||
def create_list
|
def create_list
|
||||||
@table = Table.find(params[:table_id])
|
@table = Table.find(params[:table_id])
|
||||||
if @table.occupied?
|
if @table.occupied?
|
||||||
@@ -17,11 +18,8 @@ class UserController < ApplicationController
|
|||||||
format.json { render json: js_alert(t('messages.table_is_occupied'))}
|
format.json { render json: js_alert(t('messages.table_is_occupied'))}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@list = List.new(table: @table, supplier_id: @table.supplier_id)
|
if @list = List.from_table( @table, current_user )
|
||||||
@list.add_user current_user
|
end
|
||||||
#@list.add_user(current_user)
|
|
||||||
@list.save
|
|
||||||
session[:active_list_id] = @list.id
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to user_list_products_path }
|
format.html { redirect_to user_list_products_path }
|
||||||
format.json { render json: js_notice('table_created')}
|
format.json { render json: js_notice('table_created')}
|
||||||
@@ -31,9 +29,15 @@ class UserController < ApplicationController
|
|||||||
|
|
||||||
def table_info
|
def table_info
|
||||||
@table = Table.find(params[:table_id])
|
@table = Table.find(params[:table_id])
|
||||||
|
res = {}
|
||||||
|
res[:ocupied] = @table.occupied?
|
||||||
|
if list.present?
|
||||||
|
res[:other_supplier] = true if list.supplier_id != @table.supplier_id
|
||||||
|
res[:current_table_id] = list.table_id
|
||||||
|
end
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
render json: {occupied: @table.occupied?}
|
render json: res
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -56,6 +60,22 @@ class UserController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def list_products_for_table
|
||||||
|
@table = Table.find(params[:table_id])
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
render layout: 'phone'
|
||||||
|
end
|
||||||
|
format.json do
|
||||||
|
products = @table.supplier.products
|
||||||
|
products.include_relation(:product_categories)
|
||||||
|
products.sort_by!{|p| p.product_category.try(:position) || 90000}
|
||||||
|
h = products.inject({}){|h, p| n = p.product_category.try(:name) || 'other'; h[n] ||= []; h[n] << p; h}
|
||||||
|
render json: h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# GET /user/current_list.json
|
# GET /user/current_list.json
|
||||||
# Information about the currently active list
|
# Information about the currently active list
|
||||||
# This information includes detailed order information
|
# This information includes detailed order information
|
||||||
@@ -97,7 +117,7 @@ class UserController < ApplicationController
|
|||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
if !list.try(:active?)
|
if !list.try(:active?)
|
||||||
session[:active_list_id] = nil
|
current_user.list_is_closed!
|
||||||
render json: {list_active: false}
|
render json: {list_active: false}
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
@@ -144,8 +164,8 @@ class UserController < ApplicationController
|
|||||||
# GET /user/list_history/:list_id
|
# GET /user/list_history/:list_id
|
||||||
def history_list
|
def history_list
|
||||||
@list = List.find(params[:list_id])
|
@list = List.find(params[:list_id])
|
||||||
if params[:list_closed].present? && session[:active_list_id] == @list.id
|
if params[:list_closed].present? && current_user.active_list_id == @list.id
|
||||||
session[:active_list_id] = nil
|
current_user.list_is_closed!
|
||||||
flash.now[:notice] = t('messages.the_list_has_been_closed', list: List.model_name.human)
|
flash.now[:notice] = t('messages.the_list_has_been_closed', list: List.model_name.human)
|
||||||
end
|
end
|
||||||
redirect_to user_root_path, alert: t('messages.illegal_history_list_attempt') and return unless @list.user_ids.include?(current_user.id)
|
redirect_to user_root_path, alert: t('messages.illegal_history_list_attempt') and return unless @list.user_ids.include?(current_user.id)
|
||||||
@@ -154,7 +174,19 @@ class UserController < ApplicationController
|
|||||||
|
|
||||||
|
|
||||||
def order_selected_products
|
def order_selected_products
|
||||||
@list = list
|
if list.present?
|
||||||
|
@list = list
|
||||||
|
else
|
||||||
|
@table = Table.find(params[:table_id])
|
||||||
|
if @table.occupied?
|
||||||
|
#TODO handle placint order on occupied table
|
||||||
|
else
|
||||||
|
if @list = List.from_table( @table, current_user )
|
||||||
|
else
|
||||||
|
#TODO handle second list creation for user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
redirect_to(root_path, alert: t('messages.cannot_order_on_non_active_list')) and return unless @list.active?
|
redirect_to(root_path, alert: t('messages.cannot_order_on_non_active_list')) and return unless @list.active?
|
||||||
@@ -168,4 +200,14 @@ class UserController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
def move_table
|
||||||
|
return unless list.present?
|
||||||
|
@table = Table.find(params[:table_id])
|
||||||
|
if @table.occupied?
|
||||||
|
render json: {occupied: true}
|
||||||
|
else
|
||||||
|
list.move_to_table @table
|
||||||
|
render json: {occupied: false}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -26,8 +26,28 @@ module ApplicationHelper
|
|||||||
'Qwaiter'
|
'Qwaiter'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Helper for displaying HTML currency values
|
||||||
|
def currency(amount, opts={})
|
||||||
|
amount ||= 0.0
|
||||||
|
amount = amount.to_f
|
||||||
|
#prefix = case company.currency
|
||||||
|
# when 'GBP' then '£ '
|
||||||
|
# when 'USD' then '$ '
|
||||||
|
# else '€ '
|
||||||
|
# end
|
||||||
|
prefix = '€ '
|
||||||
|
return (prefix + ("%.2f" % amount)).html_safe
|
||||||
|
|
||||||
|
# Rails native is ambiguous since is uses translation hashes
|
||||||
|
options = {:unit => '€'}.merge(opts)
|
||||||
|
number_to_currency(amount, options)
|
||||||
|
end
|
||||||
def list_open?
|
def list_open?
|
||||||
session[:active_list_id].present?
|
active_list_id.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def active_list_id
|
||||||
|
current_user.try(:active_list_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def no_content_given(model)
|
def no_content_given(model)
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class Administrator
|
||||||
|
include SimplyStored::Couch
|
||||||
|
include Devise::Orm::SimplyStored
|
||||||
|
devise :database_authenticatable, :rememberable #, :recoverable, :rememberable, :trackable, :registerable
|
||||||
|
end
|
||||||
@@ -8,6 +8,7 @@ class List
|
|||||||
has_many :orders, dependent: :destroy
|
has_many :orders, dependent: :destroy
|
||||||
belongs_to :table
|
belongs_to :table
|
||||||
belongs_to :supplier
|
belongs_to :supplier
|
||||||
|
belongs_to :section
|
||||||
has_and_belongs_to_many :users, storing_keys: true
|
has_and_belongs_to_many :users, storing_keys: true
|
||||||
|
|
||||||
validates :table_id, presence: true
|
validates :table_id, presence: true
|
||||||
@@ -15,6 +16,16 @@ class List
|
|||||||
|
|
||||||
view :by_supplier_id_and_id, key: [:supplier_id, :_id]
|
view :by_supplier_id_and_id, key: [:supplier_id, :_id]
|
||||||
|
|
||||||
|
def self.from_table table, user
|
||||||
|
return if user.has_active_list?
|
||||||
|
list = new table: table, supplier_id: table.supplier_id, section_id: table.section_id
|
||||||
|
list.add_user user
|
||||||
|
list.save
|
||||||
|
user.active_list_id = list.id
|
||||||
|
user.save
|
||||||
|
list
|
||||||
|
end
|
||||||
|
|
||||||
def close!
|
def close!
|
||||||
orders.map(&:close!)
|
orders.map(&:close!)
|
||||||
self.state = 'closed'
|
self.state = 'closed'
|
||||||
@@ -48,6 +59,13 @@ class List
|
|||||||
@order
|
@order
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def move_to_table to_table
|
||||||
|
TableMove.create list: self, from_table_id: table_id, to_table: to_table
|
||||||
|
self.table = to_table
|
||||||
|
self.section_id = to_table.section_id
|
||||||
|
save
|
||||||
|
end
|
||||||
|
|
||||||
def as_json
|
def as_json
|
||||||
super.merge(table_number: table_number)
|
super.merge(table_number: table_number)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class Order
|
|||||||
belongs_to :list
|
belongs_to :list
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :supplier
|
belongs_to :supplier
|
||||||
|
belongs_to :section
|
||||||
|
|
||||||
has_many :product_orders, dependent: :destroy
|
has_many :product_orders, dependent: :destroy
|
||||||
#has_many :products, through: :product_orders
|
#has_many :products, through: :product_orders
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ class ProductCategory
|
|||||||
belongs_to :supplier
|
belongs_to :supplier
|
||||||
has_many :products
|
has_many :products
|
||||||
|
|
||||||
|
attr_protected :supplier_id
|
||||||
|
|
||||||
validates :position, numericality: true
|
validates :position, numericality: true
|
||||||
validates :supplier_id, presence: true
|
validates :supplier_id, presence: true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ class Section
|
|||||||
|
|
||||||
belongs_to :supplier
|
belongs_to :supplier
|
||||||
has_many :tables
|
has_many :tables
|
||||||
|
has_many :lists
|
||||||
|
has_many :orders
|
||||||
|
|
||||||
attr_protected :supplier_id
|
attr_protected :supplier_id
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -23,7 +23,8 @@ class Table
|
|||||||
}|, reduce_function: '_sum'
|
}|, reduce_function: '_sum'
|
||||||
|
|
||||||
def occupied?
|
def occupied?
|
||||||
not self.class.database.view(self.class.active_lists(key: id, reduce: true)).zero?
|
return @is_occupied if instance_variable_defined?(:'@is_occupied')
|
||||||
|
@is_occupied = !self.class.database.view(self.class.active_lists(key: id, reduce: true)).zero?
|
||||||
end
|
end
|
||||||
|
|
||||||
def name
|
def name
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class TableMove
|
||||||
|
include SimplyStored::Couch
|
||||||
|
belongs_to :list
|
||||||
|
belongs_to :from_table, class_name: 'Table'
|
||||||
|
belongs_to :to_table, class_name: 'Table'
|
||||||
|
end
|
||||||
@@ -1,10 +1,21 @@
|
|||||||
class User
|
class User
|
||||||
include SimplyStored::Couch
|
include SimplyStored::Couch
|
||||||
include Devise::Orm::SimplyStored
|
include Devise::Orm::SimplyStored
|
||||||
|
property :active_list_id
|
||||||
|
|
||||||
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable
|
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable
|
||||||
|
|
||||||
has_and_belongs_to_many :lists, storing_keys: false
|
has_and_belongs_to_many :lists, storing_keys: false
|
||||||
has_many :orders
|
has_many :orders
|
||||||
|
|
||||||
validates_uniqueness_of :email
|
validates_uniqueness_of :email
|
||||||
|
|
||||||
|
def list_is_closed!
|
||||||
|
self.active_list_id = nil
|
||||||
|
save
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_active_list?
|
||||||
|
active_list_id.present?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.page-header= title 'Select Qr code'
|
.page-header= title 'Select Qr code'
|
||||||
ul#qr-list
|
ul#qr-list
|
||||||
- for table in @tables
|
- for table in @tables
|
||||||
li= link_to_function image_tag(url_for(qrcode_table_path(table, format: :png))), %|Quser.actions_for_table('#{table.id}')|
|
li= link_to_function image_tag(url_for(table_qr_image_path(table_id: table.id, format: :png))), %|Quser.actions_for_table({table_id: '#{table.id}'})|
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
doctype html
|
||||||
|
html lang="en"
|
||||||
|
head
|
||||||
|
meta charset="utf-8"
|
||||||
|
meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"
|
||||||
|
meta name="viewport" content="width=device-width, initial-scale=1.0"
|
||||||
|
title= content_for?(:title) ? yield(:title) : application_title
|
||||||
|
= csrf_meta_tags
|
||||||
|
|
||||||
|
/! Le HTML5 shim, for IE6-8 support of HTML elements
|
||||||
|
/[if lt IE 9]
|
||||||
|
= javascript_include_tag "http://html5shim.googlecode.com/svn/trunk/html5.js"
|
||||||
|
= stylesheet_link_tag "application", :media => "all"
|
||||||
|
link href="images/apple-touch-icon-144x144.png" rel="apple-touch-icon-precomposed" sizes="144x144"
|
||||||
|
link href="images/apple-touch-icon-114x114.png" rel="apple-touch-icon-precomposed" sizes="114x114"
|
||||||
|
link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72"
|
||||||
|
link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed"
|
||||||
|
link href="images/favicon.ico" rel="shortcut icon"
|
||||||
|
|
||||||
|
body
|
||||||
|
.navbar.navbar-fixed-top
|
||||||
|
.navbar-inner
|
||||||
|
.container
|
||||||
|
a.btn.btn-navbar data-target=".nav-collapse" data-toggle="collapse"
|
||||||
|
span.icon-bar
|
||||||
|
span.icon-bar
|
||||||
|
span.icon-bar
|
||||||
|
a.brand href=root_path = application_title
|
||||||
|
.container.nav-collapse
|
||||||
|
ul.nav
|
||||||
|
li= link_to User.model_name.human_plural, users_path
|
||||||
|
li= link_to Supplier.model_name.human_plural, suppliers_path
|
||||||
|
li= link_to Table.model_name.human_plural, tables_path
|
||||||
|
li= link_to Product.model_name.human_plural, products_path
|
||||||
|
li= link_to List.model_name.human_plural, lists_path
|
||||||
|
li= link_to Order.model_name.human_plural, orders_path
|
||||||
|
li= link_to ProductCategory.model_name.human_plural, product_categories_path
|
||||||
|
|
||||||
|
.container
|
||||||
|
|
||||||
|
.content
|
||||||
|
- if flash[:alert].present?
|
||||||
|
.alert.alert-error
|
||||||
|
a.close data-dismiss="alert" ×
|
||||||
|
div= flash[:alert]
|
||||||
|
- if flash[:notice].present?
|
||||||
|
.alert.alert-success
|
||||||
|
a.close data-dismiss="alert" ×
|
||||||
|
div= flash[:notice]
|
||||||
|
.row
|
||||||
|
.span9
|
||||||
|
= yield
|
||||||
|
.span3
|
||||||
|
.well.sidebar-nav
|
||||||
|
h3= application_title
|
||||||
|
ul.nav.nav-list
|
||||||
|
li.nav-header Links
|
||||||
|
li= link_to "Home", root_path
|
||||||
|
li= link_to "Companytools", 'http://www.companytools.nl/'
|
||||||
|
= yield :sidebar
|
||||||
|
|
||||||
|
footer
|
||||||
|
p © Companytools 2012
|
||||||
|
/!
|
||||||
|
Javascripts
|
||||||
|
\==================================================
|
||||||
|
/! Placed at the end of the document so the pages load faster
|
||||||
|
= javascript_include_tag "application"
|
||||||
|
= yield :footer
|
||||||
@@ -16,8 +16,6 @@ html lang="en"
|
|||||||
link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72"
|
link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72"
|
||||||
link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed"
|
link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed"
|
||||||
link href="images/favicon.ico" rel="shortcut icon"
|
link href="images/favicon.ico" rel="shortcut icon"
|
||||||
javascript:
|
|
||||||
var active_list_id = #{session[:active_list_id] ? "'#{session[:active_list_id]}'" : 'null'};
|
|
||||||
|
|
||||||
body
|
body
|
||||||
.navbar.navbar-fixed-top
|
.navbar.navbar-fixed-top
|
||||||
@@ -30,13 +28,8 @@ html lang="en"
|
|||||||
a.brand href=root_path = application_title
|
a.brand href=root_path = application_title
|
||||||
.container.nav-collapse
|
.container.nav-collapse
|
||||||
ul.nav
|
ul.nav
|
||||||
li= link_to User.model_name.human_plural, users_path
|
li= link_to User.model_name.human_plural, user_root_path
|
||||||
li= link_to Supplier.model_name.human_plural, suppliers_path
|
li= link_to Supplier.model_name.human_plural, supplier_root_path
|
||||||
li= link_to Table.model_name.human_plural, tables_path
|
|
||||||
li= link_to Product.model_name.human_plural, products_path
|
|
||||||
li= link_to List.model_name.human_plural, lists_path
|
|
||||||
li= link_to Order.model_name.human_plural, orders_path
|
|
||||||
li= link_to ProductCategory.model_name.human_plural, product_categories_path
|
|
||||||
|
|
||||||
.container
|
.container
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ html lang="en"
|
|||||||
link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed"
|
link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed"
|
||||||
link href="images/favicon.ico" rel="shortcut icon"
|
link href="images/favicon.ico" rel="shortcut icon"
|
||||||
javascript:
|
javascript:
|
||||||
var active_list_id = #{session[:active_list_id] ? "'#{session[:active_list_id]}'" : 'null'};
|
// Dummy holder when Qmobile object is not supplied by the mobile phone
|
||||||
|
var QMobile = {
|
||||||
|
scanQr: function(){window.location = '/select_qrcode'}
|
||||||
|
}
|
||||||
|
|
||||||
body
|
body
|
||||||
.navbar.navbar-fixed-top
|
.navbar.navbar-fixed-top
|
||||||
@@ -31,8 +34,6 @@ html lang="en"
|
|||||||
a.brand href=user_root_path = application_title
|
a.brand href=user_root_path = application_title
|
||||||
.container.nav-collapse
|
.container.nav-collapse
|
||||||
ul.nav#top-navigation-list
|
ul.nav#top-navigation-list
|
||||||
- if list_open?
|
|
||||||
li= link_to 'Move table', '#'
|
|
||||||
li= link_to 'View history', user_list_history_path
|
li= link_to 'View history', user_list_history_path
|
||||||
|
|
||||||
.container
|
.container
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ html lang="en"
|
|||||||
link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72"
|
link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72"
|
||||||
link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed"
|
link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed"
|
||||||
link href="images/favicon.ico" rel="shortcut icon"
|
link href="images/favicon.ico" rel="shortcut icon"
|
||||||
javascript:
|
|
||||||
var active_list_id = #{session[:active_list_id] ? "'#{session[:active_list_id]}'" : 'null'};
|
|
||||||
|
|
||||||
body
|
body
|
||||||
.navbar.navbar-fixed-top.navbar-inverse
|
.navbar.navbar-fixed-top.navbar-inverse
|
||||||
@@ -32,12 +30,20 @@ html lang="en"
|
|||||||
ul.nav#top-navigation-list
|
ul.nav#top-navigation-list
|
||||||
li= link_to t('supplier.menu.active_orders', orders: Order.model_name.human_plural), supplier_active_orders_path
|
li= link_to t('supplier.menu.active_orders', orders: Order.model_name.human_plural), supplier_active_orders_path
|
||||||
li= link_to t('supplier.menu.active_lists', lists: List.model_name.human_plural), supplier_active_lists_path
|
li= link_to t('supplier.menu.active_lists', lists: List.model_name.human_plural), supplier_active_lists_path
|
||||||
|
li= link_to ProductCategory.model_name.human_plural, suppliers_product_categories_path
|
||||||
|
li= link_to Product.model_name.human_plural, suppliers_products_path
|
||||||
li= link_to Section.model_name.human_plural, suppliers_sections_path
|
li= link_to Section.model_name.human_plural, suppliers_sections_path
|
||||||
li= link_to Table.model_name.human_plural, suppliers_tables_path
|
li= link_to Table.model_name.human_plural, suppliers_tables_path
|
||||||
|
ul.nav.pull-right
|
||||||
|
li.dropdown
|
||||||
|
a.dropdown-toggle href="#" data-toggle="dropdown"
|
||||||
|
= current_supplier.email
|
||||||
|
b.caret
|
||||||
|
ul.dropdown-menu
|
||||||
|
li= link_to 'Logout', destroy_supplier_session_path, method: :delete
|
||||||
.container.nav-collapse
|
.container.nav-collapse
|
||||||
|
|
||||||
.container
|
.container
|
||||||
|
|
||||||
.content
|
.content
|
||||||
- if flash[:alert].present?
|
- if flash[:alert].present?
|
||||||
.alert.alert-error
|
.alert.alert-error
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
.control-group class=(@product_category.errors[:supplier_id].any? ? 'error' : nil)
|
.control-group class=(@product_category.errors[:supplier_id].any? ? 'error' : nil)
|
||||||
= f.label :supplier_id, Supplier.model_name.human, class: 'control-label'
|
= f.label :supplier_id, Supplier.model_name.human, class: 'control-label'
|
||||||
.controls
|
.controls
|
||||||
= f.select :supplier_id, options_for_select(@suppliers.map{|a| [a.name, a.id]}), include_blank: nil
|
= f.collection_select :supplier_id, @suppliers, :id, :name, include_blank: nil
|
||||||
.form-actions
|
.form-actions
|
||||||
= f.submit nil, class: 'btn btn-primary'
|
= f.submit nil, class: 'btn btn-primary'
|
||||||
'
|
'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
- model_class = ProductCategory
|
- model_class = ProductCategory
|
||||||
div.page-header= title :index, model_class
|
.page-header= title :index, model_class
|
||||||
- if @product_categories.any?
|
- if @product_categories.any?
|
||||||
table.table.table-striped
|
table.table.table-striped
|
||||||
thead
|
thead
|
||||||
@@ -7,16 +7,16 @@ div.page-header= title :index, model_class
|
|||||||
th= model_class.human_attribute_name(:name)
|
th= model_class.human_attribute_name(:name)
|
||||||
th= model_class.human_attribute_name(:position)
|
th= model_class.human_attribute_name(:position)
|
||||||
th= Supplier.model_name.human
|
th= Supplier.model_name.human
|
||||||
th= model_class.human_attribute_name(:created_at)
|
th.timestamp= model_class.human_attribute_name(:created_at)
|
||||||
th=t 'helpers.actions'
|
th.actions=t 'helpers.actions'
|
||||||
tbody
|
tbody
|
||||||
- @product_categories.each do |product_category|
|
- @product_categories.each do |product_category|
|
||||||
tr
|
tr
|
||||||
td= link_to product_category.name, product_category
|
td.link= link_to product_category.name, product_category
|
||||||
td= product_category.position
|
td= product_category.position
|
||||||
td= link_to_if product_category.supplier.present?, product_category.supplier.try(:name), product_category.supplier
|
td.link= link_to_if product_category.supplier.present?, product_category.supplier.try(:name), product_category.supplier
|
||||||
td=l product_category.created_at, format: :short
|
td.timestamp=l product_category.created_at, format: :short
|
||||||
td
|
td.actions
|
||||||
= link_to t('helpers.links.edit'), [:edit, product_category], class: 'btn btn-mini'
|
= link_to t('helpers.links.edit'), [:edit, product_category], class: 'btn btn-mini'
|
||||||
'
|
'
|
||||||
= link_to t("helpers.links.destroy"), product_category, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger'
|
= link_to t("helpers.links.destroy"), product_category, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
- model_class = Product
|
- model_class = Product
|
||||||
div.page-header= title :index, model_class
|
.page-header= title :index, model_class
|
||||||
- if @products.any?
|
- if @products.any?
|
||||||
table.table.table-striped
|
table.table.table-striped
|
||||||
thead
|
thead
|
||||||
@@ -9,18 +9,18 @@ div.page-header= title :index, model_class
|
|||||||
th= model_class.human_attribute_name(:price)
|
th= model_class.human_attribute_name(:price)
|
||||||
th= ProductCategory.model_name.human
|
th= ProductCategory.model_name.human
|
||||||
th= Supplier.model_name.human
|
th= Supplier.model_name.human
|
||||||
th= model_class.human_attribute_name(:created_at)
|
th.timestamp= model_class.human_attribute_name(:created_at)
|
||||||
th=t 'helpers.actions'
|
th.actions=t 'helpers.actions'
|
||||||
tbody
|
tbody
|
||||||
- @products.each do |product|
|
- @products.each do |product|
|
||||||
tr
|
tr
|
||||||
td= link_to product.name, product
|
td.link= link_to product.name, product
|
||||||
td= product.code
|
td= product.code
|
||||||
td= product.price
|
td= product.price
|
||||||
td= link_to_if product.product_category.present?, product.product_category.try(:name), product.product_category
|
td.link= link_to_if product.product_category.present?, product.product_category.try(:name), product.product_category
|
||||||
td= link_to_if product.supplier.present?, product.supplier.try(:name), product.supplier
|
td.link= link_to_if product.supplier.present?, product.supplier.try(:name), product.supplier
|
||||||
td=l product.created_at, format: :short
|
td.timestamp=l product.created_at, format: :short
|
||||||
td
|
td.actions
|
||||||
= link_to t('helpers.links.edit'), [:edit, product], class: 'btn btn-mini'
|
= link_to t('helpers.links.edit'), [:edit, product], class: 'btn btn-mini'
|
||||||
'
|
'
|
||||||
= link_to t("helpers.links.destroy"), product, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger'
|
= link_to t("helpers.links.destroy"), product, method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger'
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
= form_for [:suppliers, @product_category], html: {class: 'form-horizontal' } do |f|
|
||||||
|
= render 'error_messages', target: @product_category
|
||||||
|
.control-group class=(@product_category.errors[:name].any? ? 'error' : nil)
|
||||||
|
= f.label :name, class: 'control-label'
|
||||||
|
.controls
|
||||||
|
= f.text_field :name, class: 'text_field'
|
||||||
|
.control-group class=(@product_category.errors[:position].any? ? 'error' : nil)
|
||||||
|
= f.label :position, class: 'control-label'
|
||||||
|
.controls
|
||||||
|
= f.text_field :position, class: 'text_field'
|
||||||
|
.form-actions
|
||||||
|
= f.submit nil, class: 'btn btn-primary'
|
||||||
|
'
|
||||||
|
= link_to t("helpers.links.cancel"), suppliers_product_categories_path, class: 'btn'
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
- model_class = ProductCategory
|
||||||
|
.page-header
|
||||||
|
= title :edit, model_class
|
||||||
|
= render 'form'
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
- model_class = ProductCategory
|
||||||
|
.page-header= title :index, model_class
|
||||||
|
- if @product_categories.any?
|
||||||
|
table.table.table-striped
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th= model_class.human_attribute_name(:name)
|
||||||
|
th= model_class.human_attribute_name(:position)
|
||||||
|
th.timestamp= model_class.human_attribute_name(:created_at)
|
||||||
|
th.actions=t 'helpers.actions'
|
||||||
|
tbody
|
||||||
|
- @product_categories.each do |product_category|
|
||||||
|
tr
|
||||||
|
td.link= link_to product_category.name, [:suppliers, product_category]
|
||||||
|
td= product_category.position
|
||||||
|
td.timestamp=l product_category.created_at, format: :short
|
||||||
|
td.actions
|
||||||
|
= link_to t('helpers.links.edit'), [:edit, :suppliers, product_category], class: 'btn btn-mini'
|
||||||
|
'
|
||||||
|
= link_to t("helpers.links.destroy"), [:suppliers, product_category], method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger'
|
||||||
|
- else
|
||||||
|
= no_content_given model_class
|
||||||
|
= link_to t("helpers.links.new"), new_suppliers_product_category_path, class: 'btn btn-primary'
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
- model_class = ProductCategory
|
||||||
|
.page-header
|
||||||
|
= title :new, model_class
|
||||||
|
= render 'form'
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
- model_class = ProductCategory
|
||||||
|
.page-header= title :show, @product_category
|
||||||
|
|
||||||
|
dl.dl-horizontal.show-list
|
||||||
|
dt= model_class.human_attribute_name(:name)
|
||||||
|
dd= @product_category.name
|
||||||
|
dt= model_class.human_attribute_name(:position)
|
||||||
|
dd= @product_category.position
|
||||||
|
|
||||||
|
.form-actions
|
||||||
|
= link_to t("helpers.links.back"), suppliers_product_categories_path, class: 'btn'
|
||||||
|
'
|
||||||
|
= link_to t('helpers.links.edit'), [:edit, :suppliers, @product_category], class: 'btn'
|
||||||
|
'
|
||||||
|
= link_to t("helpers.links.destroy"), [:suppliers, @product_category], method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-danger'
|
||||||
|
- content_for :row do
|
||||||
|
- @products = @product_category.products
|
||||||
|
= render template: 'suppliers/products/index'
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
= form_for [:suppliers, @product], html: {class: 'form-horizontal' } do |f|
|
||||||
|
= render 'error_messages', target: @product
|
||||||
|
.control-group class=(@product.errors[:name].any? ? 'error' : nil)
|
||||||
|
= f.label :name, class: 'control-label'
|
||||||
|
.controls
|
||||||
|
= f.text_field :name, class: 'text_field'
|
||||||
|
.control-group class=(@product.errors[:code].any? ? 'error' : nil)
|
||||||
|
= f.label :code, class: 'control-label'
|
||||||
|
.controls
|
||||||
|
= f.text_field :code, class: 'text_field'
|
||||||
|
.control-group class=(@product.errors[:price].any? ? 'error' : nil)
|
||||||
|
= f.label :price, class: 'control-label'
|
||||||
|
.controls
|
||||||
|
= f.text_field :price, class: ['text_field', :currency]
|
||||||
|
.control-group class=(@product.errors[:product_category_id].any? ? 'error' : nil)
|
||||||
|
= f.label :product_category_id, ProductCategory.model_name.human, class: 'control-label'
|
||||||
|
.controls
|
||||||
|
= f.collection_select :product_category_id, current_supplier.product_categories, :id, :name, include_blank: ''
|
||||||
|
.form-actions
|
||||||
|
= f.submit nil, class: 'btn btn-primary'
|
||||||
|
'
|
||||||
|
= link_to t("helpers.links.cancel"), suppliers_products_path, class: 'btn'
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
- model_class = Product
|
||||||
|
.page-header
|
||||||
|
= title :edit, model_class
|
||||||
|
= render 'form'
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
- model_class = Product
|
||||||
|
.page-header= title :index, model_class
|
||||||
|
- if @products.any?
|
||||||
|
table.table.table-striped
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th= model_class.human_attribute_name(:name)
|
||||||
|
th= model_class.human_attribute_name(:code)
|
||||||
|
th.currency= model_class.human_attribute_name(:price)
|
||||||
|
th= ProductCategory.model_name.human
|
||||||
|
th.timestamp= model_class.human_attribute_name(:created_at)
|
||||||
|
th.actions=t 'helpers.actions'
|
||||||
|
tbody
|
||||||
|
- @products.each do |product|
|
||||||
|
tr
|
||||||
|
td.link= link_to product.name, product
|
||||||
|
td= product.code
|
||||||
|
td.currency=currency product.price
|
||||||
|
td.link= link_to_if product.product_category.present?, product.product_category.try(:name), [:suppliers, product.product_category]
|
||||||
|
td.timestamp=l product.created_at, format: :short
|
||||||
|
td.actions
|
||||||
|
= link_to t('helpers.links.edit'), [:edit, :suppliers, product], class: 'btn btn-mini'
|
||||||
|
'
|
||||||
|
= link_to t("helpers.links.destroy"), [:suppliers, product], method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger'
|
||||||
|
- else
|
||||||
|
= no_content_given model_class
|
||||||
|
= link_to t("helpers.links.new"), new_suppliers_product_path(product_category_id: @product_category.try(:id)), class: 'btn btn-primary'
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
- model_class = Product
|
||||||
|
.page-header
|
||||||
|
= title :new, model_class
|
||||||
|
= render 'form'
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
- model_class = Product
|
||||||
|
.page-header= title :show, @product
|
||||||
|
|
||||||
|
dl.dl-horizontal.show-list
|
||||||
|
dt= model_class.human_attribute_name(:name)
|
||||||
|
dd= @product.name
|
||||||
|
dt= model_class.human_attribute_name(:code)
|
||||||
|
dd= @product.code
|
||||||
|
dt= model_class.human_attribute_name(:price)
|
||||||
|
dd= @product.price
|
||||||
|
- if @product.product_category.present?
|
||||||
|
dt= ProductCategory.model_name.human
|
||||||
|
dd= link_to @product.product_category.name, @product.product_category
|
||||||
|
|
||||||
|
.form-actions
|
||||||
|
= link_to t("helpers.links.back"), suppliers_products_path, class: 'btn'
|
||||||
|
'
|
||||||
|
= link_to t('helpers.links.edit'), [:edit, :suppliers, @product], class: 'btn'
|
||||||
|
'
|
||||||
|
= link_to t("helpers.links.destroy"), [:suppliers, @product], method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-danger'
|
||||||
@@ -16,7 +16,8 @@
|
|||||||
- for table in @section.tables
|
- for table in @section.tables
|
||||||
.section-table.hide{ id="section-table-#{table.id}" data-position-x=table.position_x data-position-y=table.position_y data-table-id=table.id}
|
.section-table.hide{ id="section-table-#{table.id}" data-position-x=table.position_x data-position-y=table.position_y data-table-id=table.id}
|
||||||
.pull-right.action-button-container
|
.pull-right.action-button-container
|
||||||
= link_to table.number, [:suppliers, table], class: 'btn btn-mini table-number'
|
= link_to :i, [:suppliers, table], class: 'btn btn-mini table-link'
|
||||||
|
.table-number = table.number
|
||||||
.span3
|
.span3
|
||||||
h3= t('table.has_no_section')
|
h3= t('table.has_no_section')
|
||||||
.well.section-tables-container.section-tables-inactive
|
.well.section-tables-container.section-tables-inactive
|
||||||
@@ -24,7 +25,8 @@
|
|||||||
.section-table{ id="section-table-#{table.id}" data-position-x=table.position_x data-position-y=table.position_y data-table-id=table.id}
|
.section-table{ id="section-table-#{table.id}" data-position-x=table.position_x data-position-y=table.position_y data-table-id=table.id}
|
||||||
.pull-right.action-button-container
|
.pull-right.action-button-container
|
||||||
button.btn.btn-primary.btn-mini onClick="Qsupplier.move_table_to_active_section('#{table.id}')" +
|
button.btn.btn-primary.btn-mini onClick="Qsupplier.move_table_to_active_section('#{table.id}')" +
|
||||||
= link_to table.number, [:suppliers, table], class: 'btn btn-mini table-number'
|
= link_to :i, [:suppliers, table], class: 'btn btn-mini table-link'
|
||||||
|
.table-number = table.number
|
||||||
.clearfix
|
.clearfix
|
||||||
- content_for :footer do
|
- content_for :footer do
|
||||||
javascript:
|
javascript:
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
ul.nav.nav-tabs.nav-stacked
|
ul.nav.nav-tabs.nav-stacked
|
||||||
|
li
|
||||||
|
button.btn.btn-primary onClick="QMobile.scanQr()" Scan Qr
|
||||||
- if list_open?
|
- if list_open?
|
||||||
li= link_to 'Place order', user_list_products_path(supplier_id: active_list.supplier.id)
|
li= link_to 'Place order', user_list_products_path
|
||||||
li= link_to 'Active list', user_active_list_path
|
li= link_to 'Show active list', user_active_list_path
|
||||||
- else
|
|
||||||
li= link_to 'Join table with Qr scan', '/select_qrcode'
|
|
||||||
li
|
|
||||||
button.btn.btn-primary onClick="QMobile.scanQr()" Scan Qr
|
|
||||||
li= link_to 'Subscribe to list', '#'
|
li= link_to 'Subscribe to list', '#'
|
||||||
li= link_to 'Check out menu', '#'
|
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
.page-header= title 'User list history'
|
.page-header= title 'User list history'
|
||||||
p Todo
|
ul
|
||||||
|
- for list in @lists
|
||||||
|
li= link_to l(list.created_at, format: :short), user_history_list_path(list_id: list.id)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
span#list-needs-help-button
|
span#list-needs-help-button
|
||||||
table#products-table.table.table-striped.table-hover
|
table#products-table.table.table-striped.table-hover
|
||||||
tbody
|
tbody
|
||||||
-# content_for :sidebar do
|
|
||||||
table#active-order-table.table.table-striped.hide
|
table#active-order-table.table.table-striped.hide
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
.page-header
|
||||||
|
h4= t('user.show_products.title', products: Product.model_name.human_plural)
|
||||||
|
table#products-table.table.table-striped.table-hover
|
||||||
|
tbody
|
||||||
|
table#active-order-table.table.table-striped.hide
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th Product
|
||||||
|
th #
|
||||||
|
th.currency Total
|
||||||
|
th
|
||||||
|
tbody
|
||||||
|
tfoot
|
||||||
|
tr
|
||||||
|
td colspan=2
|
||||||
|
button class="btn btn-primary" onClick="Quser.order_selected_products({table_id: '#{@table.id}'})" Bestellen
|
||||||
|
|
|
||||||
|
button class="btn btn btn-warning" onClick="Qrammer.clear_active_list()" Clear
|
||||||
|
td.currency
|
||||||
|
strong#active-order-total
|
||||||
|
td
|
||||||
|
- content_for :footer do
|
||||||
|
javascript:
|
||||||
|
jQuery(function(){
|
||||||
|
Quser.load_table_products('#{@table.id}', #{@table.occupied? ? 'true' : 'false'});
|
||||||
|
})
|
||||||
|
|
||||||
@@ -77,3 +77,4 @@ module Qrammer
|
|||||||
config.assets.version = '1.0'
|
config.assets.version = '1.0'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
require 'rqrcode-rails3'
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ Qrammer::Application.configure do
|
|||||||
|
|
||||||
# Do not compress assets
|
# Do not compress assets
|
||||||
config.assets.compress = false
|
config.assets.compress = false
|
||||||
|
config.assets.logger = Logger.new('/dev/null')
|
||||||
|
|
||||||
# Expands the lines which load the assets
|
# Expands the lines which load the assets
|
||||||
config.assets.debug = true
|
config.assets.debug = true
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ Devise.setup do |config|
|
|||||||
# Configure sign_out behavior.
|
# Configure sign_out behavior.
|
||||||
# Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
|
# Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
|
||||||
# The default is true, which means any logout action will sign out all active scopes.
|
# The default is true, which means any logout action will sign out all active scopes.
|
||||||
# config.sign_out_all_scopes = true
|
config.sign_out_all_scopes = false
|
||||||
|
|
||||||
# ==> Navigation configuration
|
# ==> Navigation configuration
|
||||||
# Lists the formats that should be treated as navigational. Formats like
|
# Lists the formats that should be treated as navigational. Formats like
|
||||||
@@ -205,7 +205,7 @@ Devise.setup do |config|
|
|||||||
# config.navigational_formats = ["*/*", :html]
|
# config.navigational_formats = ["*/*", :html]
|
||||||
|
|
||||||
# The default HTTP method used to sign out a resource. Default is :delete.
|
# The default HTTP method used to sign out a resource. Default is :delete.
|
||||||
config.sign_out_via = :delete
|
config.sign_out_via = [:delete, :get]
|
||||||
|
|
||||||
# ==> OmniAuth
|
# ==> OmniAuth
|
||||||
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||||
|
|||||||
+13
-8
@@ -1,13 +1,11 @@
|
|||||||
Qrammer::Application.routes.draw do
|
Qrammer::Application.routes.draw do
|
||||||
devise_for :users
|
devise_for :users
|
||||||
devise_for :suppliers
|
devise_for :suppliers
|
||||||
authenticate :supplier do
|
devise_for :administrators
|
||||||
|
|
||||||
|
#authenticate :administrator do
|
||||||
resources :users
|
resources :users
|
||||||
resources :tables do
|
resources :tables
|
||||||
member do
|
|
||||||
get :qrcode
|
|
||||||
end
|
|
||||||
end
|
|
||||||
resources :orders do
|
resources :orders do
|
||||||
member do
|
member do
|
||||||
post :is_being_processed
|
post :is_being_processed
|
||||||
@@ -18,7 +16,7 @@ Qrammer::Application.routes.draw do
|
|||||||
resources :lists
|
resources :lists
|
||||||
resources :products
|
resources :products
|
||||||
resources :product_categories
|
resources :product_categories
|
||||||
end
|
#end
|
||||||
|
|
||||||
get '/supplier' => 'supplier#home', as: :supplier_root
|
get '/supplier' => 'supplier#home', as: :supplier_root
|
||||||
get '/supplier/active_orders' => 'supplier#active_orders', as: :supplier_active_orders
|
get '/supplier/active_orders' => 'supplier#active_orders', as: :supplier_active_orders
|
||||||
@@ -38,9 +36,11 @@ Qrammer::Application.routes.draw do
|
|||||||
post '/user/list_needs_payment' => 'user#list_needs_payment', as: :user_list_needs_payment
|
post '/user/list_needs_payment' => 'user#list_needs_payment', as: :user_list_needs_payment
|
||||||
match '/user/create_list' => 'user#create_list', as: :user_create_list
|
match '/user/create_list' => 'user#create_list', as: :user_create_list
|
||||||
get '/user/list_products' => 'user#list_products', as: :user_list_products
|
get '/user/list_products' => 'user#list_products', as: :user_list_products
|
||||||
|
get '/user/list_products_for_table' => 'user#list_products_for_table', as: :user_list_products_for_table
|
||||||
match '/user/list_history' => 'user#list_history', as: :user_list_history
|
match '/user/list_history' => 'user#list_history', as: :user_list_history
|
||||||
match '/user/list_history/:list_id' => 'user#history_list', as: :user_history_list
|
match '/user/list_history/:list_id' => 'user#history_list', as: :user_history_list
|
||||||
post '/user/order_selected_products' => 'user#order_selected_products', as: :user_order_selected_products
|
post '/user/order_selected_products' => 'user#order_selected_products', as: :user_order_selected_products
|
||||||
|
post '/user/move_table' => 'user#move_table', as: :user_move_table
|
||||||
get '/user/table_info' => 'user#table_info', as: :user_table_info
|
get '/user/table_info' => 'user#table_info', as: :user_table_info
|
||||||
|
|
||||||
match '/show_products' => 'dashboard#show_products', as: :user_products
|
match '/show_products' => 'dashboard#show_products', as: :user_products
|
||||||
@@ -48,10 +48,15 @@ Qrammer::Application.routes.draw do
|
|||||||
namespace :suppliers, path: '/supplier' do
|
namespace :suppliers, path: '/supplier' do
|
||||||
resources :sections
|
resources :sections
|
||||||
resources :tables
|
resources :tables
|
||||||
|
resources :products
|
||||||
|
resources :product_categories
|
||||||
root to: 'sections#index'
|
root to: 'sections#index'
|
||||||
end
|
end
|
||||||
|
|
||||||
match "/:action", controller: 'dashboard'
|
#DEMO & DEVELOPMENT
|
||||||
|
get '/select_qrcode' => 'dashboard#select_qrcode'
|
||||||
|
get '/table_qr_image' => 'dashboard#table_qr_image', as: :table_qr_image
|
||||||
|
#match "/:action", controller: 'dashboard'
|
||||||
|
|
||||||
# The priority is based upon order of creation:
|
# The priority is based upon order of creation:
|
||||||
# first created -> highest priority.
|
# first created -> highest priority.
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
require 'action_controller'
|
||||||
|
require 'rqrcode'
|
||||||
|
require 'rqrcode-rails3/size_calculator.rb'
|
||||||
|
require 'rqrcode-rails3/renderers/svg.rb'
|
||||||
|
|
||||||
|
module RQRCode
|
||||||
|
Mime::Type.register "image/svg+xml", :svg unless Mime::Type.lookup_by_extension(:svg)
|
||||||
|
Mime::Type.register "image/png", :png unless Mime::Type.lookup_by_extension(:png)
|
||||||
|
|
||||||
|
extend SizeCalculator
|
||||||
|
|
||||||
|
ActionController::Renderers.add :qrcode do |string, options|
|
||||||
|
format = self.request.format.symbol
|
||||||
|
size = options[:size] || RQRCode.minimum_qr_size_from_string(string)
|
||||||
|
level = options[:level] || :h
|
||||||
|
|
||||||
|
qrcode = RQRCode::QRCode.new(string, :size => size, :level => level)
|
||||||
|
svg = RQRCode::Renderers::SVG::render(qrcode, options)
|
||||||
|
|
||||||
|
data = \
|
||||||
|
if format == :png
|
||||||
|
image = MiniMagick::Image.read(svg) { |i| i.format "svg" }
|
||||||
|
image.format "png"
|
||||||
|
png = image.to_blob
|
||||||
|
else
|
||||||
|
svg
|
||||||
|
end
|
||||||
|
|
||||||
|
self.response_body = render_to_string(:text => data, :template => nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="318.89764"
|
||||||
|
height="318.89764"
|
||||||
|
id="svg2991"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.2 r9819"
|
||||||
|
sodipodi:docname="table_qr_image.svg">
|
||||||
|
<defs
|
||||||
|
id="defs3">
|
||||||
|
<filter
|
||||||
|
id="filter3789"
|
||||||
|
inkscape:label="Cutout"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Shadows and Glows"
|
||||||
|
inkscape:menu-tooltip="Drop shadow under the cut-out of the shape"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feGaussianBlur
|
||||||
|
id="feGaussianBlur3791"
|
||||||
|
in="SourceAlpha"
|
||||||
|
stdDeviation="4.2" />
|
||||||
|
<feOffset
|
||||||
|
id="feOffset3793"
|
||||||
|
dy="5"
|
||||||
|
dx="5"
|
||||||
|
result="result91" />
|
||||||
|
<feComposite
|
||||||
|
id="feComposite3795"
|
||||||
|
in2="result91"
|
||||||
|
operator="out"
|
||||||
|
in="SourceGraphic" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.3773478"
|
||||||
|
inkscape:cx="107.03459"
|
||||||
|
inkscape:cy="78.51279"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
units="mm"
|
||||||
|
inkscape:window-width="1440"
|
||||||
|
inkscape:window-height="856"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata2995">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,141.73227)">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:semi-expanded;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffb213;fill-opacity:1;stroke:none;font-family:BankGothic Md BT;-inkscape-font-specification:BankGothic Md BT Semi-Expanded"
|
||||||
|
x="80.589668"
|
||||||
|
y="-90.740822"
|
||||||
|
id="text4695"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4697"
|
||||||
|
x="80.589668"
|
||||||
|
y="-90.740822">Qwaiter</tspan></text>
|
||||||
|
<g
|
||||||
|
id="g3838"
|
||||||
|
transform="matrix(0.49177687,0,0,0.49177687,49.419301,-77.511451)">#qrcode
|
||||||
|
</g>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||||
|
x="277.10553"
|
||||||
|
y="160.40939"
|
||||||
|
id="text3799"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3801"
|
||||||
|
x="277.10553"
|
||||||
|
y="160.40939">#table_number</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,50 @@
|
|||||||
|
module RQRCode
|
||||||
|
module Renderers
|
||||||
|
class SVG
|
||||||
|
class << self
|
||||||
|
# Render the SVG from the qrcode string provided from the RQRCode gem
|
||||||
|
# Options:
|
||||||
|
# offset - Padding around the QR Code (e.g. 10)
|
||||||
|
# unit - How many pixels per module (Default: 11)
|
||||||
|
# fill - Background color (e.g "ffffff" or :white)
|
||||||
|
# color - Foreground color for the code (e.g. "000000" or :black)
|
||||||
|
|
||||||
|
def render(qrcode, options={})
|
||||||
|
offset = options[:offset].to_i || 0
|
||||||
|
color = options[:color] || "000"
|
||||||
|
unit = options[:unit] || 11
|
||||||
|
|
||||||
|
# height and width dependent on offset and QR complexity
|
||||||
|
dimension = (qrcode.module_count*unit) + (2*offset)
|
||||||
|
|
||||||
|
xml_tag = %{<?xml version="1.0" standalone="yes"?>}
|
||||||
|
open_tag = %{<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="#{dimension}" height="#{dimension}">}
|
||||||
|
close_tag = "</svg>"
|
||||||
|
|
||||||
|
result = []
|
||||||
|
qrcode.modules.each_index do |c|
|
||||||
|
tmp = []
|
||||||
|
qrcode.modules.each_index do |r|
|
||||||
|
y = c*unit + offset
|
||||||
|
x = r*unit + offset
|
||||||
|
|
||||||
|
next unless qrcode.is_dark(c, r)
|
||||||
|
tmp << %{<rect width="#{unit}" height="#{unit}" x="#{x}" y="#{y}" style="fill:##{color}"/>}
|
||||||
|
end
|
||||||
|
result << tmp.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
if options[:fill]
|
||||||
|
result.unshift %{<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{options[:fill]}"/>}
|
||||||
|
end
|
||||||
|
|
||||||
|
svg = [xml_tag, open_tag, result, close_tag].flatten.join("\n")
|
||||||
|
svg = File.read(File.expand_path('../../qr_container.svg', __FILE__))
|
||||||
|
svg.gsub!(/#table_number/, options[:table_number].to_s)
|
||||||
|
svg.gsub!(/#qrcode/, result.join("\n"))
|
||||||
|
svg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
module RQRCode
|
||||||
|
module SizeCalculator
|
||||||
|
# size - seems to follow this logic
|
||||||
|
# # | input | modules
|
||||||
|
# | size | created
|
||||||
|
#-------|-------|--------
|
||||||
|
# 1 | 7 | 21
|
||||||
|
# 2 | 14 | 25 (+4)
|
||||||
|
# 3 | 24 | 29 -
|
||||||
|
# 4 | 34 | 33 -
|
||||||
|
# 5 | 44 | 37 -
|
||||||
|
# 6 | 58 | 41 -
|
||||||
|
# 7 | 64 | 45 -
|
||||||
|
# 8 | 84 | 49 -
|
||||||
|
# 9 | 98 | 53 -
|
||||||
|
# 10 | 119 | 57 -
|
||||||
|
# 11 | 137 | 61 -
|
||||||
|
# 12 | 155 | 65 -
|
||||||
|
# 13 | 177 | 69 -
|
||||||
|
# 14 | 194 | 73 -
|
||||||
|
|
||||||
|
QR_CHAR_SIZE_VS_SIZE = [7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137, 155, 177, 194]
|
||||||
|
|
||||||
|
def minimum_qr_size_from_string(string)
|
||||||
|
QR_CHAR_SIZE_VS_SIZE.each_with_index do |size, index|
|
||||||
|
return (index + 1) if string.size < size
|
||||||
|
end
|
||||||
|
|
||||||
|
# If it's particularly big, we'll try and create codes until it accepts
|
||||||
|
i = QR_CHAR_SIZE_VS_SIZE.size
|
||||||
|
begin
|
||||||
|
i += 1
|
||||||
|
RQRCode::QRCode.new(string, :size => i)
|
||||||
|
return i
|
||||||
|
rescue RQRCode::QRCodeRunTimeError
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -2,6 +2,18 @@ Stories:
|
|||||||
- Person moves to different table
|
- Person moves to different table
|
||||||
- Person tries to create list on occupied table
|
- Person tries to create list on occupied table
|
||||||
- Person walks away without paying
|
- Person walks away without paying
|
||||||
|
- Person checks out menu through qr scan
|
||||||
|
- Other persion occupies the table by placing an order
|
||||||
|
- Person tries to order something
|
||||||
|
-> Is informed that the table is not occupied
|
||||||
|
-> redirect to user_root_path
|
||||||
|
- Person1 check out the products by scanning the Qr of an empty table
|
||||||
|
- Person2 checks out the products by scanning the Qr of the same table
|
||||||
|
- Person2 places order and gets the list
|
||||||
|
- Person has an active list and creates an order
|
||||||
|
- Supplier closes the list
|
||||||
|
- Person submits order
|
||||||
|
-> Cannot orde on closed list
|
||||||
|
|
||||||
Person actions:
|
Person actions:
|
||||||
When list is open:
|
When list is open:
|
||||||
@@ -42,3 +54,21 @@ Wireless wachtwoord via qr code
|
|||||||
|
|
||||||
|
|
||||||
handle closed list on list update for user list
|
handle closed list on list update for user list
|
||||||
|
|
||||||
|
Scan qr button:
|
||||||
|
If table is not occupied:
|
||||||
|
- if there is an open list
|
||||||
|
- if the scan is of the same supplier
|
||||||
|
- Offer to move table
|
||||||
|
- else
|
||||||
|
- Cannot perform action with open list
|
||||||
|
- else
|
||||||
|
View menu direct
|
||||||
|
- When order is placed:
|
||||||
|
- create list
|
||||||
|
- add order to list
|
||||||
|
- table is assigned to person (occupied)
|
||||||
|
If table is occupied:
|
||||||
|
- Offer to Join
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user