Ember temp commit

This commit is contained in:
2013-09-24 08:47:30 +02:00
parent ebbb5dedfc
commit 5650ada04c
71 changed files with 595 additions and 66 deletions
+7 -4
View File
@@ -9,6 +9,11 @@ gem 'rack-cors', :require => 'rack/cors'
# gem 'sqlite3'
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'ember-rails'
gem 'ember-source'
gem 'slim-rails'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
@@ -18,18 +23,16 @@ group :assets do
gem 'bootstrap-sass'
gem 'bourbon'
gem 'compass-rails'
gem 'js-routes'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
#gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
gem 'emblem-rails'
#gem 'mustache' #, :require => 'mustache/railtie'
end
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'ember-rails'
gem 'slim-rails'
#gem 'less-rails'
gem 'couch_potato' , github: 'bterkuile/couch_potato'
+12
View File
@@ -87,6 +87,9 @@ GEM
ember-source
execjs
handlebars-source
barber-emblem (0.1.1)
barber (>= 0.4.1)
emblem-source
bcrypt-ruby (3.1.2)
bootstrap-sass (2.3.2.2)
sass (~> 3.2)
@@ -169,6 +172,10 @@ GEM
railties (>= 3.1)
ember-source (1.0.0)
handlebars-source (= 1.0.12)
emblem-rails (0.1.1)
barber-emblem (~> 0.1.1)
ember-rails (>= 0.11.1)
emblem-source (0.3.2)
erubis (2.7.0)
eventmachine (1.0.3)
execjs (2.0.1)
@@ -219,6 +226,8 @@ GEM
jquery-ui-rails (4.0.4)
jquery-rails
railties (>= 3.1.0)
js-routes (0.9.0)
rails (>= 3.2)
json (1.8.0)
kaminari (0.14.1)
actionpack (>= 3.0.0)
@@ -385,11 +394,14 @@ DEPENDENCIES
devise (= 3.1.0)
devise_simply_stored!
ember-rails
ember-source
emblem-rails
factory_girl_rails
faye
guard-rspec
jquery-rails
jquery-ui-rails
js-routes
kaminari
letter_opener
mini_magick
-4
View File
@@ -42,7 +42,3 @@ window.Qwaiter=
currency(Mustache.render(val, this))
)
Mustache.to_html($(selector).html(), locs)
jQuery.ajaxSetup
'beforeSend': (xhr) ->
xhr.setRequestHeader("Accept", "text/javascript")
@@ -0,0 +1,3 @@
Qsupplier.App = Ember.Application.create
LOG_TRANSITIONS: true
rootElement: '#app'
@@ -0,0 +1,6 @@
#= require handlebars
#= require ember
#= require ember-data
#= require_directory ./modifications
#= require ./app
#= require_tree .
@@ -0,0 +1,17 @@
Qsupplier.App.IndexController = Ember.ObjectController.extend
active_lists: (->
@get('lists').filterProperty('state', 'active')
).property('lists.@each.state')
active_orders: (->
@get('orders').filter (o)->(o.get('state') == 'active')
).property('orders.@each.state')
markListAsHelped: (id)->
list = Qsupplier.App.List.find(id)
list.set('needs_help', false)
$.post '/supplier/mark_list_as_helped', {list_id: id}
closeList: (id)->
list = Qsupplier.App.List.find(id)
list.set('state', 'closed')
$.post '/supplier/close_list', {list_id: id}
@@ -0,0 +1,13 @@
Qsupplier.App.SectionController = Ember.ObjectController.extend
#width: -> $('.section-tables-active').width()
#height: -> $('.section-tables-active').height()
dummy: -> 3
editmode: false
makeEditable: -> @set('editmode', true)
finishEditable: ->
@set('editmode', false)
@get('model').save()
addTables: ->
$('#add-tables-modal').modal()
arrangeTables: ->
$('#arrange-tables-modal').modal()
@@ -0,0 +1 @@
Qsupplier.App.SectionsController = Ember.ArrayController.extend {}
@@ -0,0 +1,2 @@
Ember.Handlebars.registerBoundHelper 'currency', (amount, params..., options)->
new Handlebars.SafeString Qwaiter.currency(amount)
@@ -0,0 +1,43 @@
# on why local storage is used in the enter events
# http://stackoverflow.com/questions/8762635/getting-the-filename-during-the-dragenter-event
DragNDrop = Ember.Namespace.create()
DragNDrop.cancel = (e)->
e.preventDefault()
false
DragNDrop.Draggable = Ember.Mixin.create
attributeBindings: 'draggable'
draggable: 'true'
dragStart: (e)->
@set 'content.isDragging', true
localStorage.setItem('draggingView', @get('elementId'))
dataTransfer = e.originalEvent.dataTransfer
dataTransfer.setData 'Text', @get('elementId')
dragEnd: (e)->
@set 'content.isDragging', false
localStorage.removeItem 'draggingView' if localStorage.getItem 'draggingView'
DragNDrop.Droppable = Ember.Mixin.create
dragEnter: (e)->
if @dragEntered
e.preventDefault()
viewId = localStorage.getItem 'draggingView'
view = Ember.View.views[viewId]
@dragEntered view
else
DragNDrop.cancel(e)
dragOver: DragNDrop.cancel
drop: (e)->
e.preventDefault()
viewId = e.originalEvent.dataTransfer.getData('Text')
view = Ember.View.views[viewId]
return unless view
# Calculate drop position relative to container
position =
left: Math.max(e.originalEvent.pageX - view.$el.offsetParent().offset().left - (view.$el.outerWidth()/2), 0)
top: Math.max(e.originalEvent.pageY - view.$el.offsetParent().offset().top - (view.$el.outerHeight()/2), 0)
@dropped view, position if @dropped
false
@DragNDrop = DragNDrop
@@ -0,0 +1,8 @@
Ember.Handlebars.registerHelper 'route', (route_name, params..., options)->
opts = options.hash
if scope = @get('content')
params = params.map (a) -> scope.get(a)
for k,v of opts
opts[k] = scope.get(v) if typeof(v) == 'string' && scope.get(v)
route = if params.length then Routes[route_name].call(this, params, opts) else Routes[route_name].call(this, opts)
new Handlebars.SafeString route
@@ -0,0 +1,4 @@
Ember.Handlebars.registerHelper 't', (path, params..., options)->
text = t(path)
tag = if options.hash.bare then text else "<span data-t=\"#{path}\">#{text}</span>"
new Handlebars.SafeString tag
@@ -0,0 +1,11 @@
attr = DS.attr
Qsupplier.App.List = DS.Model.extend
state: attr 'string'
needs_help: attr 'boolean'
needs_payment: attr 'boolean'
is_paid: attr 'boolean'
has_active_orders: attr 'boolean'
price: attr 'number'
table_number: attr 'number'
table: DS.belongsTo('Qsupplier.App.Table', inverse: 'active_list')
orders: DS.hasMany('Qsupplier.App.Order')
@@ -0,0 +1,9 @@
attr = DS.attr
Qsupplier.App.Order = DS.Model.extend
state: attr('string')
list: DS.belongsTo('Qsupplier.App.List')
total_amount: attr('number')
#products: attr('object')
products: DS.hasMany('Qsupplier.App.Product')
active: (-> @get('state') == 'active').property('state')
delivered: (-> @get('state') == 'delivered').property('state')
@@ -0,0 +1,3 @@
attr = DS.attr
Qsupplier.App.Product = DS.Model.extend
order: DS.belongsTo('Qsupplier.App.Order')
@@ -0,0 +1,6 @@
attr = DS.attr
Qsupplier.App.Section = DS.Model.extend
title: attr 'string'
width: attr 'number'
height: attr 'number'
tables: DS.hasMany('Qsupplier.App.Table')
@@ -0,0 +1,10 @@
attr = DS.attr
Qsupplier.App.Table = DS.Model.extend
number: attr 'number'
width: attr 'number'
height: attr 'number'
position_x: attr 'number'
position_y: attr 'number'
occupied: attr 'boolean'
section: DS.belongsTo('Qsupplier.App.Section')
active_list: DS.belongsTo('Qsupplier.App.List')
@@ -0,0 +1,5 @@
DS.JSONTransforms['object'] =
deserialize: (serialized)->
serialized
serialize: (deserialized)->
deserialized
@@ -0,0 +1,11 @@
DS.Model.reopen
created_at: DS.attr('string')
updated_at: DS.attr('string')
DS.Model.reopenClass
findCached: (id)->
@all().findProperty('id', id)
updateOrCreate: (attributes)->
if cached = @findCached(attributes.id)
cached.setProperties attributes
else
@createRecord(attributes)
@@ -0,0 +1,9 @@
# For more information see: http://emberjs.com/guides/routing/
Qsupplier.App.Router.reopen
location: 'history'
rootURL: '/supplier'
Qsupplier.App.Router.map ->
@resource 'sections', ->
@resource 'section', path: ':section_id'
@@ -0,0 +1,11 @@
Qsupplier.App.IndexRoute = Ember.Route.extend
model: ->
Ember.Object.create
lists: Qsupplier.App.List.find({state: 'active'})
orders: Qsupplier.App.Order.find()
#setupController: (controller, model)->
#controller.set('model', model)
#controller.set 'lists', Qsupplier.App.List.all() #.filterProperty('state', 'active')
#controller.set 'orders', Qsupplier.App.Order.all()
#controller.set 'lists', model.get('lists')
#controller.set 'orders', model.get('orders')
@@ -0,0 +1,3 @@
Qsupplier.App.SectionRoute = Ember.Route.extend
renderTemplate: ->
@render 'section'
@@ -0,0 +1,5 @@
Qsupplier.App.SectionsRoute = Ember.Route.extend
model: -> Qsupplier.App.Section.find()
setupController: (controller, collection) ->
controller.set 'content', collection
@@ -0,0 +1,7 @@
# http://emberjs.com/guides/models/defining-a-store/
Qsupplier.App.Store = DS.Store.extend
revision: 11
adapter: DS.RESTAdapter.create
namespace: 'supplier'
@@ -0,0 +1,14 @@
td.list-status
if view.content.needs_help
span.list-needs-help-indicator ?
if view.content.needs_payment
span.list-needs-payment-indicator &euro;
td.numeric.table_number {{view.content.table_number}}
td.section_title {{view.content.section_title}}
td.currency.total_list_amount {{currency total_amount}}
td.actions
if view.content.needs_help
button.btn.btn-info{ action markListAsHelped view.content.id} {{t 'list.is_helped_button'}}
button.btn.btn-warning{ action closeList view.content.id} {{t 'list.close_list' }}
a.btn href="/supplier/lists/{{unbound view.content.id}}"
span.icon-list &nbsp;
@@ -0,0 +1,8 @@
td {{view.content.display}}
td.numeric.table_number {{view.content.table_number}}
td.section_title {{view.content.section_title}}
td.currency {{currency total_amount}}
td.actions
/*<button id="order-in-process-button-{{id}}" class="btn btn-success {{^can_process}}hide{{/can_process}}" onclick="Qsupplier.mark_order_in_process('{{id}}')" data-t="order.being_processed"></button>*/
/*<button class="btn btn-inverse" onclick="Qsupplier.mark_order_delivered('{{id}}')" data-t="order.being_served"></button>*/
' Actions
@@ -0,0 +1 @@
{{outlet}}
@@ -0,0 +1,28 @@
.page-header
h3 {{t 'active_lists.title'}}
.well
table.active-lists-table.table
thead
tr
th.status-icons
th.numeric {{t 'table_number'}}
th {{t 'models.section'}}
th.currency {{t 'active_lists.price'}}
th.actions
tbody
each list in controller.active_lists
' {{view 'Qsupplier.App.ActiveListView' contentBinding=list}}
.page-header
h3 {{t 'active_orders.title' }}
.well
table.active-orders-table.table
thead
tr
th {{t 'models.order'}}
th.numeric {{t 'table_number'}}
th {{t 'models.section'}}
th.currency {{t 'active_orders.price'}}
th.actions
tbody
each order in controller.active_orders
' {{view 'Qsupplier.App.ActiveOrderView' contentBinding=order}}
@@ -0,0 +1,26 @@
.section-manage-tables.pull-right
if editmode
.btn-group
a.btn.dropdown-toggle data-toggle="dropdown" href="#"
span Action
span.caret
ul.dropdown-menu
li
a{action addTables} {{t 'section.add_tables.button_label'}}
li
a{action arrangeTables} {{t 'section.arrange_tables.modal.title'}}
li
a href="{{route 'qr_codes_suppliers_tables_path' section_id=id}}" {{t 'tables.qr_codes.link'}}
li
a href="{{route 'suppliers_section_path' id}}" data-method="delete" data-confirm="{{t 'helpers.links.are_you_sure' bare=true}}" {{t 'helpers.links.destroy'}}
view Ember.TextField valueBinding="title"
view Ember.TextField valueBinding="width" classNames="dimension"
span x
view Ember.TextField valueBinding="height" classNames="dimension"
a.btn.btn-mini{ action finishEditable}
span.icon-ok
else
a.btn.btn-mini{ action makeEditable }
span.icon-pencil
each table in tables
view 'Qsupplier.App.SectionTableView' contentBinding="table"
@@ -0,0 +1,6 @@
<ul class="nav nav-tabs">
{{#each section in controller}}
{{#link-to "section" section tagName="li" href=false}}{{view 'Qsupplier.App.SectionTabHeaderView' contentBinding="section"}}{{/link-to}}
{{/each}}
</ul>
{{outlet}}
@@ -0,0 +1,5 @@
.table-number {{table.number}}
.status-icons
span.needs_payment.icon-flag
span.needs_help.icon-bell
span.active_order.icon-glass
@@ -0,0 +1,3 @@
Qsupplier.App.ActiveListView = Ember.View.extend
tagName: 'tr'
templateName: 'active_list'
@@ -0,0 +1,6 @@
Qsupplier.App.ActiveOrderView = Ember.View.extend
tagName: 'tr'
templateName: 'active_order'
classNameBindings: ['content.active:active', 'content.delivered:delivered']
didInsertElement: ->
debugger
@@ -0,0 +1,19 @@
Qsupplier.App.SectionTabHeaderView = Ember.View.extend DragNDrop.Droppable,
template: Ember.Handlebars.compile('{{view.content.title}}')
tagName: 'a'
attributeBindings: ['href']
href: (-> Routes.suppliers_section_path(@content.id)).property()
dragEntered: (view)->
return false
# Changing the route for now is too difficult. Just do a move
#if view.constructor.toString().match(/SectionTableView$/)
#@get('controller').transitionToRoute 'section', @get('content')
dropped: (view)->
if view.constructor.toString().match(/SectionTableView$/)
table = view.get('content')
table.set 'section', @content
console.log "dirty? #{table.get('isDirty')}"
#table.get('transaction').commit()
table.save()
didInsertElement: ->
@$el = $ @get('element')
@@ -0,0 +1,40 @@
Qsupplier.App.SectionTableView = Ember.View.extend DragNDrop.Draggable,
templateName: 'table'
classNames: ['section-table']
classNameBindings: [
'content.active_list:occupied',
'controller.editmode:draggable',
'content.active_list.needs_help:needs_help',
'content.active_list.needs_payment:needs_payment',
'content.active_list.has_active_orders:active_order'
]
offsetX: ->
(@content.get('position_x') || 0) * @containerWidth() / (@content.get('section').get('width') || 1)
offsetY: (->
(@content.get('position_y') || 0) * @containerHeight() / (@content.get('section').get('height') || 1)
)
activeList: (->
!!@get('content.active_list_id')
).property('content.active_list_id')
attributeBindings: ['style']
style: (->
"position:absolute;width:83px;height:48px"
).property()
draggable: (-> if @get('controller.editmode') then 'true' else 'false' ).property('controller.editmode')
placeInSection: ->
@$el.css 'left', @offsetX()
@$el.css 'top', @offsetY()
didInsertElement: ->
@$el = $ @get('element')
@placeInSection()
positionChange: (position)->
@$el.css 'left', position.left
@$el.css 'top', position.top
@content.setProperties
position_x: position.left*@content.get('section').get('width') / @containerWidth()
position_y: position.top *@content.get('section').get('height') / @containerHeight()
@content.get('transaction').commit()
containerWidth: ->
$(@get('parentView.element')).width()
containerHeight: ->
$(@get('parentView.element')).height()
@@ -0,0 +1,14 @@
Qsupplier.App.SectionView = Ember.View.extend DragNDrop.Droppable,
classNames: ['well', 'section-tables-container', 'section-tables-active']
didInsertElement: ->
@$el = $(@get('element'))
height = @$el.width() * @get('controller.model.height') / @get('controller.model.width')
@$el.css('height', height)
dropped: (view, position)->
view.positionChange(position, @content)
observeSectionDimensions: (->
return unless @get('element')
@$el = $(@get('element'))
height = @$el.width() * @get('controller.model.height') / @get('controller.model.width')
@$el.css('height', height)
).observes('controller.model.height', 'controller.model.width')
@@ -17,10 +17,13 @@
// require bootstrap-popover
// require bootstrap-typeahead
//= require bootstrap
//= require handlebars
//= require faye
//= require supplier/base
//= require js-routes
//= require qwaiter
//= require ./qsupplier
//= require handlebars
//= require ./app/application
//= require faye
//= require ./base
//= require qtip
//= require_directory .
//= require_self
@@ -4,29 +4,33 @@ root.Qsupplier=
faye = new Faye.Client(event_host)
faye.subscribe "/supplier/"+supplier_id, (e)=>
if(e.event == 'new_order')
Qsupplier.App.Order.create(e.data.order)
# old stuff
body = $('#active-orders-table tbody')
order = new Order(e.data)
order = new Order(e.data.order)
if body.length
body.append @mustache('#active-order-template', order)
$('.section-table-list-'+order.list_id()).addClass('active_order')
else if(e.event == 'list_needs_help')
if list = Qsupplier.App.List.findCached(e.data.id)
list.set('needs_help', true)
# old stuff
$('#list-needs-help-indicator-'+e.data.id).removeClass('hide')
$('#list-is-helped-button-'+e.data.id).removeClass('hide')
$('.section-table-list-'+e.data.id).addClass('needs_help')
else if(e.event == 'list_needs_payment')
if list = Qsupplier.App.List.findCached(e.data.id)
list.set('needs_payment', true)
# old stuff
$('#list-needs-payment-indicator-'+e.data.id).removeClass('hide')
$('.section-table-list-'+e.data.id).addClass('needs_payment')
else if(e.event == 'list_added') # DEPRICATED now handled by list_update
list = new List(e.data)
$('#active-lists-table tbody').append @mustache('#active-list-template', list)
# Add classes to section table view
table = $('#section-table-'+list.table_id())
table.addClass('section-table-list-'+list.id())
table.addClass('occupied')
table.addClass('needs_help') if list.needs_help()
table.addClass('needs_payment') if list.needs_payment()
else if(e.event == 'list_is_paid')
if list = Qsupplier.App.List.findCached(e.data.id)
list.set('needs_payment', false)
else if e.event == 'list_update'
list = new List(e.data)
Qsupplier.App.List.updateOrCreate(e.data.list)
# old stuff
list = new List(e.data.list)
row = $('#list-row-'+list.id())
content = @mustache('#active-list-template', list)
if row.length then row.replaceWith(content) else $('#active-lists-table tbody').append(content)
@@ -38,11 +42,16 @@ root.Qsupplier=
table.addClass('needs_payment') if list.needs_payment()
table.addClass('active_order') if list.has_active_orders()
else if e.event == 'list_closed'
if list = Qsupplier.App.List.findCached(e.data.id)
list.set('table', null)
list.set('state', 'closed')
$('#list-row-'+e.data.id).remove()
$('.of-list-'+e.data.id).remove()
table_list_class = 'section-table-list-'+e.data.id
$('.'+table_list_class).removeClass('occupied needs_help needs_payment active_order').removeClass(table_list_class)
else if e.event == 'list_helped'
if list = Qsupplier.App.List.findCached(e.data.id)
list.set('needs_help', false)
list_id = e.data.id
$('#list-needs-help-indicator-'+list_id).addClass('hide')
$('#list-is-helped-button-'+list_id).addClass('hide')
@@ -15,6 +15,7 @@ var $translations = {
}
}
$transformation_mappings = {
downcase: 'toLowerCase',
upcase: 'toUpperCase'
@@ -17,7 +17,7 @@
margin-right: 7px
&.hide
display: none
#active-orders-table
.active-orders-table
tbody
tr
td
@@ -1,4 +1,3 @@
$table-width: 83px
.section-title
font-size: 24px
padding: 4px 0px
@@ -7,9 +6,10 @@ $table-width: 83px
margin: -26px 6px 4px 6px
.section-table
background-color: #ccc
//TODO remove width and height for ember control
height: 48px
width: 83px
background-repeat: no-repeat
width: $table-width
color: black
a
color: black
@@ -31,6 +31,10 @@ body
margin: 0
.location_picker_search
float: left
.draggable
cursor: move !important
input.dimension
width: 40px
.location_picker_map
width: 600px
height: 500px
+1 -1
View File
@@ -1,7 +1,7 @@
class ApplicationController < ActionController::Base
before_filter :set_locale
layout :layout_by_resource
protect_from_forgery
#protect_from_forgery
rescue_from SimplyStored::RecordNotFound, with: :show_404
@@ -13,6 +13,8 @@ module Suppliers
end
if params[:show_all] == 'yes'
@lists = List.for_supplier(current_supplier, page: params[:page], per_page: params[:per_page] || 25)
elsif params[:state] == 'active'
@lists = List.active_for_supplier(current_supplier.id)
else
@lists = List.for_supplier_created_at current_supplier, @start_time..@end_time
end
@@ -31,7 +33,7 @@ module Suppliers
respond_to do |format|
format.html {}
format.json do
render json: @list.with_orders_as_json
render json: {list: @list.with_orders_as_json}
end
end
end
@@ -0,0 +1,18 @@
module Suppliers
class OrdersController < Suppliers::ApplicationController
# GET /tables
# GET /tables.json
def index
if params[:state] == 'active'
@orders = Order.active_for_supplier(current_supplier.id)
else
@orders = Order.for_supplier(current_supplier, page: params[:page], per_page: params['per_page'] || 10)
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: {orders: @orders.map(&:with_products_as_json)} }
end
end
end
end
@@ -86,10 +86,9 @@ module Suppliers
end
def preview_products
@date = Date.parse(params[:date]) rescue Date.today
product_categories = ProductCategory.for_supplier_in_time(current_supplier, @date.to_time)
@time = Time.parse(params[:date]) rescue Time.now
product_categories = ProductCategory.for_supplier_in_time(current_supplier, @time)
render json: {categories: product_categories.map(&:to_client_format).select(&:present?)}
end
end
end
@@ -19,9 +19,10 @@ module Suppliers
# GET /sections/1.json
def show
@section = Section.find_by_supplier_id_and_id!(current_supplier.id, params[:id])
@tables = @section.tables_with_active_list_id
respond_to do |format|
format.html # show.html.erb
format.html { render action: 'tables_view' }# show.html.erb
format.json { render json: @section }
end
end
@@ -103,7 +104,7 @@ module Suppliers
# GET /sections/1/tables_view.json
def tables_view
@section = Section.find_by_supplier_id_and_id!(current_supplier.id, params[:id])
@tables = Table.enrich_active_list_id(@section.tables)
@tables = @section.tables_with_active_list_id
respond_to do |format|
format.html # show.html.erb
@@ -57,8 +57,8 @@ module Suppliers
end
end
# PUT /tables/1
# PUT /tables/1.json
# PUT /supplier/tables/1
# PUT /supplier/tables/1.json
def update
@table= Table.find_by_supplier_id_and_id!(current_supplier.id, params[:id])
+27 -19
View File
@@ -1,5 +1,6 @@
class List
include SimplyStored::Couch
include ActiveModel::SerializerSupport
per_page_method :limit_value #kaminari
property :state, default: 'active' # active, #closed
@@ -8,8 +9,8 @@ class List
property :closed_at, type: Time
property :join_requests, type: Array, default: []
property :price, type: Float
property :is_payed, type: :boolean, default: false
property :payed_at, type: Time
property :is_paid, type: :boolean, default: false
property :paid_at, type: Time
has_many :orders, dependent: :destroy
belongs_to :table
@@ -121,11 +122,6 @@ class List
database.view(for_supplier_view({startkey: [supplier.id, range.last], endkey: [supplier.id, range.first], include_docs: true, reduce: false, descending: true}.merge(options)))
end
def mark_as_payed
self.is_payed = true
self.payed_at = Time.now
end
def close!
orders.include_relation(:product_orders)
set_price
@@ -142,6 +138,16 @@ class List
end
end
def needs_help!
self.needs_help = true
if save
for user_id in user_ids
broadcast_user user_id, 'list_needs_help', id: id
end
broadcast_supplier(supplier_id, 'list_needs_help', id: id)
end
end
def is_helped!
self.needs_help = false
if save
@@ -162,6 +168,18 @@ class List
end
end
def is_paid!
self.is_paid = true
self.paid_at ||= Time.now
if save
for user_id in user_ids
broadcast_user user_id, 'list_is_paid', id: id
end
broadcast_supplier supplier_id, 'list_is_paid', id: id
end
end
def move_to_table! to_table
UserTableMove.create list: self, from_table_id: table_id, to_table: to_table
from_table = self.table_id.try(:dup)
@@ -180,16 +198,6 @@ class List
end
end
def needs_help!
self.needs_help = true
if save
for user_id in user_ids
broadcast_user user_id, 'list_needs_help', id: id
end
broadcast_supplier(supplier_id, 'list_needs_help', id: id)
end
end
def approve_join_request_for_user!(user)
if join_requests.include?(user.id)
join_requests.delete(user.id)
@@ -271,8 +279,8 @@ class List
for user_id in user_ids
broadcast_user user_id, 'new_order', order: order.with_products_as_json, total_amount: price
end
broadcast_supplier supplier.id, 'new_order', order.with_products_as_json
broadcast_supplier supplier.id, 'list_update', with_info_as_json
broadcast_supplier supplier.id, 'list_update', list: with_info_as_json
broadcast_supplier supplier.id, 'new_order', order: order.with_products_as_json
order
end
+11 -1
View File
@@ -27,6 +27,14 @@ class Order
view :by_supplier_id_and_id, key: [:supplier_id, :_id] # Do not comment me out
def self.for_supplier(supplier, options = {})
total_entries = database.view(by_supplier_id_and_id({startkey: ["#{supplier.id}\u9999"], endkey: [supplier.id], include_docs: false, reduce: true, descending: true}))
options[:total_entries] = total_entries
with_pagination_options(options) do |options|
database.view(by_supplier_id_and_id({startkey: ["#{supplier.id}\u9999"], endkey: [supplier.id], include_docs: true, reduce: false, descending: true}.merge(options)))
end
end
# Return all currently active orders for a given supplier
def self.active_for_supplier(supplier_id)
database.view(active_for_supplier_view(startkey: [supplier_id], endkey: [supplier_id, {}], reduce: false, include_docs: true))
@@ -92,6 +100,7 @@ class Order
def as_json(*args)
h = super.with_indifferent_access
h[:id] = h[:_id]
h[:table_number] = table_number
h[:section_title] = list.table.section.try(:title)
h
@@ -105,7 +114,8 @@ class Order
order_total = 0.0
for product_order in product_orders
order_total += (product_order.amount * product_order.price).round(2)
ho[:products] << {name: product_order.product.name, id: product_order.product_id, number: product_order.amount, price: product_order.price}
# Use product order id as id since the price can be different for products and the state should be preserved
ho[:products] << {name: product_order.product.name, id: product_order.id, number: product_order.amount, price: product_order.price}
end
ho[:total_amount] = order_total.round(2)
@with_products_as_json = ho
+7 -2
View File
@@ -1,6 +1,7 @@
class Section
include SimplyStored::Couch
include Qwaiter::Distribution
include ActiveModel::SerializerSupport
property :title
property :path, type: Array, default: [[0.0, 0.0], [20.0, 30.0]] # default width 20m height 30m
@@ -61,10 +62,14 @@ class Section
end
end
def as_json
super.merge(width: width, height: height)
def tables_with_active_list_id
Table.enrich_active_list_id(tables)
end
#def as_json(*)
#super.merge(width: width, height: height)
#end
def for_tables_as_json
return @for_tables_as_json if @for_tables_as_json.present?
h = as_json
+8
View File
@@ -1,5 +1,6 @@
class Table
include SimplyStored::Couch
include ActiveModel::SerializerSupport
per_page_method :limit_value #kaminari
property :number, type: Fixnum, default: 1
@@ -41,10 +42,15 @@ class Table
end
end
def serializable_hash
attributes
end
def 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?
end
def occupied=(val) end
def self.enrich_active_list_id(tables)
if tables.is_a?(Array)
@@ -77,9 +83,11 @@ class Table
def width
2.0
end
def width=(val) end
# Method returning the sections table height
def height
2.0
end
def height=(val) end
end
+4
View File
@@ -0,0 +1,4 @@
class ListSerializer < Qwaiter::Serializer
embed :ids
attributes :state, :needs_help, :needs_payment, :is_paid, :price, :table_id, :table_number
end
+4
View File
@@ -0,0 +1,4 @@
class OrderSerializer < Qwaiter::Serializer
embed :ids
attributes :state, :list_id
end
+5
View File
@@ -0,0 +1,5 @@
class SectionSerializer < Qwaiter::Serializer
embed :ids, include: true
attributes *%i[title path width height]
has_many :tables
end
+7
View File
@@ -0,0 +1,7 @@
class TableSerializer < Qwaiter::Serializer
attributes(*%i[number width height position_x position_y section_id occupied active_list_id])
def occupied
object.active_list_id.present?
end
end
+3
View File
@@ -72,6 +72,9 @@ html lang="en"
= content_for?(:content) ? yield(:content) : yield
- if content_for?(:row)
.row= yield :row
.row
.span12
#app
= javascript_include_tag "supplier/application"
script#alert-template[type="text/html"]= mustache_template 'supplier/alert'
= yield :footer
+1 -1
View File
@@ -1,5 +1,5 @@
.page-header
h3 = t('supplier.active_lists.title', lists: List.model_name.human_plural)
h3 = t('supplier.active_lists.title')
.well
table#active-lists-table.table
thead
+1 -1
View File
@@ -1,7 +1,7 @@
.page-header
h3 = t('supplier.active_orders.title', orders: Order.model_name.human_plural)
.well
table#active-orders-table.table
table#active-orders-table.active-orders-table.table
thead
tr
th= Order.model_name.human
@@ -17,8 +17,53 @@
- @tables.each do |table|
.section-table-menu-content class="section-table-menu-#{table.id} section-table-list-#{table.active_list_id}"
button.btn.btn-info.list-is-helped.hide Question answered!
#add-tables-modal.modal.hide.fade tabindex=-1 role=:dialog aria-labeledby='add-tables-modal-label' aria-hidden=true
.modal-header
button.close type=:button data-dismiss=:modal aria-hidden=true x
h3#add-tables-modal-label data-t='section.add_tables.modal.title' = t('supplier.section.add_tables.modal.title')
.modal-body
p data-t='section.add_tables.modal.body_header' = t('supplier.section.add_tables.modal.body_header')
form.form-horizontal
.control-group
label.control-label for='add-tables-number-start' data-t='section.add_tables.modal.number_start' = t('supplier.section.add_tables.modal.number_start')
.controls
input.input-mini#add-tables-number-start type=:number value=100
.control-group
label.control-label for='add-tables-number-end' data-t='section.add_tables.modal.number_end' = t('supplier.section.add_tables.modal.number_end')
.controls
input.input-mini#add-tables-number-end type=:number value=120
.modal-footer
button.btn data-dismiss="modal" aria-hidden=true data-t='section.add_tables.modal.close_button'
button.btn.btn-primary onclick="Qsupplier.add_tables_to_active_section()" data-t='section.add_tables.modal.add_button'
#arrange-tables-modal.modal.hide.fade tabindex=-1 role=:dialog aria-labeledby='add-tables-modal-label' aria-hidden=true
button.close type=:button data-dismiss=:modal aria-hidden=true x
h3#arrange-tables-modal-label data-t='section.arrange_tables.modal.title' = t('supplier.section.arrange_tables.modal.title')
.modal-body
p data-t='section.arrange_tables.modal.body_header' = t('supplier.section.arrange_tables.modal.body_header')
form.form-horizontal
.control-group
label.control-label for='arrange-tables-distributed' data-t='section.arrange_tables.modal.distributed' = t('supplier.section.arrange_tables.modal.distributed')
.controls
input#arrange-tables-distributed type="radio" name="arrange-table-option" checked=true value="distributed"
.control-group
label.control-label for='arrange-tables-by_row' data-t='section.arrange_tables.modal.by_row' = t('supplier.section.arrange_tables.modal.by_row')
.controls
input#arrange-tables-by_row type="radio" name="arrange-table-option" value="by_row"
label for="arrange-tables-by-row-count" data-t='section.arrange_tables.modal.by_row_count' = t('supplier.section.arrange_tables.modal.by_row_count')
input.input-mini#arrange-tables-by-row-count type="text" value=0
'
span data-t='models.plural.table'
.control-group
label.control-label for='arrange-tables-by_column' data-t='section.arrange_tables.modal.by_column' = t('supplier.section.arrange_tables.modal.by_column')
.controls
input#arrange-tables-by_column type="radio" name="arrange-table-option" value="by_column"
label for="arrange-tables-by-column-count" data-t='section.arrange_tables.modal.by_column_count' = t('supplier.section.arrange_tables.modal.by_column_count')
input.input-mini#arrange-tables-by-column-count type="text" value=0
'
span data-t='models.plural.table'
.modal-footer
button.btn data-dismiss="modal" aria-hidden=true data-t='section.arrange_tables.modal.close_button'
button.btn.btn-primary onclick="Qsupplier.arrange_tables_of_active_section()" data-t='section.arrange_tables.modal.arrange_button'
- content_for :footer do
javascript:
var current_section_id = '#{@section.id}';
+3
View File
@@ -72,6 +72,9 @@ module Qwaiter
# Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true
config.handlebars.templates_root = %w[supplier/app/templates]
config.generators do |g|
g.orm :simply_stored
g.template_engine :slim
+2
View File
@@ -13,6 +13,8 @@ Qwaiter::Application.configure do
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.ember.variant = :development
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
config.action_mailer.delivery_method = :letter_opener
+2
View File
@@ -17,6 +17,8 @@ Qwaiter::Application.configure do
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
config.ember.variant = :production
# Generate digests for assets URLs
config.assets.digest = true
+2 -2
View File
@@ -8,10 +8,10 @@ en:
menu:
active_lists: Active lists
active_lists:
title: Active list
title: Active lists
price: Price
active_orders:
title: Active %{orders}
title: Active orders
price: Price
close: Close the shop
you_are_currently_closed_alert: 'You are currently closed and not able to take orders'
+3 -3
View File
@@ -6,12 +6,12 @@ nl:
could_not_arrange_tables_by_row: 'De ${models.plural.table} konden niet worden gepositioneerd. Heeft de ${models.section|downcase} een hoogte en breedte?'
could_not_arrange_tables_by_column: 'De ${models.plural.table} konden niet worden gepositioneerd. Heeft de ${models.section|downcase} een hoogte en breedte?'
menu:
active_lists: Actieve %{lists}
active_lists: Actieve lijsten
active_lists:
title: Actieve %{lists}
title: Actieve lijsten
price: Prijs
active_orders:
title: Actieve %{orders}
title: Actieve orders
price: Prijs
close: De zaak afsluiten voor bestellingen
you_are_currently_closed_alert: 'Je bent momenteel gesloten en kan geen orders ontvangen'
+1
View File
@@ -99,6 +99,7 @@ Qwaiter::Application.routes.draw do
post :sort
end
end
resources :orders, only: [:index, :show]
root to: 'sections#index'
end
+2
View File
@@ -1,4 +1,6 @@
module Qwaiter
extend ActiveSupport::Autoload
autoload :Distribution
autoload :Serializer
end
+5
View File
@@ -0,0 +1,5 @@
module Qwaiter
class Serializer < ActiveModel::Serializer
attribute :_id, key: :id
end
end
+10
View File
@@ -27,4 +27,14 @@ describe Order do
end
end
describe '.for_supplier' do
before { order }
it 'works' do
Order.for_supplier(supplier).should == order
end
it 'paginates'
end
end