Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI for setting the reason why SHF is waiting on an applicant #281

Conversation

weedySeaDragon
Copy link
Collaborator

PT Story: https://www.pivotaltracker.com/story/show/143810729

This is the 2nd PR (the 2nd half) for the story.

Changes proposed in this pull request:

  1. Seed the db with 1 reason: the "other/custom" reason because it is used specifically. (Other reasons can be entered via the usual web pages/interface).
  2. UI: the reasons for waiting has been moved to above the _application status buttons
  3. Uses AJAX to update the db immediately when a reason is selected from the list. The db is also updated immediately when the text for a 'custom/other' reason is entered.

Screenshots (Optional):

reasonwaiting-select-reason-sv

reasonwaiting-select-reason-en


The reason isn't shown if the status is not 'Waiting for Applicant'

reasonwaiting-hidden-unless-status-en


The text field for typing in the "other reason" only shows if that reason is selected

reasonwaiting-other-reason-text-en

Ready for review:
@patmbolger @thesuss @RobertCram

}

input[type="text"]{
padding: 0.3rem 0.3rem;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shorthand form for property padding should be written more concisely as 0.3rem instead of 0.3rem 0.3rem

height: 110%;
}

input[type="text"]{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid qualifying attribute selectors with an element.
Opening curly brace { should be preceded by one space

@@ -1,7 +1,12 @@
.member_app_waiting_reasons {
#member_app_waiting_reasons {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using id selectors
Selector member_app_waiting_reasons should be written in lowercase with hyphens

@@ -0,0 +1,78 @@
-# submit the changed reason via xhr (javascript) whenever the change from the )
-# Do not make user press a "save" or "submit" button for just these changes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment should have a space after the #

@@ -0,0 +1,78 @@
-# submit the changed reason via xhr (javascript) whenever the change from the )

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 consecutive comments can be merged into one


= button_to t('membership_applications.reject_btn'), reject_membership_application_path(@membership_application), {class: 'btn reject', disabled: !(@membership_application.may_reject?)}
= button_to t('membership_applications.ask_applicant_for_info_btn'), need_info_membership_application_path(@membership_application), {class: 'btn need-info', disabled: !(@membership_application.may_ask_applicant_for_info?)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views


= button_to t('membership_applications.accept_btn'), accept_membership_application_path(@membership_application), {class: 'btn accept', disabled: !(@membership_application.may_accept?)}
= button_to t('membership_applications.reject_btn'), reject_membership_application_path(@membership_application), {class: 'btn reject', disabled: !(@membership_application.may_reject?)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

.row
= button_to t('membership_applications.start_review_btn'), start_review_membership_application_path(@membership_application), {class: 'btn start-review', disabled: !(@membership_application.may_start_review?)}

= button_to t('membership_applications.accept_btn'), accept_membership_application_path(@membership_application), {class: 'btn accept', disabled: !(@membership_application.may_accept?)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

#admin-change-status-buttons
%p.header
= "#{t('membership_applications.show.change_status')}:"


= button_to t('membership_applications.start_review_btn'), start_review_membership_application_path(@membership_application), {class: 'btn start-review', disabled: !(@membership_application.may_start_review?)}
.row
= button_to t('membership_applications.start_review_btn'), start_review_membership_application_path(@membership_application), {class: 'btn start-review', disabled: !(@membership_application.may_start_review?)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views


def reason_method(method_prefix, locale)
possible_method = "#{method_prefix}_#{locale}".to_sym
method_name = (AdminOnly::MemberAppWaitingReason.new.respond_to?(possible_method) ? possible_method : AdminOnly::MemberAppWaitingReason.send("default_#{method_prefix}_method".to_sym))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless assignment to variable - method_name.

def self.other_reason_name
I18n.t('admin_only.member_app_waiting_reasons.other_custom_reason')
def self.other_reason_name(locale = I18n.locale)
I18n.t('admin_only.member_app_waiting_reasons.other_custom_reason', locale)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second parameter to the translate method should be an options hash. As it stands now the locale is ignored, and the method always returns the swedish translation

I18n.t('admin_only.member_app_waiting_reasons.other_custom_reason', locale: locale)

end


def self.other_reason_desc(locale = I18n.locale)
I18n.t('admin_only.member_app_waiting_reasons.other_custom_reason_desc', locale)
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@RobertCram
Copy link
Collaborator

Great work, Ashley. Apart from my inline comment, two minor remarks:

  1. There should probably be some sort of protection against changing or deleting the "other/custom reason" record?

  2. In the UI, I would personally prefer the "Other (enter the reason)" to be the last option in the list

select_options= case field.tag_name
when 'select'
options = field.all('option')
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end at 492, 16 is not aligned with case at 489, 18.


select_options= case field.tag_name
when 'select'
options = field.all('option')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless assignment to variable - options.

font-weight: normal;
}

input[type="text"] {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid qualifying attribute selectors with an element.

padding-bottom: 0.5rem;
}

border-bottom: 1pt solid coral;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expected item on line 11 to appear before line 4. Rule sets should be ordered as follows: @extends, @includes without @content, properties, @includes with @content, nested rule sets
Color coral should be written in hexadecimal form as #ff7f50
Color literals like coral should only be used in variable declarations; they should be referred to via variable everywhere else.

width: 3rem;
margin-bottom: 1rem;
.row {
margin-top: 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Properties should be ordered margin-bottom, margin-top, padding-bottom, padding-top

input.wpcf7-form-control.is-custom {
width: 3rem;
margin-bottom: 1rem;
.row {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule declaration should be preceded by an empty line


input.wpcf7-form-control.is-custom {
width: 3rem;
margin-bottom: 1rem;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Properties should be ordered border-bottom, margin-bottom

select_options= case field.tag_name
when 'select'
options = field.all('option')
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end at 492, 16 is not aligned with case at 489, 18.


select_options= case field.tag_name
when 'select'
options = field.all('option')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless assignment to variable - options.

font-weight: normal;
}

input[type="text"] {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid qualifying attribute selectors with an element.

padding-bottom: 0.5rem;
}

border-bottom: 1pt solid coral;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expected item on line 11 to appear before line 4. Rule sets should be ordered as follows: @extends, @includes without @content, properties, @includes with @content, nested rule sets
Color coral should be written in hexadecimal form as #ff7f50
Color literals like coral should only be used in variable declarations; they should be referred to via variable everywhere else.

width: 3rem;
margin-bottom: 1rem;
.row {
margin-top: 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Properties should be ordered margin-bottom, margin-top, padding-bottom, padding-top

input.wpcf7-form-control.is-custom {
width: 3rem;
margin-bottom: 1rem;
.row {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule declaration should be preceded by an empty line


input.wpcf7-form-control.is-custom {
width: 3rem;
margin-bottom: 1rem;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Properties should be ordered border-bottom, margin-bottom

@weedySeaDragon
Copy link
Collaborator Author

weedySeaDragon commented Jun 23, 2017

I know the build fails. I can't figure out why the cucumber feature tests are failing. Any help is appreciated!

fyi: the feature that fail is this file: features/membership-application-status/admin-custom-reason-waiting.feature

.container
.reason-waiting-information
= label_tag :member_app_waiting_reasons, t('membership_applications.need_info.reason_title')
- collection = AdminOnly::MemberAppWaitingReason.all.to_a

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 consecutive Ruby scripts can be merged into a single :ruby filter

.container
#other-text-field
= label_tag :custom_reason_text, t('membership_applications.need_info.other_reason_label')
= text_field_tag :custom_reason_text, @membership_application.custom_reason_text

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

= label_tag :member_app_waiting_reasons, t('membership_applications.need_info.reason_title')
- collection = AdminOnly::MemberAppWaitingReason.all.to_a
- collection << AdminOnly::MemberAppWaitingReason.new(id: -1, "name_#{I18n.locale.to_s}": "#{@other_waiting_reason_text}")
- selected = ! @membership_application.custom_reason_text.blank? ? -1 : @membership_application.member_app_waiting_reasons_id

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

.reason-waiting-information
= label_tag :member_app_waiting_reasons, t('membership_applications.need_info.reason_title')
- collection = AdminOnly::MemberAppWaitingReason.all.to_a
- collection << AdminOnly::MemberAppWaitingReason.new(id: -1, "name_#{I18n.locale.to_s}": "#{@other_waiting_reason_text}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

$reason-border-color: #ff7f50; // coral; picked sort of at random


#member-app-waiting-reasons {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using id selectors

.container
.reason-waiting-information
= label_tag :member_app_waiting_reasons, t('membership_applications.need_info.reason_title')
- collection = AdminOnly::MemberAppWaitingReason.all.to_a

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 consecutive Ruby scripts can be merged into a single :ruby filter

.container
#other-text-field
= label_tag :custom_reason_text, t('membership_applications.need_info.other_reason_label')
= text_field_tag :custom_reason_text, @membership_application.custom_reason_text

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

= label_tag :member_app_waiting_reasons, t('membership_applications.need_info.reason_title')
- collection = AdminOnly::MemberAppWaitingReason.all.to_a
- collection << AdminOnly::MemberAppWaitingReason.new(id: -1, "name_#{I18n.locale.to_s}": "#{@other_waiting_reason_text}")
- selected = ! @membership_application.custom_reason_text.blank? ? -1 : @membership_application.member_app_waiting_reasons_id

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

.reason-waiting-information
= label_tag :member_app_waiting_reasons, t('membership_applications.need_info.reason_title')
- collection = AdminOnly::MemberAppWaitingReason.all.to_a
- collection << AdminOnly::MemberAppWaitingReason.new(id: -1, "name_#{I18n.locale.to_s}": "#{@other_waiting_reason_text}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using instance variables in partials views

$reason-border-color: #ff7f50; // coral; picked sort of at random


#member-app-waiting-reasons {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using id selectors

@weedySeaDragon
Copy link
Collaborator Author

passing locally on my machine with selenium, but not here with semaphore.

teampoltergeist/poltergeist#895

 Unfortunately parse time errors for ES6 features like *let* can be silently swallowed by PhantomJS, so you end up with no errors but also with no JS being actually run.
@weedySeaDragon
Copy link
Collaborator Author

Closing this. Will replace it with with a much cleaner approach that @patmbolger came up with. 👍

We sure did learn a lot about poltergeist, phantom, selenium, and data-remote (oh my!).
Hopefully we'll write up / document that. Meanwhile, where's a short list:

Lessons learned:

  • phantom.js will silently fail if you use let in your Javascript (ECMS 6.0). (Use 'var' instead) Ref: poltergeist issue 823: use of JavaScript's let will fail silently

  • waiting for a "Then I should not see" used expect(page).not_to have_content content. However, this does not make Capybara wait for ajax, which leads to all kind of messes (rails still running while the test is finished, etc.). (This made some of the tests fail due to timeout because they were waiting forever.)
    use Capybara's assert_text instead

  • use data-remote to send info back to the controller, even if the parameters aren't what is 'normally' expected by the Controller. Let the controller parse and deal with whatever parameters are sent. Dealing with them in your Javascript is ugly and harder to maintain.

@patmbolger
Copy link
Collaborator

patmbolger commented Jun 27, 2017

Good list!

In the 2nd item, the assert_ Capybara methods do not wait on outstanding AJAX requests to complete, but they do wait as long as the Capybara timeout setting (which I think is 10 seconds by default). This is usually a much better approach than using Rspec expect.

A 4th item is the mechanism that @RobertCram developed to tell Capybara to wait until outstanding AJAX requests have all completed - that will prove to be useful, I am sure. We should make that a separate test step altogether, so we can use it as needed (e.g. Then I wait until AJAX requests complete). (kind of wonky, but since we don't expose the cute tests to the client I suppose we can get away with it).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants