table management fixes

This commit is contained in:
2013-01-12 13:34:00 +01:00
parent f6b28f84f0
commit b02951aaec
17 changed files with 164 additions and 76 deletions
+1
View File
@@ -1,5 +1,6 @@
window.Qwaiter= window.Qwaiter=
alert: (msg) -> alert: (msg) ->
$('.modal').modal('hide')
template = @mustache('#alert-template', {title: 'Alert', message: msg, close: 'OK'}) template = @mustache('#alert-template', {title: 'Alert', message: msg, close: 'OK'})
$(template).modal() $(template).modal()
false false
@@ -134,10 +134,8 @@ root.Qsupplier=
Qsupplier.build_list_table(body, foot, res) Qsupplier.build_list_table(body, foot, res)
) )
build_list_table: (body, foot, res) -> build_list_table: (body, foot, res) ->
if !res.orders && !res.orders.length
alert('No orders in list')
return
body.html('') body.html('')
return unless res.orders
for order in res.orders for order in res.orders
body.append @mustache('#list-order-template', new Order(order)) body.append @mustache('#list-order-template', new Order(order))
foot.find('.list-total').html(currency(res.total_amount)) foot.find('.list-total').html(currency(res.total_amount))
@@ -160,10 +158,11 @@ root.Qsupplier=
by_row_count = parseInt($('#arrange-tables-by-row-count').val()) by_row_count = parseInt($('#arrange-tables-by-row-count').val())
by_column_count = parseInt($('#arrange-tables-by-column-count').val()) by_column_count = parseInt($('#arrange-tables-by-column-count').val())
if(option == "by_row") if(option == "by_row")
return alert('Please fill in a positive number representing the number of tables per row') unless by_row_count && by_row_count > 0 return @alert(t('section.arrange_tables.by_row_no_row_count')) unless by_row_count && by_row_count > 0
if(option == "by_column") if(option == "by_column")
return alert('Please fill in a positive number representing the number of tables per column') unless by_column_count && by_column_count > 0 return @alert(t('section.arrange_tables.by_column_no_column_count')) unless by_column_count && by_column_count > 0
$.post('/supplier/sections/'+current_section_id+'/arrange_tables', {option: option, row_count: by_row_count, column_count: by_column_count}, -> window.location.reload()) $.post '/supplier/sections/'+current_section_id+'/arrange_tables', {option: option, row_count: by_row_count, column_count: by_column_count}, (response)=>
if response.ok then window.location.reload() else @alert(t(response.message))
false false
mustache: (selector, locals)-> mustache: (selector, locals)->
locs = $.extend(locals, locs = $.extend(locals,
@@ -172,3 +171,4 @@ root.Qsupplier=
currency(Mustache.render(val, this)) currency(Mustache.render(val, this))
) )
Mustache.to_html($(selector).html(), locs) Mustache.to_html($(selector).html(), locs)
alert: Qwaiter.alert
@@ -1,13 +1,14 @@
var $translations = { var $translations = {
en: { en: {
messages: <%= I18n.t('messages', locale: :en).to_json %>,
models: <%= I18n.t('activemodel.models', locale: :en).to_json %>, models: <%= I18n.t('activemodel.models', locale: :en).to_json %>,
attributes: <%= I18n.t('activemodel.attributes', locale: :en).to_json %>, attributes: <%= I18n.t('activemodel.attributes', locale: :en).to_json %>,
helpers: <%= I18n.t('helpers', locale: :en).to_json %>,
<%= I18n.t('supplier', locale: :en).to_json[1..-2] %> <%= I18n.t('supplier', locale: :en).to_json[1..-2] %>
}, },
nl: { nl: {
models: <%= I18n.t('activemodel.models', locale: :nl).to_json %>, models: <%= I18n.t('activemodel.models', locale: :nl).to_json %>,
attributes: <%= I18n.t('activemodel.attributes', locale: :nl).to_json %>, attributes: <%= I18n.t('activemodel.attributes', locale: :nl).to_json %>,
helpers: <%= I18n.t('helpers', locale: :nl).to_json %>,
<%= I18n.t('supplier', locale: :nl).to_json[1..-2] %> <%= I18n.t('supplier', locale: :nl).to_json[1..-2] %>
} }
} }
@@ -15,6 +16,7 @@ $transformation_mappings = {
downcase: 'toLowerCase', downcase: 'toLowerCase',
upcase: 'toUpperCase' upcase: 'toUpperCase'
} }
function t(path, vars){ function t(path, vars){
vars || (vars = {}); vars || (vars = {});
var result, m, translatable, isafety,replacable; var result, m, translatable, isafety,replacable;
@@ -49,11 +49,13 @@ private
message = args.first || '' message = args.first || ''
{ok: false, message: message}.merge(options).to_json {ok: false, message: message}.merge(options).to_json
end end
alias json_alert js_alert
def js_notice(*args) def js_notice(*args)
options = args.extract_options! options = args.extract_options!
message = args.first || '' message = args.first || ''
{ok: true, message: message}.merge(options).to_json {ok: true, message: message}.merge(options).to_json
end end
alias json_notice js_notice
# Return the hostname of the event server # Return the hostname of the event server
def event_host def event_host
@@ -132,11 +132,11 @@ module Suppliers
def arrange_tables def arrange_tables
@section = Section.find_by_supplier_id_and_id!(current_supplier.id, params[:id]) @section = Section.find_by_supplier_id_and_id!(current_supplier.id, params[:id])
case params[:option] case params[:option]
when 'distributed' then @section.arrange_tables_in_grid when 'distributed' then render(json: (@section.arrange_tables_in_grid ? {ok: true} : json_alert('messages.could_not_arrange_tables_distributed')))
when 'by_row' then @section.arrange_tables_in_rows_of(params[:row_count].to_i) when 'by_row' then render(json: (@section.arrange_tables_in_rows_of(params[:row_count].to_i) ? {ok: true} : json_alert('messages.could_not_arrange_tables_by_row')))
when 'by_column' then @section.arrange_tables_in_columns_of(params[:column_count].to_i) when 'by_column' then render(json: (@section.arrange_tables_in_columns_of(params[:column_count].to_i) ? {ok: true} : json_alert('messages.could_not_arrange_tables_by_column')))
else render(json: json_alert('messages.could_not_arrange_tables'))
end end
render json: {ok: true}
end end
end end
end end
+20 -33
View File
@@ -1,5 +1,6 @@
class Section class Section
include SimplyStored::Couch include SimplyStored::Couch
include Qwaiter::Distribution
property :title property :title
property :path, type: Array, default: [] property :path, type: Array, default: []
@@ -77,50 +78,45 @@ class Section
w = width w = width
h = height h = height
n = tables.size n = tables.size
return unless w > 0 && h > 0 && n > 0 return false unless w > 0 && h > 0 && n > 0
l = Math.sqrt((w*h).to_f/n) lx, ly = distribute_lattice(w, h, n)
epsilon = (10 ** -(Float::DIG - 1)).to_f x0 = lx/2
while (w/l).floor * (h/l).floor < n # find a fitting combination
l = if w.remainder(l) < epsilon then (h/l).ceil
elsif h.remainder(l) < epsilon then (w/l).ceil
elsif w.remainder(l) < epsilon && h.remainder(l) < epsilon then [w / (w/l).ceil.succ, h / (h/l).ceil.succ].max # Failsafe for when both are valid and it still does not fit
else [w / (w/l).ceil, h / (h/l).ceil].max end
end
x0 = w.remainder(l - epsilon)/2 # Start with half a remainder space, will end with the other halve
x = x0 x = x0
y = h.remainder(l - epsilon)/2 y = ly/2
saves = [] saves = []
for table in tables.sort_by(&:number) for table in tables.sort_by(&:number)
if x + l > w + (1e4*epsilon) # New row, error = epsilon times possible tables if x > w + (1e4*epsilon) # New row, error = epsilon times possible tables in a row
x = x0 x = x0
y += l y += ly
end end
table.position_x = x + (l/2) - (table_width/2) # Starting point of square + half the square (center) minus half the table size table.position_x = x - (table.width/2) # Starting point of square + half the square (center) minus half the table size
table.position_y = y + (l/2) - (table_height/2) table.position_y = y - (table.height/2)
saves << table.save saves << table.save
x += l x += lx
end end
[l, saves.all?] saves.all?
end end
def arrange_tables_in_rows_of(n) def arrange_tables_in_rows_of(n)
return unless n.present? return false unless n.present?
n = n.to_i n = n.to_i
return unless n > 0 return false unless n > 0
dx = width / n dx = width / n
dy = height / (tables.size.to_f/n).ceil dy = height / (tables.size.to_f/n).ceil
x = 0.0 x = 0.0
y = 0.0 y = 0.0
saves = []
tables.sort_by(&:number).each.with_index do |table, i| tables.sort_by(&:number).each.with_index do |table, i|
table.position_x = x + (dx/2) - (table_width/2) table.position_x = x + (dx/2) - (table.width/2)
table.position_y = y + (dy/2) - (table_height/2) table.position_y = y + (dy/2) - (table.height/2)
x += dx x += dx
if (i + 1).multiple_of?( n ) if (i + 1).multiple_of?( n )
x = 0.0 x = 0.0
y += dy y += dy
end end
table.save saves << table.save
end end
return saves.all?
end end
def arrange_tables_in_columns_of(n) def arrange_tables_in_columns_of(n)
return unless n.present? return unless n.present?
@@ -131,8 +127,8 @@ class Section
x = 0.0 x = 0.0
y = 0.0 y = 0.0
tables.sort_by(&:number).each.with_index do |table, i| tables.sort_by(&:number).each.with_index do |table, i|
table.position_x = x + (dx/2) - (table_width/2) table.position_x = x + (dx/2) - (table.width/2)
table.position_y = y + (dy/2) - (table_height/2) table.position_y = y + (dy/2) - (table.height/2)
y += dy y += dy
if (i + 1).multiple_of?( n ) if (i + 1).multiple_of?( n )
y = 0.0 y = 0.0
@@ -142,13 +138,4 @@ class Section
end end
end end
# Method returning the sections table width
def table_width
2.0
end
# Method returning the sections table height
def table_height
2.0
end
end end
+9
View File
@@ -36,4 +36,13 @@ class Table
number number
end end
# Method returning the sections table width
def width
2.0
end
# Method returning the sections table height
def height
2.0
end
end end
+12
View File
@@ -0,0 +1,12 @@
<div class="modal hide fade" role="dialog" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{{title}}</h3>
</div>
<div class="modal-body">
<p>{{message}}</p>
</div>
<div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal" aria-hidden="true">{{close}}</a>
</div>
</div>
+1 -4
View File
@@ -77,9 +77,6 @@ html lang="en"
= content_for?(:content) ? yield(:content) : yield = content_for?(:content) ? yield(:content) : yield
- if content_for?(:row) - if content_for?(:row)
.row= yield :row .row= yield :row
/!
Javascripts
\==================================================
/! Placed at the end of the document so the pages load faster
= javascript_include_tag "supplier/application" = javascript_include_tag "supplier/application"
script#alert-template[type="text/html"]= mustache_template 'supplier/alert'
= yield :footer = yield :footer
+12 -10
View File
@@ -5,12 +5,12 @@
table.table table.table
thead thead
tr tr
th.link= model_class.human_attribute_name(:title) th.link data-t='attributes.section.title' = model_class.human_attribute_name(:title)
th.table-info= Table.model_name.human_plural th.table-info data-t='models.plural.table' = Table.model_name.human_plural
th.numeric= model_class.human_attribute_name(:width) th.numeric data-t='attributes.section.width' = model_class.human_attribute_name(:width)
th.numeric= model_class.human_attribute_name(:height) th.numeric data-t='attributes.section.height' = model_class.human_attribute_name(:height)
th.timestamp= model_class.human_attribute_name(:created_at) th.timestamp data-t='attributes.section.created_at' = model_class.human_attribute_name(:created_at)
th.actions=t 'helpers.actions' th.actions data-t='helpers.actions' = t 'helpers.actions'
tbody tbody
- @sections.each do |section| - @sections.each do |section|
tr tr
@@ -22,12 +22,14 @@
td.numeric= section.height td.numeric= section.height
td.timestamp=l section.created_at, format: :short td.timestamp=l section.created_at, format: :short
td.actions td.actions
= link_to t('supplier.section.tables_view'), [:tables_view, :suppliers, section], class: [:btn, 'btn-mini btn-info'] = link_to t('supplier.section.tables_view.link'), [:tables_view, :suppliers, section], class: 'btn btn-mini btn-info', data: {t: 'section.tables_view.link'}
' '
= link_to t('helpers.links.edit'), [:edit, :suppliers, section], class: 'btn btn-mini' = link_to t('supplier.section.manage_tables.link'), [:manage_tables, :suppliers, section], class: 'btn btn-mini btn-warning', data: {t: 'section.manage_tables.link'}
' '
= link_to t("helpers.links.destroy"), [:suppliers, section], method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-mini btn-danger' = link_to t('helpers.links.edit'), [:edit, :suppliers, section], class: 'btn btn-mini', data: {t: 'helpers.links.edit'}
'
= link_to t("helpers.links.destroy"), [:suppliers, section], method: :delete, data: {confirm: are_you_sure?, t: 'helpers.links.destroy'}, class: 'btn btn-mini btn-danger'
- else - else
= no_content_given model_class = no_content_given model_class
.form-actions .form-actions
= link_to t("helpers.links.new"), new_suppliers_section_path, class: 'btn btn-primary' = link_to t("helpers.links.new"), new_suppliers_section_path, class: 'btn btn-primary', data: {t: 'helpers.links.new'}
@@ -1,5 +1,6 @@
- model_class = Section - model_class = Section
.page-header data-t='section.manage_tables.title' data-t-attributes=%|{"title":"#{@section.title}"}| .page-header
h1 data-t='section.manage_tables.title' data-t-attributes=%|{"title":"#{@section.title}"}|
- content_for :row do - content_for :row do
ul.nav.nav-tabs ul.nav.nav-tabs
- for section in @section.supplier.sections - for section in @section.supplier.sections
@@ -22,17 +23,17 @@
.table-number = table.number .table-number = table.number
.clearfix .clearfix
.form-actions .form-actions
= link_to t("helpers.links.back"), suppliers_sections_path, class: 'btn' = link_to t("helpers.links.back"), suppliers_sections_path, class: 'btn', data: {t: 'helpers.links.back'}
' '
= link_to t('helpers.links.edit'), [:edit, :suppliers, @section], class: 'btn' = link_to t('helpers.links.edit'), [:edit, :suppliers, @section], class: 'btn', data: {t: 'helpers.links.edit'}
' '
= link_to t('supplier.section.tables_view'), [:tables_view, :suppliers, @section], class: [:btn, 'btn-info'] = link_to t('supplier.section.tables_view.link'), [:tables_view, :suppliers, @section], class: 'btn btn-info', data: {t: 'section.tables_view.link'}
' '
a.btn href='#add-tables-modal' role='button' data-toggle='modal'= t('supplier.section.add_tables.button_label') a.btn href='#add-tables-modal' role='button' data-toggle='modal' data-t='section.add_tables.button_label' = t('supplier.section.add_tables.button_label')
' '
a.btn href='#arrange-tables-modal' role='button' data-toggle='modal'= t('supplier.section.arrange_tables.button_label') a.btn href='#arrange-tables-modal' role='button' data-toggle='modal' data-t='section.arrange_tables.button_label' = t('supplier.section.arrange_tables.button_label')
' '
= link_to t("helpers.links.destroy"), [:suppliers, @section], method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-danger' = link_to t("helpers.links.destroy"), [:suppliers, @section], method: :delete, data: {confirm: are_you_sure?, t: 'helpers.links.destroy' }, class: 'btn btn-danger'
- content_for :footer do - content_for :footer do
javascript: javascript:
var current_section_id = '#{@section.id}'; var current_section_id = '#{@section.id}';
+10 -9
View File
@@ -1,21 +1,22 @@
- model_class = Section - model_class = Section
.page-header= title :show, @section .page-header
h1 data-t='section.show.title'
dl.dl-horizontal.show-list dl.dl-horizontal.show-list
dt= model_class.human_attribute_name(:title) dt data-t='attributes.section.title' = model_class.human_attribute_name(:title)
dd= @section.title dd= @section.title
dl.dl-horizontal.show-list dl.dl-horizontal.show-list
dt= model_class.human_attribute_name(:width) dt data-t='attributes.section.width' = model_class.human_attribute_name(:width)
dd= @section.width dd= @section.width
dl.dl-horizontal.show-list dl.dl-horizontal.show-list
dt= model_class.human_attribute_name(:height) dt data-t='attributes.section.height' = model_class.human_attribute_name(:height)
dd= @section.height dd= @section.height
.form-actions .form-actions
= link_to t("helpers.links.back"), suppliers_sections_path, class: 'btn' = link_to t("helpers.links.back"), suppliers_sections_path, class: 'btn', data: {t: 'helpers.links.back'}
' '
= link_to t('helpers.links.edit'), [:edit, :suppliers, @section], class: 'btn' = link_to t('helpers.links.edit'), [:edit, :suppliers, @section], class: 'btn', data: {t: 'helpers.links.edit'}
' '
= link_to t('supplier.section.manage_tables'), [:manage_tables, :suppliers, @section], class: [:btn, 'btn-warning'] = link_to t('supplier.section.manage_tables.link'), [:manage_tables, :suppliers, @section], class: 'btn btn-warning', data: {t: 'section.manage_tables.link'}
' '
= link_to t('supplier.section.tables_view'), [:tables_view, :suppliers, @section], class: [:btn, 'btn-info'] = link_to t('supplier.section.tables_view.link'), [:tables_view, :suppliers, @section], class: 'btn btn-info', data: {t: 'section.tables_view.link'}
' '
= link_to t("helpers.links.destroy"), [:suppliers, @section], method: :delete, data: {confirm: are_you_sure? }, class: 'btn btn-danger' = link_to t("helpers.links.destroy"), [:suppliers, @section], method: :delete, data: {confirm: are_you_sure?, t: 'helpers.links.destroy'}, class: 'btn btn-danger'
+1
View File
@@ -86,4 +86,5 @@ module Qwaiter
config.assets.version = '1.0' config.assets.version = '1.0'
end end
end end
require 'qwaiter'
require 'rqrcode-rails3' require 'rqrcode-rails3'
+12 -1
View File
@@ -91,6 +91,11 @@ en:
needs_payment: Wants to pay needs_payment: Wants to pay
closed_at: Closed at closed_at: Closed at
supplier: supplier:
messages:
could_not_arrange_tables: 'The tables could not be arranged'
could_not_arrange_tables_distributed: 'The tables could not be arranged. Does the ${models.section|downcase} have a width and a height?'
could_not_arrange_tables_by_row: 'The tables could not be arranged. Does the ${models.section|downcase} have a width and a height?'
could_not_arrange_tables_by_column: 'The tables could not be arranged. Does the ${models.section|downcase} have a width and a height?'
menu: menu:
active_lists: Active lists active_lists: Active lists
active_lists: active_lists:
@@ -111,9 +116,13 @@ en:
title: Show %{list} title: Show %{list}
section: section:
first_section_title: Room first_section_title: Room
show:
title: 'Show ${models.section|downcase}'
manage_tables: manage_tables:
link: 'Manage tables'
title: "Manage tables for ${models.section|downcase}: %{title}" title: "Manage tables for ${models.section|downcase}: %{title}"
tables_view: Tables view tables_view:
link: 'Tables view'
add_tables: add_tables:
button_label: Add tables button_label: Add tables
modal: modal:
@@ -125,6 +134,8 @@ en:
add_button: Add add_button: Add
arrange_tables: arrange_tables:
button_label: Arrange tables button_label: Arrange tables
by_row_no_row_count: 'Please fill in a positive number representing the number of ${models.plural.table|downcase} per row'
by_column_no_column_count: 'Please fill in a positive number representing the number of ${models.plural.table|downcase} per column'
modal: modal:
title: Arrange tables title: Arrange tables
body_header: "" body_header: ""
+12 -1
View File
@@ -100,6 +100,11 @@ nl:
password: 'Wachtwoord' password: 'Wachtwoord'
password_confirmation: 'Bevestiging' password_confirmation: 'Bevestiging'
supplier: supplier:
messages:
could_not_arrange_tables: 'De ${models.plural.table} konden niet worden gepositioneerd'
could_not_arrange_tables_distributed: 'De ${models.plural.table} konden niet worden gepositioneerd. Heeft de ${models.section|downcase} een hoogte en breedte?'
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: menu:
active_lists: Actieve %{lists} active_lists: Actieve %{lists}
active_lists: active_lists:
@@ -120,9 +125,13 @@ nl:
title: "%{list} tonen" title: "%{list} tonen"
section: section:
first_section_title: Ruimte first_section_title: Ruimte
show:
title: 'Toon ${models.section|downcase}'
manage_tables: manage_tables:
link: 'Tafels beheren'
title: "Tafels beheren voor ${models.section|downcase}: %{title}" title: "Tafels beheren voor ${models.section|downcase}: %{title}"
tables_view: Tafel overzicht tables_view:
link: Tafel overzicht
add_tables: add_tables:
button_label: Voeg tafels toe button_label: Voeg tafels toe
modal: modal:
@@ -134,6 +143,8 @@ nl:
add_button: Voeg toe add_button: Voeg toe
arrange_tables: arrange_tables:
button_label: Positioneer tafels button_label: Positioneer tafels
by_row_no_row_count: 'Geef een positief getal voor het aantal ${models.plural.table|downcase} per rij'
by_column_no_column_count: 'Geef een positief getal voor het aantal ${models.plural.table|downcase} per kolom'
modal: modal:
title: Positioneer tafels title: Positioneer tafels
body_header: "" body_header: ""
+4
View File
@@ -0,0 +1,4 @@
module Qwaiter
extend ActiveSupport::Autoload
autoload :Distribution
end
+47
View File
@@ -0,0 +1,47 @@
module Qwaiter
module Distribution
module DistributionMethods
def epsilon
@@epsilon ||= (10 ** -(Float::DIG - 1)).to_f
end
##
# Distribute a section of width w and height h in a length and a width scale
# that makes n tables fit.
# distribute_lattice 10, 10, 3 #=> [5.0, 5.0]
# distribute_lattice 10, 10, 4 #=> [5.0, 5.0]
##
def distribute_lattice(w, h, n)
w, h = w.to_f, h.to_f
area = w*h
l = Math.sqrt(area.to_f/n)
nx = w/l
ny = h/l
while (w/l + epsilon).floor * (h/l + epsilon).floor < n
tx = w/l
ty = h/l
# The biggest remainder is closest to a fitting option
# Just add one if no remainder wins and it still is not enough
if tx.remainder(1) < epsilon && ty.remainder(1) < epsilon
# Both divide, but there is no solution yet. Just add one
l = [w/(tx + 1).round, h/(ty + 1).round].max
nx = tx.ceil
ny = ny.ceil
elsif tx.remainder(1) > ty.remainder(1)
nx = tx.ceil
ny = (n.to_f/nx).ceil
l = w/nx
else
ny = ty.ceil
nx = (n.to_f/ny).ceil
l = h/ny
end
end
[w/nx, h/ny]
end
end
include DistributionMethods
extend DistributionMethods
end
end