Save progress

This commit is contained in:
2014-03-30 15:55:22 +02:00
parent e179f6e582
commit 013a41b9f6
71 changed files with 1699 additions and 107 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ group :assets do
gem 'coffee-rails' #, '~> 3.2.1' gem 'coffee-rails' #, '~> 3.2.1'
#gem 'twitter-bootstrap-rails' #gem 'twitter-bootstrap-rails'
gem 'bootstrap-sass', '~>2.3' gem 'bootstrap-sass', '~>2.3'
#gem 'bourbon' gem 'bourbon'
gem 'compass-rails' gem 'compass-rails'
gem 'js-routes' gem 'js-routes'
gem "font-awesome-rails" gem "font-awesome-rails"
+1
View File
@@ -392,6 +392,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
active_decorator active_decorator
bootstrap-sass (~> 2.3) bootstrap-sass (~> 2.3)
bourbon
capybara capybara
capybara-webkit capybara-webkit
cmtool! cmtool!
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

@@ -3,19 +3,26 @@ Qsupplier.App.Order = DS.Model.extend
state: attr('string') state: attr('string')
list: DS.belongsTo('list') list: DS.belongsTo('list')
price: attr('number') price: attr('number')
product_orders: attr()
section: DS.belongsTo('section') section: DS.belongsTo('section')
section_id: attr('string') section_id: attr('string')
product_orders: DS.hasMany('product_order')
active: (-> @get('state') == 'active').property('state') active: (-> @get('state') == 'active').property('state')
delivered: (-> @get('state') == 'delivered').property('state') delivered: (-> @get('state') == 'delivered').property('state')
placed: (-> @get('state') == 'placed').property('state') placed: (-> @get('state') == 'placed').property('state')
needs_supplier_attention: (-> @get('state') == 'placed' || @get('state') == 'active').property('state') needs_supplier_attention: (-> @get('state') == 'placed' || @get('state') == 'active').property('state')
display: (-> #display: (->
return '' unless @get('product_orders') #return '' unless @get('product_orders')
@get('product_orders').map((po)-> "#{po.product_name} (#{po.quantity})").join(',') #@get('product_orders').map((po)-> "#{po.product_name} (#{po.quantity})").join(',')
).property('product_orders') #).property('product_orders')
markClosed: -> markClosed: ->
@set 'state', 'closed' @set 'state', 'closed'
total: (->
@get('product_orders').getEach('total').reduce(((sum, total) -> sum + total), 0)
).property('product_orders.@each.quantity', 'product_orders.@each.product.@each.price')
display: (->
@get('product_orders').map((po) -> "#{po.get('quantity')} x #{po.get('product.name')}").join(', ')
).property('product_orders.@each.quantity', 'product_orders.@each.product.@each.name')
@@ -1,3 +1,6 @@
attr = DS.attr attr = DS.attr
Qsupplier.App.Product = DS.Model.extend Qsupplier.App.Product = DS.Model.extend
order: DS.belongsTo('order') name: attr 'string'
price: attr 'number'
product_category: DS.belongsTo('product_category')
product_orders: DS.hasMany('product_order')
@@ -0,0 +1,4 @@
attr = DS.attr
Qsupplier.App.ProductCategory = DS.Model.extend
name: attr('string')
products: DS.hasMany('product')
@@ -0,0 +1,8 @@
attr = DS.attr
Qsupplier.App.ProductOrder = DS.Model.extend
quantity: attr 'number', defaultValue: 1
product: DS.belongsTo('product')
order: DS.belongsTo('order')
increment: ->
@set('quantity', @get('quantity') + 1)
total: (-> @get('quantity') * @get('product.price')).property('quantity', 'product.price')
@@ -0,0 +1,3 @@
Qsupplier.App.ApplicationRoute = Ember.Route.extend
setupController: (controller)->
controller.set 'product_categories', @store.find('product_category')
@@ -3,6 +3,13 @@ DS.RESTAdapter.reopen
namespace: 'supplier' namespace: 'supplier'
Qsupplier.App.ApplicationSerializer = DS.ActiveModelSerializer Qsupplier.App.ApplicationSerializer = DS.ActiveModelSerializer
Qsupplier.App.CustomAdapter = DS.RESTAdapter.extend
# user underscored paths
pathForType: (type)->
decamelized = Ember.String.decamelize(type)
Ember.String.pluralize(decamelized)
Qsupplier.App.Store = DS.Store.extend Qsupplier.App.Store = DS.Store.extend
revision: 13 revision: 13
adapter: DS.RESTAdapter adapter: Qsupplier.App.CustomAdapter
@@ -2,7 +2,7 @@ td {{view.content.display}}
td.numeric.table_number td.numeric.table_number
view Qsupplier.App.ActiveOrderTableNumberView contextBinding=view.content view Qsupplier.App.ActiveOrderTableNumberView contextBinding=view.content
td.section_title {{view.content.section.title}} td.section_title {{view.content.section.title}}
td.currency {{currency view.content.price }} td.currency {{currency view.content.total }}
td.actions td.actions
if view.content.placed if view.content.placed
button.btn.btn-success{ action markOrderActive view.content.id} {{t 'order.being_processed'}} button.btn.btn-success{ action markOrderActive view.content.id} {{t 'order.being_processed'}}
@@ -15,7 +15,7 @@ div class="table-actions table-actions-#{unbound table.id}"
a href="suppliers_table_path(@table)" {{t 'section.tables_view.table_actions.got_to_table'}} a href="suppliers_table_path(@table)" {{t 'section.tables_view.table_actions.got_to_table'}}
each user in table.active_list.users each user in table.active_list.users
img src="http://graph.facebook.com/#{user.uid}/picture?type=square" img src="http://graph.facebook.com/#{user.uid}/picture?type=square"
if editmode_beta if editmode
.table-settings .table-settings
select select
option Round option Round
@@ -55,15 +55,16 @@
setTranslations() setTranslations()
@setTranslations = (selector) -> @setTranslations = (selector) ->
list = $("#top-navigation-list") #list = $("#top-navigation-list")
list.find(".locale").show() selector = $( selector || document)
list.find(".locale-" + $locale).hide() selector.find(".locale-select").show()
selector.find(".locale-select-" + $locale).hide()
moment.lang $locale moment.lang $locale
if selector if selector
$(selector).find("[data-t]").each -> selector.find("[data-t]").each ->
$(this).html t($(this).data("t"), $(this).data("tAttributes")) $(this).html t($(this).data("t"), $(this).data("tAttributes"))
$(selector).find("*[data-time]").each -> selector.find("*[data-time]").each ->
$(this).text moment($(this).data("time")).format($(this).data("timeFormat") or "dd D MMM HH:MM") $(this).text moment($(this).data("time")).format($(this).data("timeFormat") or "dd D MMM HH:MM")
else else
@@ -17,7 +17,26 @@ App.ApplicationController = Ember.Controller.extend
list_needs_help: -> @set 'list.needs_help', true # incoming from other users list_needs_help: -> @set 'list.needs_help', true # incoming from other users
list_is_paid: -> @set 'list.needs_payment', false list_is_paid: -> @set 'list.needs_payment', false
list_needs_payment: -> @set 'list.needs_payment', true # incoming from other users list_needs_payment: -> @set 'list.needs_payment', true # incoming from other users
list_closed: -> @set 'list', null
join_request_approved: (data)->
@setCurrentList -> @transitionToRoute('active_list')
#getProducts: (options = {})-> #getProducts: (options = {})->
#@store.find('product_category', options).then (product_categories)=> #@store.find('product_category', options).then (product_categories)=>
#@controllerFor('list_products').set 'model', product_categories #@controllerFor('list_products').set 'model', product_categories
setCurrentList: (callback)->
success = (list)=>
#@store.find('list', 'current').deleteRecord() # gets not replaced, buty stays as dummy
# A list record with id current and with the content of the returned list is created
# at the moment remove the dummy list, this should be resolved by Ember eventually
if error_list = @store.all('list').findBy('id', 'current')
error_list.eraseRecord()
@set 'list', list
@controllerFor('active_list').set('model', list)
callback.call(@) if callback
error = (jqXHR)=>
# if jqXHR.status == 404 officially, now assume close list on error
#@redirect_to 'index', message: 'the_list_has_been_closed'
@set 'list', null
@store.find('list', 'current').then(success, error)
@@ -5,16 +5,18 @@ App.ProductOrdersController = Ember.ArrayController.extend
).property('model.@each.quantity') ).property('model.@each.quantity')
actions: actions:
clearProductOrders: -> clearProductOrders: ->
@store.all('product_order').toArray().invoke 'unloadRecord' #TODO: make clearing of unpersisted product orders
@store.all('product_order').toArray().invoke 'eraseRecord'
orderProducts: -> orderProducts: ->
order = @store.createRecord('order', list: @get('controllers.application.list')) order = @store.createRecord('order', list: @get('controllers.application.list'))
new_product_orders = @store.all('product_order').filterProperty('order', null) new_product_orders = @store.all('product_order').filterProperty('order', null)
order.get('product_orders').pushObjects(new_product_orders) order.get('product_orders').pushObjects(new_product_orders)
order.save().then -> order.save().then (response)=>
# The new versions will be returned in the json response debugger
#new_product_orders.invoke 'rollback' new_product_orders.invoke 'eraseRecord'
#new_product_orders.invoke 'transitionTo', 'loaded.saved' .error (a,b,c)=>
new_product_orders.invoke 'deleteRecord' d=a
debugger
@transitionToRoute 'active_list' @transitionToRoute 'active_list'
#orders = @store.all('product_order').toArray() #orders = @store.all('product_order').toArray()
@@ -31,4 +33,4 @@ App.ProductOrdersController = Ember.ArrayController.extend
#orders.invoke 'unloadRecord' #orders.invoke 'unloadRecord'
removeProductOrder: (product_order)-> removeProductOrder: (product_order)->
product_order.unloadRecord() product_order.eraseRecord()
@@ -7,10 +7,10 @@ App.SelectQrcodeController = Ember.Controller.extend
if res.current_table_id if res.current_table_id
if res.other_supplier if res.other_supplier
@redirect_to 'user_root', message: 'table_is_from_other_supplier' @redirect_to 'user_root', message: 'table_is_from_other_supplier'
else if res.current_table_id == table.table_id else if res.current_table_id == table._id
#nothing has changed, show product list #nothing has changed, show product list
@redirect_to 'list_products' @redirect_to 'list_products'
else if res.current_table_id != table.table_id else if res.current_table_id != table._id
if res.occupied if res.occupied
@redirect_to 'user_root', message: 'table_is_occupied' @redirect_to 'user_root', message: 'table_is_occupied'
else if res.reserved else if res.reserved
@@ -35,9 +35,9 @@ App.SelectQrcodeController = Ember.Controller.extend
@redirect_to 'list_products' @redirect_to 'list_products'
else else
if res.occupied if res.occupied
@redirect_to 'join_occupied_table', {table_id: table.table_id} @redirect_to 'join_occupied_table', {table_id: table._id}
else if res.supplier_closed else if res.supplier_closed
@redirect_to 'user_root', {message: 'supplier_is_closed'} @redirect_to 'user_root', {message: 'supplier_is_closed'}
else else
#$.post(data_host + '/user/create_list.json', {table_id: table.table_id}, (res)-> Quser.handle_response(res)) #$.post(data_host + '/user/create_list.json', {table_id: table._id}, (res)-> Quser.handle_response(res))
@redirect_to 'list_products_for_table', {table_id: table.table_id} @redirect_to 'table', table._id, a: 3
@@ -0,0 +1,28 @@
App.TableController = Ember.ObjectController.extend
join_request_sent: false
tableCanTakeOrders: (->
return false unless @get('supplier.can_take_orders')
list = @get('controllers.application.list')
if list
return false unless list.get('supplier.id') == @get('supplier.id')
return false unless list.get('table.id') == @get('model.id')
true
else
# no list and open supplier
if @get('model.occupied') then false else true
).property('controllers.application.list.id', 'supplier.can_take_orders', 'model.occupied', 'model.id', 'controllers.application.list.table.id')
showJoinButton: (->
return false unless @get('supplier.can_take_orders')
return false if @get('controllers.application.list') # if you already have an active list, do not join another
if @get('model.occupied') then true else false
).property('controllers.application.list.id', 'supplier.can_take_orders', 'model.occupied', 'model.id', 'controllers.application.list.table.id')
actions:
addProduct: (product)->
if existing = @store.all('product_order').find((po)-> po.get('product') == product and not po.get('order'))
existing.increment()
else
@store.createRecord 'product_order', product: product
joinOccupiedTable: ->
#@secured =>
$.post('/user/join_occupied_table.json', table_id: @get('model.id'))
@set 'join_request_sent', true
@@ -8,6 +8,10 @@ App.List = DS.Model.extend
extended_version: attr('boolean') extended_version: attr('boolean')
supplier_orders_in_process_count: attr('number') supplier_orders_in_process_count: attr('number')
supplier_orders_placed_count: attr('number') supplier_orders_placed_count: attr('number')
supplier: DS.belongsTo('supplier')
table: DS.belongsTo('table')
total: (-> total: (->
@get('orders').getEach('total').reduce(((sum, total) -> sum + total), 0) @get('orders').getEach('total').reduce(((sum, total) -> sum + total), 0)
).property('orders.@each.total') ).property('orders.@each.total')
@@ -2,3 +2,4 @@ attr = DS.attr
App.ProductCategory = DS.Model.extend App.ProductCategory = DS.Model.extend
name: attr('string') name: attr('string')
products: DS.hasMany('product') products: DS.hasMany('product')
supplier: DS.belongsTo('supplier')
@@ -2,6 +2,7 @@ attr = DS.attr
App.ProductOrder = DS.Model.extend App.ProductOrder = DS.Model.extend
quantity: attr 'number', defaultValue: 1 quantity: attr 'number', defaultValue: 1
product: DS.belongsTo('product') product: DS.belongsTo('product')
product_name: attr('string')
order: DS.belongsTo('order') order: DS.belongsTo('order')
placed: attr('boolean', defaultValue: false) placed: attr('boolean', defaultValue: false)
increment: -> increment: ->
@@ -0,0 +1,20 @@
attr = DS.attr
App.Supplier= DS.Model.extend
name: attr('string')
extended_version: attr('boolean')
open: attr('boolean')
orders_in_process_count: attr('number')
orders_placed_count: attr('number')
orders: DS.hasMany('order')
product_categories: DS.hasMany('product_category')
is_extended_version: ->
@get('extended_version')
can_take_orders: (->
return false unless @get('open')
true
).property('open')
@@ -0,0 +1,7 @@
attr = DS.attr
App.Table= DS.Model.extend
number: attr('number')
needs_help: attr('boolean')
occupied: attr('boolean')
supplier: DS.belongsTo('supplier')
@@ -6,9 +6,20 @@ Ember.Controller.reopen
@authentication_string = 'auth_token='+Qstorage.getItem('auth_token') @authentication_string = 'auth_token='+Qstorage.getItem('auth_token')
@authentication_object = {auth_token: Qstorage.getItem('auth_token')} @authentication_object = {auth_token: Qstorage.getItem('auth_token')}
callback.call(@) if callback callback.call(@) if callback
redirect_to: (route, options={})-> redirect_to: (route, args...)->
route = 'index' if route == 'user_root' route = 'index' if route == 'user_root'
@transitionToRoute(route).then => route_segments = App.Router.router.recognizer.names[route].segments
dynamic_segments = route_segments.reduce (sum, segment) ->
if segment.name then sum + 1 else sum
, 0
route_args = [route]
for isegment in [1..dynamic_segments]
route_args.push args.shift()
options = args.pop() || {}
#route_args.push args if a
@transitionToRoute.apply(@,route_args).then =>
if options.message if options.message
tkey = if options.message.indexOf('.') > -1 then options.message else "messages.#{options.message}" tkey = if options.message.indexOf('.') > -1 then options.message else "messages.#{options.message}"
@set 'controllers.application.notice', t(tkey) @set 'controllers.application.notice', t(tkey)
@@ -26,7 +37,7 @@ Ember.Controller.reopen
##$('#confirm-modal').css('visibility', 'visible').show() ##$('#confirm-modal').css('visibility', 'visible').show()
showModal: (options={})-> showModal: (options={})->
#this.container.lookup('view:modal', {title:'Test title'}) #this.container.lookup('view:modal', {title:'Test title'})
debugger #debugger
$(document).foundation('reflow') # needed (stupid!!!) $(document).foundation('reflow') # needed (stupid!!!)
@confirm_cancel = options.cancel @confirm_cancel = options.cancel
@set 'controllers.application.modal.title', options.title if options.title @set 'controllers.application.modal.title', options.title if options.title
@@ -48,3 +59,6 @@ Ember.ArrayController.reopen
if options.message if options.message
tkey = if options.message.indexOf('.') > -1 then options.message else "messages.#{options.message}" tkey = if options.message.indexOf('.') > -1 then options.message else "messages.#{options.message}"
@set 'controllers.application.notice', t(tkey) @set 'controllers.application.notice', t(tkey)
Ember.ObjectController.reopen
needs: ['application']
@@ -0,0 +1,6 @@
DS.Model.reopen
created_at: DS.attr('date')
updated_at: DS.attr('date')
eraseRecord: ->
@clearRelationships();
@transitionTo('deleted.saved');
@@ -9,6 +9,7 @@ App.Router.map ->
@route 'obtain_token' @route 'obtain_token'
@route 'active_list' @route 'active_list'
@route 'list_products' @route 'list_products'
@route 'list_products_for_table' @route 'list_products_for_table', path: '/list_products/:table_id'
@route 'table', path: '/tables/:table_id'
@resource 'lists', -> @resource 'lists', ->
@resource 'list', path: ':list_id' @resource 'list', path: ':list_id'
@@ -1 +1,7 @@
App.ActiveListRoute = Ember.Route.extend {} App.ActiveListRoute = Ember.Route.extend
afterModel: (a,b,c)->
controller = @controllerFor('application')
if table_id = controller.get('list.table.id')
transitionTo 'table', table_id
else
controller.redirect_to 'index', message: 'the_list_has_been_closed'
@@ -8,17 +8,7 @@ App.ApplicationRoute = Ember.Route.extend
faye.subscribe "/user/"+user_id, (e)=> faye.subscribe "/user/"+user_id, (e)=>
console.log e console.log e
@events[e.event].call(@) if @events[e.event] @events[e.event].call(@) if @events[e.event]
@store.find('list', 'current').then (list)=> @setCurrentList()
#@store.find('list', 'current').deleteRecord() # gets not replaced, buty stays as dummy
# A list record with id current and with the content of the returned list is created
# at the moment remove the dummy list, this should be resolved by Ember eventually
if error_list = @store.all('list').findBy('id', 'current')
error_list.rollback()
error_list.transitionTo 'loaded.saved'
error_list.unloadRecord()
@set 'list', list
@controllerFor('active_list').set('model', list)
unauthorized: -> unauthorized: ->
Qstorage.setItem('auth_token', '') Qstorage.setItem('auth_token', '')
@@ -25,10 +25,9 @@ DS.ActiveModelSerializer.reopen
json[key].push item.serialize() json[key].push item.serialize()
else else
@_super record, json, relationship @_super record, json, relationship
DS.Model.reopen
created_at: DS.attr('date')
updated_at: DS.attr('date')
App.ApplicationSerializer = DS.ActiveModelSerializer App.ApplicationSerializer = DS.ActiveModelSerializer
App.CustomAdapter = DS.RESTAdapter.extend App.CustomAdapter = DS.RESTAdapter.extend
# user underscored paths # user underscored paths
@@ -2,7 +2,7 @@
h2=t 'models.list' h2=t 'models.list'
p Hoi p Hoi
= controller = controller
if model.extended_version if model.is_extended_version
h3 Extended h3 Extended
else else
h3 Not extended h3 Not extended
@@ -1,4 +1,5 @@
.row h2= List products for table
/.row
.large-6.columns .large-6.columns
each product_category in controller each product_category in controller
hr hr
@@ -0,0 +1,37 @@
.row
h2
=t 'models.table'
|
= number
if showJoinButton
if join_request_sent
button.disabled
span.fa.fa-spinner.fa-spin.fa-lg
span Waiting for approval
else
button{action joinOccupiedTable} Join occupied table
if tableCanTakeOrders
.large-6.columns
each product_category in supplier.product_categories
if product_category.products
hr
h4= product_category.name
hr
ul.product_category-products
each product in product_category.products
li
a{action addProduct product}= product.name
span.right.currency=currency product.price
.large-6.columns= render 'product_orders'
else
.large12
each product_category in supplier.product_categories
if product_category.products
hr
h4= product_category.name
hr
ul.product_category-products
each product in product_category.products
li
span= product.name
span.right.currency=currency product.price
@@ -196,6 +196,22 @@ $(function(){
Qstorage.removeItem('list_closed'); Qstorage.removeItem('list_closed');
} }
setTranslations(); setTranslations();
$('#toggle-side-menu').click(function(){
var body = $('body');
var menu = $('#side-menu-container');
if(menu.is(':visible')){
body.animate({paddingLeft: 0});
menu.animate({width: 0}, function(){$(this).hide()});
}else{
body.animate({paddingLeft: '222px'});
menu.show().animate({width: '222px'});
}
//if(body.css('margin-left') && body.css('margin-left') != '0px'){
// body.animate('margin-left', '0')
//}else{
//}
});
}); });
function setLocale(locale){ function setLocale(locale){
Qstorage.setItem('locale', locale); Qstorage.setItem('locale', locale);
@@ -58,7 +58,7 @@
padding: 0 padding: 0
height: 400px height: 400px
//background-image: image-url('textures/wood4.jpg') //background-image: image-url('textures/wood4.jpg')
background-color: rgba(0,0,0,0.4) //background-color: rgba(0,0,0,0.4)
.section-table .section-table
position: absolute position: absolute
cursor: pointer cursor: pointer
@@ -2,6 +2,7 @@ $side-spacing: 0px
@import constants @import constants
html html
body body
padding-top: 42px
padding-left: $side-spacing padding-left: $side-spacing
padding-right: $side-spacing padding-right: $side-spacing
background-color: transparent background-color: transparent
@@ -35,7 +35,16 @@ $input-color: white
//=General ======================================== //=General ========================================
// Everything with the inset panel just extends .well // Everything with the inset panel just extends .well
.well .well
+inset-panel-dark //+inset-panel-dark
background-color: rgba(255,255,255,0.8)
h1,h2,h3,h4,h5,h6,a
color: #333
.table
thead
color: #111
td
border-top-color: #aaa
color: #111
body body
background: $bg background: $bg
@@ -51,7 +51,7 @@
padding: 0 padding: 0
height: 400px height: 400px
//background-image: image-url('textures/wood4.jpg') //background-image: image-url('textures/wood4.jpg')
background-color: rgba(0,0,0,0.4) //background-color: rgba(0,0,0,0.4)
.section-table .section-table
position: absolute position: absolute
cursor: pointer cursor: pointer
@@ -4,6 +4,7 @@ html
background-image: $wood background-image: $wood
background-color: $background-brown background-color: $background-brown
body body
padding-top: 42px
padding-left: $side-spacing padding-left: $side-spacing
padding-right: $side-spacing padding-right: $side-spacing
background-color: transparent background-color: transparent
@@ -1,6 +1,6 @@
@import "bootstrap" @import "bootstrap"
body body
padding-top: 42px //padding-top: 42px
.table .table
&.table-condensed &.table-condensed
margin-bottom: 5px margin-bottom: 5px
@@ -1,3 +1,3 @@
//= require foundation //= require ./foundation_and_overrides
//= require font-awesome //= require font-awesome
//= require_directory . //= require_directory .
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,4 @@
@import foundation @import "foundation_and_overrides"
.lists-overview-entry .lists-overview-entry
+grid-column(12) +grid-column(12)
@media #{$medium-only} @media #{$medium-only}
@@ -1,6 +1,7 @@
$qbrown: #853d15 $qbrown: #853d15
$qbrown-active: lighten($qbrown, 20%) $qbrown-active: lighten($qbrown, 20%)
$green: #7BB459 //Heineken $green: #7BB459 //Heineken
//$green: //Heineken
//$wood: image-url('textures/wood001-vertical.jpg') //$wood: image-url('textures/wood001-vertical.jpg')
$wood: image-url('textures/theme1.jpg') $wood: image-url('textures/theme1.jpg')
$background-brown: #57351f $background-brown: #57351f
@@ -10,7 +11,7 @@ $side-spacing: 5px
background-repeat: no-repeat, no-repeat, repeat-x background-repeat: no-repeat, no-repeat, repeat-x
background-position: left center, right center, center center background-position: left center, right center, center center
background-image: image-url('theme1/button-wood-left.png'), image-url('theme1/button-wood-right.png'), image-url('theme1/button-wood-middle.png') background-image: image-url('theme1/button-wood-left.png'), image-url('theme1/button-wood-right.png'), image-url('theme1/button-wood-middle.png')
color: $green color: white
border-width: 0 border-width: 0
border-radius: 0 border-radius: 0
height: 31px height: 31px
@@ -21,7 +22,7 @@ $side-spacing: 5px
background-repeat: no-repeat, no-repeat, repeat-x background-repeat: no-repeat, no-repeat, repeat-x
background-position: left center, right center, center center background-position: left center, right center, center center
background-image: image-url('theme1/button-wood-left.png'), image-url('theme1/button-wood-right.png'), image-url('theme1/button-wood-middle.png') background-image: image-url('theme1/button-wood-left.png'), image-url('theme1/button-wood-right.png'), image-url('theme1/button-wood-middle.png')
color: blue color: black
=button-bar =button-bar
background-color: transparent background-color: transparent
background-repeat: no-repeat, no-repeat background-repeat: no-repeat, no-repeat
@@ -53,6 +54,9 @@ $side-spacing: 5px
line-height: 1.1em line-height: 1.1em
color: black color: black
float: left float: left
.main-buttons
float: left
margin-right: 12px
.action-buttons .action-buttons
float: left float: left
width: 150px width: 150px
@@ -72,7 +76,6 @@ $side-spacing: 5px
background-color: $qbrown background-color: $qbrown
text-align: center text-align: center
line-height: 34px line-height: 34px
text-indent: -5000px
&.active &.active
background-color: $qbrown-active background-color: $qbrown-active
&.hide &.hide
@@ -11,6 +11,7 @@
*= require 'twitter-bootstrap/bootstrap_and_overrides' *= require 'twitter-bootstrap/bootstrap_and_overrides'
*= require 'twitter-bootstrap/bootstrap_overrides' *= require 'twitter-bootstrap/bootstrap_overrides'
*= require 'general' *= require 'general'
*= require font-awesome
*= require_directory . *= require_directory .
*= require_self *= require_self
*/ */
@@ -34,7 +34,21 @@ $input-color: white
//=General ======================================== //=General ========================================
// Everything with the inset panel just extends .well // Everything with the inset panel just extends .well
.well .well
+inset-panel-dark //+inset-panel-dark
background-color: rgba(255,255,255,0.8)
h1,h2,h3,h4,h5,h6,a
color: #333
.table
thead
color: #111
td
border-top-color: #aaa
color: #111
.table-striped
tbody tr:nth-child(2n+1)
td, th
background-color: #444
body body
background: $bg background: $bg
@@ -4,3 +4,9 @@
.order-product-button .order-product-button
+wood-button +wood-button
color: white color: white
button.order-selected-products
color: white
background-color: $green
.product_order-remove-button
padding: 2px 5px
background-color: #bbb
@@ -0,0 +1,23 @@
@import ./constants
@import font-awesome
#toggle-side-menu
position: absolute
width: 28px
height: 28px
color: white
span
@extend .fa
@extend .fa-bars
@extend .fa-lg
#side-menu-container
background-color: #444
position: fixed
display: none
left: 0
top: 0
width: 0
height: 100%
> ul
list-style: none
a
color: white
@@ -1,5 +1,9 @@
@import compass @import compass
@import ./constants @import ./constants
@import font-awesome
.fa-menu
@extend .fa-cutlery
html html
background-image: $wood background-image: $wood
background-color: $background-brown background-color: $background-brown
@@ -102,6 +106,7 @@ body
height: 28px height: 28px
background-position: center center background-position: center center
background-repeat: no-repeat background-repeat: no-repeat
line-height: 28px
.top-button-bar .top-button-bar
+button-bar +button-bar
height: 90px height: 90px
@@ -112,21 +117,20 @@ body
margin-right: 8px margin-right: 8px
.table-number .table-number
float: right float: right
#show-active-list //#show-active-list
span span
background-image: image-url('icons/list.png') background-image: image-url('icons/list.png')
#place-order-on-list #place-order-on-list
span span
background-image: image-url('icons/menu.png') background-image: image-url('icons/menu.png')
#list-needs-payment-button #list-needs-payment-button
span //span
background-image: image-url('icons/needs-payment.png') //background-image: image-url('icons/needs-payment.png')
&.active &.active
span span.fa
background-image: image-url('icons/needs-payment-active.png') @extend .fa-spin
//background-image: image-url('icons/needs-payment-active.png')
#list-needs-help-button #list-needs-help-button
span
background-image: image-url('icons/needs-help.png')
&.active &.active
span span.fa
background-image: image-url('icons/needs-help-active.png') @extend .fa-spin
+1 -1
View File
@@ -134,7 +134,7 @@ class UserController < Users::ApplicationController
if @list = @table.active_list if @list = @table.active_list
if @list.user_ids.include?(current_user.id) if @list.user_ids.include?(current_user.id)
render json: {approved: true} render json: {approved: true}
elsif @list.join_requests.include?(current_user.id) elsif @list.join_request_user_ids.include?(current_user.id)
render json: {waiting: true} render json: {waiting: true}
else else
render json: {rejected: true} render json: {rejected: true}
@@ -11,6 +11,7 @@ module Users
#EMBER #EMBER
def current def current
list = current_user.active_list list = current_user.active_list
render json: {}, status: :not_found and return unless list.present?
[list].include_relation(supplier: {product_categories: :products}, orders: :product_orders) # table also when it is a real array :) [list].include_relation(supplier: {product_categories: :products}, orders: :product_orders) # table also when it is a real array :)
render json: json_response(not_present: true) and return unless list.present? render json: json_response(not_present: true) and return unless list.present?
render json: list, serializer: UserExtendedListSerializer render json: list, serializer: UserExtendedListSerializer
+11 -1
View File
@@ -2,8 +2,18 @@ module Users
class OrdersController < Users::ApplicationController class OrdersController < Users::ApplicationController
respond_to :json respond_to :json
def create def create
converted_order = params[:order][:product_orders].each_with_object({}){|po, o| o[po[:product_id]] = po[:quantity] } converted_order = params[:order][:product_orders].each_with_object({}){|po, o| o[po[:product_id]] = po[:quantity] }
list = current_user.active_list unless list = current_user.active_list
table = Table.find(params[:order][:table_id])
if table.occupied?
#render json: json_alert('messages.table_is_occupied', location: :join_occupied_table, location_params: {table_id: @table.id})
render status: :not_acceptable and return
end
list = List.from_table( table, current_user )
end
order = list.place_order converted_order order = list.place_order converted_order
render json: order, serializer: OrderSerializer render json: order, serializer: OrderSerializer
end end
@@ -0,0 +1,8 @@
module Users
class TablesController < Users::ApplicationController
def show
@table = Table.find(params[:id])
render json: @table, serializer: UserExtendedTableSerializer
end
end
end
+22 -16
View File
@@ -7,7 +7,7 @@ class List
property :needs_help, type: :boolean, default: false property :needs_help, type: :boolean, default: false
property :needs_payment, type: :boolean, default: false property :needs_payment, type: :boolean, default: false
property :closed_at, type: Time property :closed_at, type: Time
property :join_requests, type: Array, default: [] property :join_request_user_ids, type: Array, default: []
property :price, type: Float property :price, type: Float
property :is_paid, type: :boolean, default: false property :is_paid, type: :boolean, default: false
property :paid_at, type: Time property :paid_at, type: Time
@@ -177,6 +177,7 @@ class List
def is_paid! def is_paid!
self.is_paid = true self.is_paid = true
self.needs_payment = false
self.paid_at ||= Time.now self.paid_at ||= Time.now
if save if save
broadcast_users 'list_is_paid', id: id broadcast_users 'list_is_paid', id: id
@@ -192,18 +193,18 @@ class List
self.section_id = to_table.section_id self.section_id = to_table.section_id
if save if save
# Update the section of an order # Update the section of an order
orders.each do |order| #orders.each do |order|
order.section_id = self.section_id #order.section_id = self.section_id
order.save #order.save
end #end
broadcast_users 'list_changed_table', list: as_json, section_title: to_table.section.try(:title), from_table_id: from_table broadcast_users 'list_changed_table', list: as_json, section_title: to_table.section.try(:title), from_table_id: from_table
broadcast_supplier supplier_id, 'list_changed_table', list: as_json, section_title: to_table.section.try(:title), from_table_id: from_table broadcast_supplier supplier_id, 'list_changed_table', list: as_json, section_title: to_table.section.try(:title), from_table_id: from_table
end end
end end
def approve_join_request_for_user!(user) def approve_join_request_for_user!(user)
if join_requests.include?(user.id) if join_request_user_ids.include?(user.id)
join_requests.delete(user.id) join_request_user_ids.delete(user.id)
user.active_list_id = self.id user.active_list_id = self.id
add_user(user) add_user(user)
user.save user.save
@@ -215,7 +216,7 @@ class List
end end
def unlink_user(user) def unlink_user(user)
changed = join_requests.delete(user.id) changed = join_request_user_ids.delete(user.id)
changed ||= Array.wrap(user_ids).delete(user.id) changed ||= Array.wrap(user_ids).delete(user.id)
if user.active_list_id == id if user.active_list_id == id
user.active_list_id = nil user.active_list_id = nil
@@ -225,8 +226,8 @@ class List
end end
def send_table_join_request_for_user!(requester) def send_table_join_request_for_user!(requester)
unless join_requests.include?(requester.id) unless join_request_user_ids.include?(requester.id)
self.join_requests << requester.id self.join_request_user_ids << requester.id
self.is_dirty self.is_dirty
if save if save
for user in users for user in users
@@ -237,8 +238,8 @@ class List
end end
def reject_join_request_for_user!(user_id) def reject_join_request_for_user!(user_id)
if join_requests.include?(user_id) if join_request_user_ids.include?(user_id)
join_requests.delete(user_id) join_request_user_ids.delete(user_id)
self.is_dirty self.is_dirty
if save if save
broadcast_user user_id, 'join_request_rejected' broadcast_user user_id, 'join_request_rejected'
@@ -269,14 +270,14 @@ class List
def place_order(products, user: nil, employee: nil) def place_order(products, user: nil, employee: nil)
return false unless products.any? return false unless products.any?
order = Order.create list: self, supplier: supplier, user: user, employee: employee, section_id: section_id order = Order.create list: self, supplier: supplier, user: user, employee: employee, section_id: section_id, table_id: table_id
return unless order.id return unless order.id
orders_placed_count = supplier.increment_orders_placed_count! orders_placed_count = supplier.increment_orders_placed_count!
loaded_products = self.class.database.load_document products.keys loaded_products = self.class.database.load_document products.keys
products.each do |product_id, quantity| products.each do |product_id, quantity|
quantity = quantity.to_i quantity = quantity.to_i
product = loaded_products.find{|p| p.id == product_id} # to get the price product = loaded_products.find{|p| p.id == product_id} # to get the price
ProductOrder.create order: order, product_id: product_id, quantity: quantity, price: product.price if quantity > 0 ProductOrder.create order: order, product_id: product_id, quantity: quantity, price: product.price, product_name: product.name if quantity > 0
end end
set_price set_price
save save
@@ -366,18 +367,23 @@ class List
# Return a join requests object in the form of: # Return a join requests object in the form of:
# {join_request: [{user_id: '1saf3...', user_email: 'info@qwaiter.com'}, [....]]} # {join_request: [{user_id: '1saf3...', user_email: 'info@qwaiter.com'}, [....]]}
# DEPRICATED IN EMBER
def join_requests_as_json def join_requests_as_json
return @join_requests_as_json if @join_requests_as_json.present? return @join_requests_as_json if @join_requests_as_json.present?
h = {join_requests: []} h = {join_requests: []}
# Handle join requests # Handle join requests
if join_requests.any? if join_request_user_ids.any?
for user in self.class.database.load_document(join_requests) for user in self.class.database.load_document(join_request_user_ids)
h[:join_requests] << {user_id: user.id, user_email: user.email} h[:join_requests] << {user_id: user.id, user_email: user.email}
end end
end end
@join_requests_as_json = h @join_requests_as_json = h
end end
def join_requests
@join_requests ||= join_request_user_ids.any? ? self.class.database.load_document(join_request_user_ids).map{|user| JoinRequest.new(user: user, list: self) } : []
end
def product_categories def product_categories
supplier.product_categories supplier.product_categories
end end
+1
View File
@@ -8,6 +8,7 @@ class Order
belongs_to :user belongs_to :user
belongs_to :supplier belongs_to :supplier
belongs_to :section belongs_to :section
belongs_to :table
belongs_to :employee belongs_to :employee
has_many :product_orders, dependent: :destroy has_many :product_orders, dependent: :destroy
+1
View File
@@ -4,6 +4,7 @@ class ProductOrder
property :quantity, type: Fixnum property :quantity, type: Fixnum
property :price, type: Float property :price, type: Float
property :product_name
belongs_to :product belongs_to :product
belongs_to :order belongs_to :order
+1
View File
@@ -1,5 +1,6 @@
class Supplier class Supplier
include SimplyStored::Couch include SimplyStored::Couch
include ActiveModel::SerializerSupport
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable, :confirmable devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable, :confirmable
property :unconfirmed_email property :unconfirmed_email
+3
View File
@@ -6,6 +6,7 @@ class Table
property :number, type: Fixnum, default: 1 property :number, type: Fixnum, default: 1
property :position_x, type: Float property :position_x, type: Float
property :position_y, type: Float property :position_y, type: Float
property :needs_help, type: :boolean
belongs_to :supplier belongs_to :supplier
belongs_to :section belongs_to :section
@@ -47,9 +48,11 @@ class Table
end end
def occupied? def occupied?
return true #testing...
return @is_occupied if instance_variable_defined?(:'@is_occupied') return @is_occupied if instance_variable_defined?(:'@is_occupied')
@is_occupied = !self.class.database.view(List.active_by_table_id_view(key: id, reduce: true)).zero? @is_occupied = !self.class.database.view(List.active_by_table_id_view(key: id, reduce: true)).zero?
end end
alias occupied occupied?
def occupied=(val) end def occupied=(val) end
def self.enrich_active_list_id(tables) def self.enrich_active_list_id(tables)
@@ -0,0 +1,3 @@
class JoinRequestSerializer < Qwaiter::Serializer
attributes :user_id, :user_facebook_id, :list_id
end
+1 -1
View File
@@ -1,7 +1,7 @@
class ListSerializer < Qwaiter::Serializer class ListSerializer < Qwaiter::Serializer
# user ids for facebook pictures # user ids for facebook pictures
#embed :ids #embed :ids
attributes :state, :needs_help, :needs_payment, :is_paid, :price, :table_id, :table_number, :section_id, :has_active_orders, :user_ids attributes :state, :needs_help, :needs_payment, :is_paid, :price, :table_id, :table_number, :section_id, :user_ids, :supplier_id #, :has_active_orders
#def has_active_orders #def has_active_orders
#object.has_active_orders? #object.has_active_orders?
+1 -1
View File
@@ -1,6 +1,6 @@
class OrderSerializer < Qwaiter::Serializer class OrderSerializer < Qwaiter::Serializer
embed :ids, include: true embed :ids, include: true
attributes :state, :list_id, :section_id #, :price attributes :state, :list_id, :section_id, :table_id #, :price
# todo, put this logic in Ember # todo, put this logic in Ember
#def product_orders #def product_orders
+1 -1
View File
@@ -1,5 +1,5 @@
# Used for user ember1 # Used for user ember1
class ProductOrderSerializer < Qwaiter::Serializer class ProductOrderSerializer < Qwaiter::Serializer
embed :ids embed :ids
attributes :order_id, :product_id, :quantity, :price attributes :order_id, :product_id, :quantity, :price, :product_name
end end
-4
View File
@@ -10,10 +10,6 @@ class TableSerializer < Qwaiter::Serializer
#object.active_list #object.active_list
#end #end
def occupied
object.active_list_id.present?
end
def list def list
object.active_list object.active_list
end end
@@ -17,7 +17,9 @@ class UserExtendedListSerializer < Qwaiter::Serializer
object.has_active_orders? object.has_active_orders?
end end
has_many :orders has_many :orders
has_many :product_categories #has_many :product_categories
has_one :table, serializer: UserExtendedTableSerializer
has_many :join_requests
def extended_version def extended_version
true true
@@ -0,0 +1,10 @@
class UserExtendedSupplierSerializer < Qwaiter::Serializer
self.root = :supplier
embed :ids, include: true
attributes :extended_version, :open, :name
has_many :product_categories
def extended_version
true
end
end
@@ -0,0 +1,6 @@
class UserExtendedTableSerializer < Qwaiter::Serializer
self.root = :table
embed :ids, include: true
attributes :number, :width, :height, :position_x, :position_y, :section_id, :occupied, :needs_help
has_one :supplier, serializer: UserExtendedSupplierSerializer
end
@@ -0,0 +1,8 @@
class UserExtendedSupplierSerializer < Qwaiter::Serializer
self.root = :supplier
attributes :extended_version, :open, :name
def extended_version
false
end
end
+4
View File
@@ -0,0 +1,4 @@
class UserTableSerializer < Qwaiter::Serializer
self.root = :table
attributes :number, :width, :height, :position_x, :position_y, :section_id, :occupied, :needs_help
end
+19
View File
@@ -0,0 +1,19 @@
class JoinRequest
attr_reader :user, :list
def initialize(user: nil, list: nil)
@user, @list = user, list
end
def user_id
user.id
end
def user_facebook_id
user.uid
end
def list_id
list.id
end
end
+13 -4
View File
@@ -4,7 +4,6 @@
<th data-t="models.product"></th> <th data-t="models.product"></th>
<th>#</th> <th>#</th>
<th class="currency" data-t="basket.total"></th> <th class="currency" data-t="basket.total"></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -12,18 +11,28 @@
<tr> <tr>
<td>{{name}}</td> <td>{{name}}</td>
<td>{{number}}</td> <td>{{number}}</td>
<td class="currency">{{#currency}}{{product_total}}{{/currency}}</td> <td class="currency">
{{#currency}}{{product_total}}{{/currency}}
<a class="product_order-remove-button" href=""><span class="fa fa-times fa-large"></span></a>
</td>
</tr> </tr>
{{/products}} {{/products}}
</tbody> </tbody>
<tfoot> <tfoot>
<tr> <tr>
<td colspan="2"> <td colspan="2">
<button class="btn btn-primary" onClick="Quser.order_selected_products()" data-t="selected_products.order"></button> Totaal
<button class="btn btn btn-warning" onClick="Quser.clear_selected_products()" data-t="selected_products.clear"></button>
</td> </td>
<td class="currency"><strong id="active-order-total">{{#currency}}{{total}}{{/currency}}</strong></td> <td class="currency"><strong id="active-order-total">{{#currency}}{{total}}{{/currency}}</strong></td>
<tr>
<tr>
<td>
<button class="btn btn btn-warning hide" onClick="Quser.clear_selected_products()" data-t="selected_products.clear"></button>
</td>
<td></td> <td></td>
<td style="text-align: right">
<button class="order-selected-products" onClick="Quser.order_selected_products()" data-t="selected_products.order"></button>
</td>
<tr> <tr>
</tfoot> </tfoot>
</table> </table>
@@ -1,13 +1,15 @@
<tr><td colspan="4"><h4>{{category}}</h4></td></tr> <tr><td colspan="3"><h4>{{category}}</h4></td></tr>
{{#products}} {{#products}}
<tr> <tr>
<td>{{name}}</td> <td>{{name}}</td>
<td class="order-count-cell"> <td class="order-count-cell">
<span class="btn btn-info btn-mini" onclick="Quser.lower_products_counter('{{_id}}')">-</span> <span class="btn btn-mini hide" onclick="Quser.lower_products_counter('{{_id}}')">-</span>
<span id="order-product-count-{{_id}}" class="order-product-count">1</span> <span id="order-product-count-{{_id}}" class="order-product-count">1</span>
<span class="btn btn-info btn-mini" onclick="Quser.increment_products_counter('{{_id}}')">+</span> <span class="btn btn-mini hide" onclick="Quser.increment_products_counter('{{_id}}')">+</span>
</td>
<td style="text-align: right">
{{#currency}}{{price}}{{/currency}}
<button class="btn order-product-button order-product-{{_id}}" onclick="Quser.add_product_to_order('{{_id}}', this)">Add</button>
</td> </td>
<td>{{#currency}}{{price}}{{/currency}}</td>
<td><button class="btn order-product-button order-product-{{_id}}" onclick="Quser.add_product_to_order('{{_id}}', this)">Add</button></td>
</tr> </tr>
{{/products}} {{/products}}
+8 -1
View File
@@ -53,7 +53,7 @@ html lang="en"
}); });
body class=action_name body class=action_name
.navbar.navbar-fixed-top /.navbar.navbar-fixed-top
.navbar-inner .navbar-inner
.container .container
a.btn.btn-navbar data-target=".nav-collapse" data-toggle="collapse" a.btn.btn-navbar data-target=".nav-collapse" data-toggle="collapse"
@@ -66,6 +66,13 @@ html lang="en"
li.locale.locale-en= link_to_function 'English', %|setLocale('en')| li.locale.locale-en= link_to_function 'English', %|setLocale('en')|
li.locale.locale-nl= link_to_function 'Nederlands', %|setLocale('nl')| li.locale.locale-nl= link_to_function 'Nederlands', %|setLocale('nl')|
li= link_to t('user.list_history.title'), user_list_history_path, data: {t: 'list_history.title'} li= link_to t('user.list_history.title'), user_list_history_path, data: {t: 'list_history.title'}
a#toggle-side-menu href="#"
span.fa.fa-bars.fa-lg
#side-menu-container
ul
li.locale-select.locale-select-en= link_to_function 'English', %|setLocale('en')|
li.locale-select.locale-select-nl= link_to_function 'Nederlands', %|setLocale('nl')|
li= link_to t('user.list_history.title'), user_list_history_path, data: {t: 'list_history.title'}
.container .container
.content .content
.alert.alert-error.hide .alert.alert-error.hide
+8 -4
View File
@@ -1,4 +1,4 @@
= top_bar title: 'show_products.title' do = top_bar title: '' || 'show_products.title' do
.pull-right .pull-right
.supplier-info-row .supplier-info-row
.table-number .table-number
@@ -6,14 +6,18 @@
.supplier-info-row .supplier-info-row
.counter.supplier-orders-placed-count .counter.supplier-orders-placed-count
.counter.supplier-orders-in-process-count .counter.supplier-orders-in-process-count
.main-buttons= link_to image_tag('icons/logo-small.png', alt: application_title), user_root_path, class: :brand
.action-buttons .action-buttons
= link_to user_active_list_path, class: ['user-top-button'], id: 'show-active-list' do = link_to user_active_list_path, class: ['user-top-button'], id: 'show-active-list' do
span= t('helpers.links.show_active_list', list: List.model_name.human) /span=# t('helpers.links.show_active_list', list: List.model_name.human)
span.fa.fa-menu.fa-lg
span#list-needs-payment-button.user-top-button span#list-needs-payment-button.user-top-button
span span.fa.fa-money.fa-lg
span#list-needs-help-button.user-top-button /span#list-needs-help-button.user-top-button
span span
span span
span#list-needs-help-button.user-top-button.left
span.fa.fa-question.fa-lg
.well .well
+1
View File
@@ -78,6 +78,7 @@ Qwaiter::Application.routes.draw do
end end
resources :orders, only: [:create] resources :orders, only: [:create]
resources :tables, only: [:show]
end end