Standing Orders: form split into ngForm elements with staggered validation

This commit is contained in:
Rob Harrington
2016-09-23 16:58:58 +10:00
parent ac5fe6a9fb
commit 897eb11512
9 changed files with 66 additions and 47 deletions

View File

@@ -0,0 +1,10 @@
angular.module("admin.standingOrders").controller "DetailsController", ($scope, StatusMessage) ->
$scope.submitted = false
$scope.next = ->
$scope.submitted = true
if $scope.standing_order_details_form.$valid
StatusMessage.clear()
$scope.setView('products')
else
StatusMessage.display 'failure', 'Oops! There seems to be a problem...'

View File

@@ -0,0 +1,9 @@
angular.module("admin.standingOrders").controller "ProductsController", ($scope, StatusMessage) ->
$scope.next = ->
if $scope.standingOrder.standing_line_items.length > 0
StatusMessage.clear()
$scope.setView('review')
else
StatusMessage.display 'failure', 'Please add at least one product'
$scope.back = -> $scope.setView('details')

View File

@@ -7,20 +7,13 @@ angular.module("admin.standingOrders").controller "StandingOrderController", ($s
$scope.errors = StandingOrder.errors
$scope.newItem = { variant_id: 0, quantity: 1 }
$scope.distributor_id = $scope.standingOrder.shop_id # variant selector requires distributor_id
$scope.views = ['details','products','review']
$scope.view = if $scope.standingOrder.id? then $scope.views[$scope.views.length-1] else $scope.views[0]
$scope.view = if $scope.standingOrder.id? then 'review' else 'details'
$scope.save = ->
$scope.standing_order_form.$setPristine()
StandingOrder.save()
$scope.next = ->
viewIndex = $scope.views.indexOf($scope.view)
$scope.view = $scope.views[viewIndex+1]
$scope.back = ->
viewIndex = $scope.views.indexOf($scope.view)
$scope.view = $scope.views[viewIndex-1]
$scope.setView = (view) -> $scope.view = view
$scope.addStandingLineItem = ->
StandingOrder.buildItem($scope.newItem)

View File

@@ -3,9 +3,11 @@ label.disabled {
pointer-events: none;
}
input[type='button']:disabled {
background-color: #c3c3c3;
color: #ffffff;
input[type='button'], input[type='submit'] {
&:disabled {
background-color: #c3c3c3;
color: #ffffff;
}
}
.select2-container-disabled {

View File

@@ -62,10 +62,6 @@ input.search {
float: right;
}
.ng .ng-invalid.ng-dirty {
background-color: #fa787e;
}
a {
cursor:pointer;
}

View File

@@ -1,4 +1,4 @@
input.ng-invalid {
input.ng-invalid.ng-dirty {
border: solid 1px red;
&.update-pending {
@@ -9,4 +9,3 @@ input.ng-invalid {
select.ng-invalid {
border: solid 1px red;
}

View File

@@ -1,37 +1,43 @@
%fieldset
%fieldset.no-border-bottom
%legend{ align: 'center'}= t("admin.standing_orders.form.details")
.row
.four.columns.alpha.field
Customer
.four.columns.field
%input.ofn-select2.fullwidth#customer_id{ name: 'customer_id', type: 'number', data: 'customers', text: 'email', ng: { model: 'standingOrder.customer_id' } }
.error{ ng: { repeat: 'error in errors.customer', show: 'standing_order_form.customer_id.$pristine' } } {{ error }}
%input.ofn-select2.fullwidth#customer_id{ name: 'customer_id', type: 'number', data: 'customers', text: 'email', required: true, ng: { model: 'standingOrder.customer_id' } }
.error{ ng: { show: 'submitted && standing_order_details_form.customer_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.customer', show: 'standing_order_details_form.customer_id.$pristine' } } {{ error }}
.four.columns.field
Schedule
.four.columns.omega.field
%input.ofn-select2.fullwidth#schedule_id{ name: 'schedule_id', type: 'number', data: 'schedules', ng: { model: 'standingOrder.schedule_id' } }
.error{ ng: { repeat: 'error in errors.schedule', show: 'standing_order_form.schedule_id.$pristine'} } {{ error }}
%input.ofn-select2.fullwidth#schedule_id{ name: 'schedule_id', type: 'number', data: 'schedules', required: true, ng: { model: 'standingOrder.schedule_id' } }
.error{ ng: { show: 'submitted && standing_order_details_form.schedule_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.schedule', show: 'standing_order_details_form.schedule_id.$pristine'} } {{ error }}
.row
.four.columns.alpha.field
Payment Method
.four.columns.field
%input.ofn-select2.fullwidth#payment_method_id{ name: 'payment_method_id',type: 'number', data: 'paymentMethods', ng: { model: 'standingOrder.payment_method_id' } }
.error{ ng: { repeat: 'error in errors.payment_method', show: 'standing_order_form.payment_method_id.$pristine' } } {{ error }}
%input.ofn-select2.fullwidth#payment_method_id{ name: 'payment_method_id', type: 'number', data: 'paymentMethods', required: true, ng: { model: 'standingOrder.payment_method_id' } }
%div
.error{ ng: { show: 'submitted && standing_order_details_form.payment_method_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.payment_method', show: 'standing_order_details_form.payment_method_id.$pristine' } } {{ error }}
.four.columns.field
Shipping Method
.four.columns.omega.field
%input.ofn-select2.fullwidth#shipping_method_id{ name: 'shipping_method_id', type: 'number', data: 'shippingMethods', ng: { model: 'standingOrder.shipping_method_id' } }
.error{ ng: { repeat: 'error in errors.shipping_method', show: 'standing_order_form.shipping_method_id.$pristine' } } {{ error }}
%input.ofn-select2.fullwidth#shipping_method_id{ name: 'shipping_method_id', type: 'number', data: 'shippingMethods', required: true, ng: { model: 'standingOrder.shipping_method_id' } }
.error{ ng: { show: 'submitted && standing_order_details_form.shipping_method_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.shipping_method', show: 'standing_order_details_form.shipping_method_id.$pristine' } } {{ error }}
.row
.four.columns.alpha.field
Begins At
.four.columns.field
%input.fullwidth#begins_at{ name: 'begins_at', type: 'text', placeholder: 'Select A Date', datepicker: 'standingOrder.begins_at', ng: { model: 'standingOrder.begins_at' } }
.error{ ng: { repeat: 'error in errors.begins_at', show: 'standing_order_form.begins_at.$pristine' } } {{ error }}
%input.fullwidth#begins_at{ name: 'begins_at', type: 'text', placeholder: 'Select A Date', datepicker: 'standingOrder.begins_at', required: true, ng: { model: 'standingOrder.begins_at' } }
.error{ ng: { show: 'submitted && standing_order_details_form.begins_at.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.begins_at', show: 'standing_order_details_form.begins_at.$pristine' } } {{ error }}
.four.columns.field
Ends at
.four.columns.omega.field
%input.fullwidth#ends_at{ name: 'ends_at', type: 'text', placeholder: 'Optional', datepicker: 'standingOrder.begins_at', ng: { model: 'standingOrder.ends_at' } }
.error{ ng: { repeat: 'error in errors.ends_at', show: 'standing_order_form.ends_at.$pristine' } } {{ error }}
.error{ ng: { repeat: 'error in errors.ends_at', show: 'standing_order_details_form.ends_at.$pristine' } } {{ error }}

View File

@@ -1,13 +1,18 @@
%form.margin-bottom-50{ name: 'standing_order_form', ng: { app: 'admin.standingOrders', controller: 'StandingOrderController' } }
%save-bar{ dirty: "standing_order_form.$dirty" }
%input{ type: "submit", ng: { click: "back()", hide: "view == 'details' || view == 'review'", disabled: "!standing_order_form.$dirty", value: "'Back'" } }
%input.red{ type: "submit", ng: { click: "next()", hide: "view == 'review'", disabled: "!standing_order_form.$dirty", value: "'Next'" } }
%input.red{ type: "submit", ng: { click: "save()", show: "view == 'review'", disabled: "!standing_order_form.$dirty", value: "'Save'" } }
-# %input{ type: "button", ng: { value: "order_cycle_form.$dirty ? 'Cancel' : 'Close'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
%form.margin-bottom-50{ name: 'standing_order_form', novalidate: true, ng: { app: 'admin.standingOrders', controller: 'StandingOrderController', submit: 'save()' } }
%save-bar{ dirty: "standing_order_form.$dirty", persist: 'true', ng: { show: "view == 'review'" } }
%input.red{ type: "submit", value: "Save" }
.details{ ng: { show: "['details','review'].indexOf(view) >= 0" } }
= render 'details'
%ng-form{ name: 'standing_order_details_form', ng: { controller: 'DetailsController' } }
%save-bar{ dirty: "standing_order_details_form.$dirty", persist: 'true', ng: { hide: "view == 'review'" } }
%input{ type: "button", value: 'Back', ng: { click: "back()" } }
%input.red{ type: "button", value: 'Next', ng: { click: 'next()' } }
= render 'details'
.products{ ng: { show: "['products','review'].indexOf(view) >= 0" } }
%ng-form{ name: 'standing_order_products_form', ng: { controller: 'ProductsController' } }
%save-bar{ dirty: "standing_order_products_form.$dirty", persist: 'true', ng: { hide: "view == 'review'" } }
%input{ type: "button", value: 'Back', ng: { click: "back()" } }
%input.red{ type: "button", value: 'Next', ng: { click: 'next()' } }
= render 'autocomplete'
= render 'products'

View File

@@ -27,7 +27,16 @@ feature 'Standing Orders' do
select2_select payment_method.name, from: 'payment_method_id'
select2_select shipping_method.name, from: 'shipping_method_id'
# No date filled out, so error returned
click_button('Next')
expect(page).to have_content 'can\'t be blank'
expect(page).to have_content 'Oops! There seems to be a problem...'
fill_in 'begins_at', with: Date.today.strftime('%F')
click_button('Next')
expect(page).to have_content 'NAME OR SKU'
click_button('Next')
expect(page).to have_content 'Please add at least one product'
# Adding a product and getting a price estimate
targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
@@ -42,16 +51,6 @@ feature 'Standing Orders' do
click_button('Next')
# No date filled out, so error returned
expect{
click_button('Save')
expect(page).to have_content 'Oh no! I was unable to save your changes.'
}.to_not change(StandingOrder, :count)
expect(page).to have_content 'Begins at can\'t be blank'
fill_in 'begins_at', with: Date.today.strftime('%F')
# Date filled out, so submit should be successful
expect{
click_button('Save')
expect(page).to have_content 'Saved'