diff --git a/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee b/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee index 2fac4a4b4f..99110a89d6 100644 --- a/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/directives/order_cycles_selector.js.coffee @@ -1,9 +1,26 @@ -angular.module("admin.orderCycles").directive 'orderCyclesSelector', (OrderCycles, RequestMonitor) -> +angular.module("admin.orderCycles").directive 'orderCyclesSelector', ($timeout, OrderCycles) -> restrict: 'C' templateUrl: 'admin/order_cycles_selector.html' link: (scope, element, attr) -> - scope.availableOptions = - connectWith: '#selected-order-cycles .order-cycles' + scope.orderCycles = OrderCycles.all.filter (oc) -> oc.viewing_as_coordinator - scope.selectedOptions = - connectWith: '#available-order-cycles .order-cycles' + $timeout -> + scope.selections = + available: scope.availableOrderCycles[0] + selected: scope.selectedOrderCycles[0] + + scope.add = (orderCycle) -> + orderCycle ?= scope.selections.available + index = scope.availableOrderCycles.indexOf(orderCycle) + if index > -1 + scope.selectedOrderCycles.push orderCycle + scope.selections.available = scope.availableOrderCycles[index+1] || scope.availableOrderCycles[index-1] + scope.selections.selected = orderCycle + + scope.remove = (orderCycle) -> + orderCycle ?= scope.selections.selected + index = scope.selectedOrderCycles.indexOf(orderCycle) + if index > -1 + scope.selectedOrderCycles.splice(index, 1) + scope.selections.selected = scope.selectedOrderCycles[index] || scope.selectedOrderCycles[index-1] + scope.selections.available = orderCycle diff --git a/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee b/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee index 7a97d51e26..30f033af43 100644 --- a/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/directives/schedule_dialog.js.coffee @@ -13,7 +13,6 @@ angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compi order_cycle_ids: existing?.order_cycle_ids || [] scope.selectedOrderCycles = [] scope.selectedOrderCycles.push orderCycle for orderCycle in (existing?.order_cycles || []) - scope.availableOrderCycles = (orderCycle for id, orderCycle of OrderCycles.byID when orderCycle.id not in scope.schedule.order_cycle_ids) scope.submitted = false scope.errors = [] # Compile modal template diff --git a/app/assets/javascripts/admin/order_cycles/filters/available.js.coffee b/app/assets/javascripts/admin/order_cycles/filters/available.js.coffee new file mode 100644 index 0000000000..9597bfbdf6 --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/filters/available.js.coffee @@ -0,0 +1,7 @@ +angular.module("admin.orderCycles").filter "available", ($filter) -> + return (orderCycles, selectedOrderCycles) -> + return orderCycles unless selectedOrderCycles?.length > 0 + $filter('filter')(orderCycles, (orderCycle) -> + (selectedOrderCycles.indexOf(orderCycle) == -1) && + (orderCycle.coordinator.id == selectedOrderCycles[0].coordinator.id) + ) diff --git a/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml b/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml index d4ef1dcb96..406a12f056 100644 --- a/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml +++ b/app/assets/javascripts/templates/admin/order_cycles_selector.html.haml @@ -1,11 +1,18 @@ -#available-order-cycles - Available - .order-cycles{ ui: { sortable: 'availableOptions' }, ng: { model: "availableOrderCycles" } } - .order-cycle{ ng: { repeat: 'orderCycle in availableOrderCycles' } } - {{ orderCycle.name }} -#selected-order-cycles - Selected - .order-cycles{ ui: { sortable: 'selectedOptions' }, ng: { model: "selectedOrderCycles" } } - .order-cycle{ ng: { repeat: 'orderCycle in selectedOrderCycles' } } - {{ orderCycle.name }} +%table + %tr + %td#available-order-cycles + Available + .order-cycles + .order-cycle{ ng: { repeat: 'orderCycle in orderCycles | available:selectedOrderCycles as availableOrderCycles', click: 'selections.available = orderCycle', dblclick: 'add(orderCycle)', class: '{selected: selections.available == orderCycle}' } } + {{ orderCycle.name }} + %td#add-remove-buttons + %a.add.button{ href: 'javascript:void(0)', ng: { click: 'add()' } } + %i.icon-chevron-right + %a.remove.button{ href: 'javascript:void(0)', ng: { click: 'remove()' } } + %i.icon-chevron-left + %td#selected-order-cycles + Selected + .order-cycles + .order-cycle{ ng: { repeat: 'orderCycle in selectedOrderCycles', click: 'selections.selected = orderCycle', dblclick: 'remove(orderCycle)', class: '{selected: selections.selected == orderCycle}' } } + {{ orderCycle.name }} .error{ ng: { repeat: "error in errors", bind: "error" } } diff --git a/app/assets/stylesheets/admin/order_cycles.scss b/app/assets/stylesheets/admin/order_cycles.scss index a649599ad5..4eebb90c8d 100644 --- a/app/assets/stylesheets/admin/order_cycles.scss +++ b/app/assets/stylesheets/admin/order_cycles.scss @@ -1,26 +1,55 @@ #schedule-dialog { - #available-order-cycles, #selected-order-cycles { - text-align: left; - display: inline-block; - width: 45%; - height: 200px; - max-height: 300px; - width: 45%; + table { + border: none; - .order-cycles { - display: block; - border: 1px solid #dddddd; - height: 100%; - width: 100%; - overflow-x: hidden; - overflow-y: scroll; + tr { + &:hover { + td { background: none; } + } - .order-cycle { - padding: 8px 5px; - cursor: pointer; + td { + border: none; + } - &:hover { - background-color: #cee1f4; + #add-remove-buttons{ + width: 10%; + height: 200px; + max-height: 300px; + + a.button { + display: block; + width: 100%; + margin-bottom: 10px; + color: #ffffff; + font-size: 1em; + } + } + #available-order-cycles, #selected-order-cycles { + text-align: left; + width: 40%; + height: 200px; + max-height: 300px; + + .order-cycles { + display: block; + border: 1px solid #dddddd; + height: 100%; + width: 100%; + overflow-x: hidden; + overflow-y: scroll; + + .order-cycle { + padding: 8px 5px; + cursor: pointer; + + &.selected { + background-color: #b9d1e9; + } + + &:hover { + background-color: #cee1f4; + } + } } } } diff --git a/spec/features/admin/schedules_spec.rb b/spec/features/admin/schedules_spec.rb index 17823bd7d7..1b45ad45d1 100644 --- a/spec/features/admin/schedules_spec.rb +++ b/spec/features/admin/schedules_spec.rb @@ -5,13 +5,15 @@ feature 'Schedules', js: true do include WebHelper context "as an enterprise user" do - let(:user) { create(:user) } + let(:user) { create(:user, enterprise_limit: 10) } let(:managed_enterprise) { create(:distributor_enterprise, owner: user) } let(:unmanaged_enterprise) { create(:distributor_enterprise) } + let(:managed_enterprise2) { create(:distributor_enterprise, owner: user) } let!(:oc1) { create(:simple_order_cycle, coordinator: managed_enterprise, name: 'oc1') } let!(:oc2) { create(:simple_order_cycle, coordinator: managed_enterprise, name: 'oc2') } let!(:oc3) { create(:simple_order_cycle, coordinator: managed_enterprise, name: 'oc3') } - let!(:oc4) { create(:simple_order_cycle, coordinator: unmanaged_enterprise, name: 'oc4') } + let!(:oc4) { create(:simple_order_cycle, coordinator: unmanaged_enterprise, distributors: [managed_enterprise], name: 'oc4') } + let!(:oc5) { create(:simple_order_cycle, coordinator: managed_enterprise2, name: 'oc5') } let!(:weekly_schedule) { create(:schedule, name: 'Weekly', order_cycles: [oc1, oc2, oc3, oc4]) } before { login_to_admin_as user } @@ -23,13 +25,19 @@ feature 'Schedules', js: true do find('a', text: 'NEW SCHEDULE').click within "#schedule-dialog" do + # Only order cycles coordinated by managed enterprises are available to select expect(page).to have_selector '#available-order-cycles .order-cycle', text: oc1.name expect(page).to have_selector '#available-order-cycles .order-cycle', text: oc2.name expect(page).to have_selector '#available-order-cycles .order-cycle', text: oc3.name expect(page).to have_no_selector '#available-order-cycles .order-cycle', text: oc4.name + expect(page).to have_selector '#available-order-cycles .order-cycle', text: oc5.name fill_in 'name', with: "Fortnightly" - find("#available-order-cycles .order-cycle", text: oc1.name).drag_to find("#selected-order-cycles") - find("#available-order-cycles .order-cycle", text: oc3.name).drag_to find("#selected-order-cycles") + find("#available-order-cycles .order-cycle", text: oc1.name).click + find("#add-remove-buttons a.add").click + # Selection of an order cycles limits available options to those with the same coordinator + expect(page).to have_no_selector '#available-order-cycles .order-cycle', text: oc5.name + find("#available-order-cycles .order-cycle", text: oc3.name).click + find("#add-remove-buttons a.add").click click_button "Create Schedule" end @@ -69,7 +77,8 @@ feature 'Schedules', js: true do end within "#schedule-dialog" do - find("#selected-order-cycles .order-cycle", text: oc3.name).drag_to find("#available-order-cycles") + find("#selected-order-cycles .order-cycle", text: oc3.name).click + find("#add-remove-buttons a.remove").click click_button "Update Schedule" end