Client side table management for supplier sections

This commit is contained in:
2015-08-14 19:02:39 +02:00
parent 9ca5190c6a
commit 5d02f5d37b
13 changed files with 191 additions and 39 deletions
@@ -1,7 +1,13 @@
App.modals.SectionAddTablesController = App.modals.BaseController.extend
number_start: 100
number_end: 107
number_end: 100
title_path: 'section.add_tables.modal.title'
#number_start: Ember.computed
#get: ->
#@_super() || 100
#set: (key, value)->
#@set 'number_end', value if value
#@_super()
actions:
addTables: ->
s = parseInt(@get('number_start'))
@@ -15,11 +21,14 @@ App.modals.SectionAddTablesController = App.modals.BaseController.extend
e = @get('number_end')
number_of_tables = 1 + e - s
return @set('alert_message', t('section.add_tables.modal.too_many', count: number_of_tables)) if number_of_tables > 10
for number in [s..e]
@store.createRecord 'table', number: number, section: @get('model')
Ember.$.post Routes.add_tables_suppliers_section_path(@get('model.id')),
number_start: s
number_end: e
, (result,state,xhr)=>
#@store.pushPayload 'table', result
@store.pushPayload result
@send 'close'
@send 'close'
#Ember.$.post Routes.add_tables_suppliers_section_path(@get('model.id')),
#number_start: s
#number_end: e
#, (result,state,xhr)=>
## @store.pushPayload 'table', result
#@store.pushPayload result
#@send 'close'
@@ -20,14 +20,23 @@ App.modals.SectionArrangeTablesController = App.modals.BaseController.extend
actions:
arrangeTables: ->
return unless @isValid()
Ember.$.post Routes.arrange_tables_suppliers_section_path(@get('model.id')),
option: @get('arrange_type')
row_count: @get('row_count')
column_count: @get('column_count')
, (result,state,xhr)=>
@store.pushPayload result
@send 'close'
return
#Ember.$.post Routes.arrange_tables_suppliers_section_path(@get('model.id')),
#option: @get('arrange_type')
#row_count: @get('row_count')
#column_count: @get('column_count')
#, (result,state,xhr)=>
#@store.pushPayload result
#@send 'close'
#return
switch @get('arrange_type')
when 'by_row'
@get('model').invoke 'arrange_tables_in_rows_of', parseInt(@get('row_count'))
when 'by_column'
@get('model').invoke 'arrange_tables_in_columns_of', parseInt(@get('column_count'))
else
@get('model').invoke 'arrange_tables_in_grid'
@send 'close'
makeDistributed: ->
@set 'arrange_type', 'distributed'
@set 'alert_message', ''
@@ -6,10 +6,16 @@ App.SectionController = Ember.Controller.extend
finishEditable: ->
@set('editmode', false)
@get('model').save()
@get('model.tables').filterProperty('hasDirtyAttributes').invoke 'save'
@get('model.section_elements').filterProperty('hasDirtyAttributes').invoke 'save'
@get('model.section_areas').filterProperty('hasDirtyAttributes').invoke 'save'
rollbackEditable: ->
@get('model').rollback()
@get('model.tables').forEach (table) ->
if table.get('isNew')
table.deleteRecord()
else
table.rollback()
@get('model.section_elements').forEach (section_element) ->
if section_element.get('isNew')
section_element.deleteRecord()
@@ -0,0 +1,36 @@
class Distribution
##
# 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]
##
distribute_lattice: (w, h, n)->
epsilon = 1e-10
w = parseFloat(w)
h = parseFloat(h)
n = parseInt(n)
area = w*h
l = Math.sqrt(area/n)
nx = w/l
ny = h/l
while Math.floor(w/l + epsilon) * Math.floor(h/l + epsilon) < 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 % 1) < epsilon and (ty % 1) < epsilon
# Both divide, but there is no solution yet. Just add one
l = Math.max(Math.round(w/(tx + 1)), Math.round(h/(ty + 1)))
nx = Math.ceil(tx)
ny = Math.ceil(ny)
else if (tx % 1) > (ty % 1)
nx = Math.ceil(tx)
ny = Math.ceil(n/nx)
l = w/nx
else
ny = Math.ceil(ty)
nx = Math.ceil(n/ny)
l = h/ny
[w/nx, h/ny]
App.Distribution = new Distribution()
@@ -6,3 +6,61 @@ App.Section = DS.Model.extend
tables: DS.hasMany('table')
section_elements: DS.hasMany('section-element')
section_areas: DS.hasMany('section-area')
arrange_tables_in_grid: (tables)->
epsilon = 1e-10
tables ||= @get('tables').sortBy('number')
w = parseFloat(@get('width'))
h = parseFloat(@get('height'))
n = parseInt(tables.get('length'))
unless w > 0 and h > 0 and n > 0
console.log "Cannot arrange tables in grid since not all conditions are met"
return false
[lx, ly] = App.Distribution.distribute_lattice(w, h, n)
return unless lx > 0 and ly > 0
console.log "Distributing tables in grid using lx: #{lx}, ly: #{ly}"
x0 = lx/2
x = x0
y = ly/2
tables.forEach (table)->
if x > w + (1e4*epsilon) # New row, error = epsilon times possible tables in a row
x = x0
y += ly
table.set 'position_x', x - table.get('width')/2 # Starting point of square + half the square (center) minus half the table size
table.set 'position_y', y - table.get('height')/2
x += lx
arrange_tables_in_rows_of: (n, tables)->
return false unless n
n = parseInt(n)
return false unless n > 0
tables ||= @get('tables').sortBy('number')
width = parseFloat(@get('width'))
height = parseFloat(@get('height'))
dx = width / n
dy = height / Math.ceil(tables.get('length')/n)
x = 0.0
y = 0.0
tables.forEach (table, i)->
table.set 'position_x', x + (dx/2) - (table.get('width')/2)
table.set 'position_y', y + (dy/2) - (table.get('height')/2)
x += dx
if (i + 1) % n is 0
x = 0.0
y += dy
arrange_tables_in_columns_of: (n, tables)->
return false unless n
n = parseInt(n)
return false unless n > 0
tables ||= @get('tables').sortBy('number')
width = parseFloat(@get('width'))
height = parseFloat(@get('height'))
dx = width / Math.ceil(tables.get('length') / n)
dy = height / n
x = 0.0
y = 0.0
tables.forEach (table, i)->
table.set 'position_x', x + (dx/2) - (table.get('width')/2)
table.set 'position_y', y + (dy/2) - (table.get('height')/2)
y += dy
if (i + 1) % n is 0
y = 0.0
x += dx
@@ -5,12 +5,12 @@ form.form-horizontal
.form-label
label for='add-tables-number-start'
=t 'section.add_tables.modal.number_start'
.form-field= number-field numericValue=number_start
.form-field= number-field value=number_start
.form-row
.form-label
label for='add-tables-number-end'
=t 'section.add_tables.modal.number_end'
.form-field= number-field numericValue=number_end
.form-field= number-field value=number_end
hr
button.modal-close{action "close"}=t 'section.add_tables.modal.close_button'
button.modal-confirm.right{action "ok"}=t 'section.add_tables.modal.add_button'
button.modal-confirm.right{action "addTables"}=t 'section.add_tables.modal.add_button'
@@ -12,9 +12,6 @@
= number-field numericValue=model.width class="dimension section-edit-width-field"
span.fa.fa-lg.fa-times
= number-field numericValue=model.height class="dimension section-edit-height-field"
a.section-rollback-button{ action "rollbackEditable" }: span
a.section-normal-mode-button{ action "finishEditable" }: span
else
= dropdown-link title="Action"
ul
li: a{action "addTables"}: span.section-add-tables-icon=t 'section.add_tables.button_label'
@@ -23,5 +20,11 @@
li: a{action "addSectionArea"}: span.section-add-section-area-icon= t 'section_area.add_button'
li= qr-codes-link section=content: span.qr-icon= t 'table.print_qr_codes'
li: a.section-destroy{action "destroySection"}: span.section-remove-icon=t 'helpers.links.destroy'
a.section-rollback-button{ action "rollbackEditable" }: span
a.section-normal-mode-button{ action "finishEditable" }: span
else
= dropdown-link title="Action"
ul
li= qr-codes-link section=content: span.qr-icon= t 'table.print_qr_codes'
a.section-edit-mode-button{ action "makeEditable" }: span
= view "section-tables" content=model.tables
@@ -40,7 +40,7 @@ App.SectionTableView = Ember.View.extend DragNDrop.Draggable,
@get('content').setProperties
position_x: position.left / dpm
position_y: position.top / dpm
@get('content').save()
#@get('content').save()
dpm: Ember.computed.alias 'tablesContext.dpm'
didInsertElement: ->
@$el = @$()
@@ -1,8 +1,10 @@
#module "suppliers-switcher", "SuppliersSwitcherComponent"
moduleForComponent "suppliers-switcher"
test "Triggers switch", ->
expect 2
component = @subject()
controller = App.__container__.lookup('controller:settings')
component.set 'targetObject', controller
Ember.run ->
controller.store.createRecord 'supplier',
id: 'other-supplier'
@@ -11,11 +13,8 @@ test "Triggers switch", ->
@render()
equal find('ul').text(), "Switch to Other supplier1"
s_name = null
# Stub the action, since it triggers an external call
component._actions.switchTo = (supplier)->
s_name = supplier.get('name')
equal supplier.get('name'), 'Other supplier1'
click 'li a'
equal s_name, 'Other supplier1'
@@ -0,0 +1,22 @@
moduleForModel 'section', 'Section model',
needs: ['model:section', 'model:table', 'model:section-area', 'model:section-element', 'model:list']
test "arrange_tables_in_grid", ->
section = @subject
width: 20
height: 13
Ember.run ->
table6 = section.store.createRecord 'table', number: 6, section: section
table1 = section.store.createRecord 'table', number: 1, section: section
table19 = section.store.createRecord 'table', number: 19, section: section
section.invoke 'arrange_tables_in_grid'
equal table1.get('position_y'), 2.85
equal table6.get('position_y'), 2.85
equal table19.get('position_y'), 9.35
equal table1.get('position_x'), 4.6
equal table6.get('position_x'), 14.6
equal table19.get('position_x'), 4.6
@@ -0,0 +1,16 @@
test "distribute_lattice", ->
expect 10
test_matrix = [
{input: [20 , 10, 4], expected_output: [10.0, 5.0]},
{input: [10 , 10, 4], expected_output: [ 5.0, 5.0]},
{input: [20 , 5, 4], expected_output: [ 5.0, 5.0]},
{input: [30 , 10, 4], expected_output: [ 7.5, 10.0]},
{input: [10 , 30, 4], expected_output: [10.0, 7.5]},
{input: [10 , 10, 3], expected_output: [ 5.0, 5.0]},
{input: [13.6, 40, 7], expected_output: [ 6.8, 10.0]},
{input: [13.6, 40, 9], expected_output: [ 6.8, 8.0]},
{input: [13.6, 40, 10], expected_output: [ 6.8, 8.0]},
{input: [40, 40, 23], expected_output: [ 8.0, 8.0]},
]
for expectation in test_matrix
deepEqual App.Distribution.distribute_lattice.apply(this, expectation.input), expectation.expected_output
+5 -4
View File
@@ -1,4 +1,5 @@
module 'Router', setup: -> App.reset()
test 'root route', ->
visit '/'
andThen -> equal currentRouteName(), 'index'
#module 'Router', setup: -> App.reset()
#test 'root route', ->
#visit '/'
#andThen ->
#equal currentRouteName(), 'index'
+1 -8
View File
@@ -4,8 +4,6 @@ Release
Supplier
--------
- Add confirmation on order
deletion!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- Allow table drag rollback same as area and element in section edit
mode view
- Move arrange tables logic to the client
@@ -26,13 +24,8 @@ Supplier
User
----
- Fix clicking on product with
variants!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- Implement https://github.com/EddyVerbruggen/Custom-URL-scheme with mozo:// scheme
- test met veel producten
- product variants
- option to make products inactive, no order plus and click on name
opens information
- remove active orders on list close
- fix ajaxError duplicity
- rename "I am signed in as a user" to "there is a signed in user" in
@@ -51,7 +44,7 @@ General
-------
- Loading pages
- Product variants
- Food/allergy information/labels
- Timed delivering
- minimum delay
- What products