From 5d02f5d37b5ffd08584ac7f872da2ec4d94f20da Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Fri, 14 Aug 2015 19:02:39 +0200 Subject: [PATCH] Client side table management for supplier sections --- .../section_add_tables_controller.js.coffee | 25 +++++--- ...ection_arrange_tables_controller.js.coffee | 25 +++++--- .../controllers/section_controller.js.coffee | 6 ++ .../app/helpers/distribute_lattice.js.coffee | 36 ++++++++++++ .../supplier/app/models/section.js.coffee | 58 +++++++++++++++++++ .../modals/section_add_tables.emblem | 6 +- .../supplier/app/templates/section.emblem | 9 ++- .../app/views/section/table_view.js.coffee | 2 +- .../components/suppliers-switcher_test.coffee | 7 +-- spec/javascript/models/section_test.coffee | 22 +++++++ spec/javascript/unit/distribution_test.coffee | 16 +++++ spec/javascript/unit/router_test.coffee | 9 +-- wip.md | 9 +-- 13 files changed, 191 insertions(+), 39 deletions(-) create mode 100644 app/assets/javascripts/supplier/app/helpers/distribute_lattice.js.coffee create mode 100644 spec/javascript/models/section_test.coffee create mode 100644 spec/javascript/unit/distribution_test.coffee diff --git a/app/assets/javascripts/supplier/app/controllers/modals/section_add_tables_controller.js.coffee b/app/assets/javascripts/supplier/app/controllers/modals/section_add_tables_controller.js.coffee index 16058d6a..b6f39eaf 100644 --- a/app/assets/javascripts/supplier/app/controllers/modals/section_add_tables_controller.js.coffee +++ b/app/assets/javascripts/supplier/app/controllers/modals/section_add_tables_controller.js.coffee @@ -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' diff --git a/app/assets/javascripts/supplier/app/controllers/modals/section_arrange_tables_controller.js.coffee b/app/assets/javascripts/supplier/app/controllers/modals/section_arrange_tables_controller.js.coffee index 977b3623..9d53cee1 100644 --- a/app/assets/javascripts/supplier/app/controllers/modals/section_arrange_tables_controller.js.coffee +++ b/app/assets/javascripts/supplier/app/controllers/modals/section_arrange_tables_controller.js.coffee @@ -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', '' diff --git a/app/assets/javascripts/supplier/app/controllers/section_controller.js.coffee b/app/assets/javascripts/supplier/app/controllers/section_controller.js.coffee index 47ae442a..26bd6c0b 100644 --- a/app/assets/javascripts/supplier/app/controllers/section_controller.js.coffee +++ b/app/assets/javascripts/supplier/app/controllers/section_controller.js.coffee @@ -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() diff --git a/app/assets/javascripts/supplier/app/helpers/distribute_lattice.js.coffee b/app/assets/javascripts/supplier/app/helpers/distribute_lattice.js.coffee new file mode 100644 index 00000000..49b1f5b0 --- /dev/null +++ b/app/assets/javascripts/supplier/app/helpers/distribute_lattice.js.coffee @@ -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() diff --git a/app/assets/javascripts/supplier/app/models/section.js.coffee b/app/assets/javascripts/supplier/app/models/section.js.coffee index de047ea4..d30b0a07 100644 --- a/app/assets/javascripts/supplier/app/models/section.js.coffee +++ b/app/assets/javascripts/supplier/app/models/section.js.coffee @@ -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 diff --git a/app/assets/javascripts/supplier/app/templates/modals/section_add_tables.emblem b/app/assets/javascripts/supplier/app/templates/modals/section_add_tables.emblem index 2fe05afd..7325bbef 100644 --- a/app/assets/javascripts/supplier/app/templates/modals/section_add_tables.emblem +++ b/app/assets/javascripts/supplier/app/templates/modals/section_add_tables.emblem @@ -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' diff --git a/app/assets/javascripts/supplier/app/templates/section.emblem b/app/assets/javascripts/supplier/app/templates/section.emblem index 7f459399..5eed1a10 100644 --- a/app/assets/javascripts/supplier/app/templates/section.emblem +++ b/app/assets/javascripts/supplier/app/templates/section.emblem @@ -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 diff --git a/app/assets/javascripts/supplier/app/views/section/table_view.js.coffee b/app/assets/javascripts/supplier/app/views/section/table_view.js.coffee index 259ccd54..bd5c0fb6 100644 --- a/app/assets/javascripts/supplier/app/views/section/table_view.js.coffee +++ b/app/assets/javascripts/supplier/app/views/section/table_view.js.coffee @@ -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 = @$() diff --git a/spec/javascript/components/suppliers-switcher_test.coffee b/spec/javascript/components/suppliers-switcher_test.coffee index ff7087c7..d0f4fe56 100644 --- a/spec/javascript/components/suppliers-switcher_test.coffee +++ b/spec/javascript/components/suppliers-switcher_test.coffee @@ -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' diff --git a/spec/javascript/models/section_test.coffee b/spec/javascript/models/section_test.coffee new file mode 100644 index 00000000..78df7368 --- /dev/null +++ b/spec/javascript/models/section_test.coffee @@ -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 + diff --git a/spec/javascript/unit/distribution_test.coffee b/spec/javascript/unit/distribution_test.coffee new file mode 100644 index 00000000..ad031d40 --- /dev/null +++ b/spec/javascript/unit/distribution_test.coffee @@ -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 diff --git a/spec/javascript/unit/router_test.coffee b/spec/javascript/unit/router_test.coffee index 4a3aaf04..2ed6a9ef 100644 --- a/spec/javascript/unit/router_test.coffee +++ b/spec/javascript/unit/router_test.coffee @@ -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' diff --git a/wip.md b/wip.md index dae2ac70..52ab77f1 100644 --- a/wip.md +++ b/wip.md @@ -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