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

Save Confirmation - Admin (Part 1 of 3) #14418

Merged
merged 94 commits into from
Sep 2, 2021

Conversation

msarit
Copy link
Contributor

@msarit msarit commented Aug 4, 2021

What type of PR is this? (check all applicable)

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Description

Part 1 of 2 implementing the Admin-Save-Confirmation RFC.
In this PR, I refactor all confirmation steps in the /admin/customization/config page to use async calls. I also update all associated requests and end-to-end tests.

The RFC: https://github.com/forem/rfcs/pull/78/

NOTES

  • Do not let the number of Files changed alarm you 😅 For about 10 files, I merely added the Update Settings button, and added the updateConfigurationSettings callback to the form therein.
  • It has been observed that there is no visual indication if an update failed or didn't "take". I have noted this and will address this UX-improvement in a future PR. 👍🏾

QA Instructions, Screenshots, Recordings

  1. Login to http://localhost:xxxx/admin/customization/config as a super_admin
  2. Make various changes to the settings on this page. After clicking the Update Settings button each time, there should be NO page refresh, and a snackbar with message Successfully updated settings should appear in the bottom-left corner.
  3. Run spec/requests/admin/configs_spec.rb and all tests under cypress/integration/seededFlows/adminFlows/config and make sure they pass.

UI accessibility concerns?

None. No major UI changes made; most changes are backend

Added/updated tests?

  • Yes
  • No, and this is why: please replace this line with details on why tests
    have not been included
  • I need help with writing tests

[Forem core team only] How will this change be communicated?

Will this PR introduce a change that impacts Forem members or creators, the
development process, or any of our internal teams? If so, please note how you
will share this change with the people who need to know about it.

  • I've updated the Developer Docs and/or
    Admin Guide, or
    Storybook (for Crayons components)
  • I've updated the README or added inline documentation
  • I've added an entry to
    CHANGELOG.md
  • I will share this change in a Changelog
    or in a forem.dev post
  • I will share this change internally with the appropriate teams
  • I will update the Admin Guide
  • I'm not sure how best to communicate this change and need help
  • This change does not need to be communicated, and this is why not: please
    replace this line with details on why this change doesn't need to be
    shared

What gif best describes this PR or how it makes you feel?

Captain Marvel

@msarit msarit changed the title Save Confirmation Flow in Admin (Part 1 of 2) Save Confirmation - Admin (Part 1 of 2) Aug 23, 2021
@@ -807,15 +807,17 @@
end

it "unsets appropriate SMTP config, and apply default value if applicable" do
Settings::SMTP.address = "smtp.example.com"
Settings::SMTP.port = 12_345
default_address = ApplicationConfig["SMTP_ADDRESS"].presence || nil
Copy link
Contributor

Choose a reason for hiding this comment

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

We do have Settings::SMTP.address and Settings::SMTP.port which have default values set through the environment, why are we doing this manually here?

field :address, type: :string, default: ApplicationConfig["SMTP_ADDRESS"].presence
...
field :port, type: :integer, default: ApplicationConfig["SMTP_PORT"].presence || 25

Copy link
Contributor Author

@msarit msarit Aug 24, 2021

Choose a reason for hiding this comment

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

Hey @citizen428, locally and on Travis, this spec kept failing, specifically the expectation that the default port was 25 (locally it was 2525 for me). I thought it more robust to expect whatever the default port was on the system running the spec. Same for the default address.

Copy link
Contributor

Choose a reason for hiding this comment

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

😄 I understand and agree with the reasoning. I was more wondering why we use ApplicationConfig directly instead of

Settings::SMTP.get_field(:smtp_port)[:default]

Which is a bit more general.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @citizen428,

So locally, this is what I get for each of these Settings values:

Settings::SMTP.get_field(:smtp_address)[:default]
=> nil

Settings::SMTP.get_field(:smtp_port)[:default]
=> nil

ApplicationConfig["SMTP_PORT"]
=> "2525"

ApplicationConfig["SMTP_ADDRESS"]
=> "smtp.mailtrap.io"

The expectations in the relevant configs_spec.rb specs are now failing when I use the more general Settings::SMTP.get_field.

I'm not sure why these values differ from each other. I think I'll keep use of ApplicationConfig; thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's fine to use ApplicationConfig of course 😃

spec/requests/admin/configs_spec.rb Show resolved Hide resolved
Copy link
Contributor

@aitchiss aitchiss left a comment

Choose a reason for hiding this comment

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

Took this for a spin again locally and looks good to me - nice one @msarit

Comment on lines +39 to +42
cy.findByRole('alert').should(
'have.text',
'Successfully updated settings.',
);
Copy link
Contributor

Choose a reason for hiding this comment

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

nice 🔥

Comment on lines +128 to +132
cy.get('#facebook-auth-btn').click();
cy.get('#settings_authentication_facebook_key').type('randomkey');
cy.get('#settings_authentication_facebook_secret').type('randomsecret');

cy.get('@authSectionForm').findByText('Update Settings').click();
Copy link
Contributor

Choose a reason for hiding this comment

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

just a suggestion and definitely not blocking, but it's a bit more robust to use cy.findByRole or cy.findByLabelText wherever possible, rather than getting by ID selector or inner text

Copy link
Contributor Author

@msarit msarit Aug 24, 2021

Choose a reason for hiding this comment

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

Yes @aitchiss Nick also pointed this out to me yesterday 😊

These cypress tests were existing before my modifications, and the use of cy.get(#id/text) is quite plentiful throughout several files. We decided that making all these tests more robust was beyond the scope of this PR.

@pr-triage pr-triage bot added PR: partially-approved bot applied label for PR's where a single reviewer approves changes and removed PR: unreviewed bot applied label for PR's with no review labels Aug 24, 2021
Comment on lines 121 to 123
outcome.message == null
? this.displaySnackbar(outcome.error)
: this.displaySnackbar(outcome.message);
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor (non-blocking): Use the nullish-coalescing operator.

Suggested change
outcome.message == null
? this.displaySnackbar(outcome.error)
: this.displaySnackbar(outcome.message);
this.displaySnackbar(outcome.message ?? outcome.error)

Copy link
Contributor

Choose a reason for hiding this comment

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

@nickytonline Isn't your suggestion reversed? The first one says display .error when .message == null, yours is the other way around, isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated it. 🙃

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Today I learned! 😅 Thanks Nick.

);
}

async activateLightConfirmation(event) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick (potentially-blocking): It's not clear to me what activateLightConfirmation means. Is this method called activateLightConfirmation because it's not a form post with a full server-side roundtrip? From what it looks like in the context of where this is called, updateConfigurationSettings or updateSettings seems more appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will change

end

format.json do
render json: { error: "😭 #{result.errors.to_sentence}" }, status: :unauthorized
render json: { error: "❗️❗️ #{result.errors.to_sentence}" }, status: :unauthorized
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder how these symbols are going to be read by the screen reader. I understand they're added to catch the attention of the user since we don't have a way to differentiate between errors and non errors in Snackbar and we should have a global notification area for errors or something and that's outside the scope wrt the conversation with Pawel.

I think the Admin team should figure this one out in a future RFC/PR

cc. @aitchiss @ludwiczakpawel

Copy link
Contributor

Choose a reason for hiding this comment

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

We probably don't need any emojis in the error message.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would love it if instead of emojis in the text we could have an optional svg/img icon in the snackbar to convey an error message vs a success/info message. You're right @rhymes in that screen reader behaviour with emojis can vary widely, and what it announces might not be something we intend (e.g. VO on Chrome announces 😭 as "loudly crying face", but this can be different when using a different screen reader/browser/etc)

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I agree with Nick here - removing the emojis from the error messaging. They were already in place when I started this task; I changed the crying-face emoji to the exclamation points as I thought that was more indicative of an error. However, using the emojis re not worth the a11y drawbacks.

Eventually, I would love our snackbars to be customizable in terms of color perhaps, to indicate a successful transaction, as opposed to a failed one. But that's another PR.

@pr-triage pr-triage bot added PR: unreviewed bot applied label for PR's with no review and removed PR: partially-approved bot applied label for PR's where a single reviewer approves changes labels Aug 25, 2021
app/controllers/admin/settings/base_controller.rb Outdated Show resolved Hide resolved
@@ -24,6 +40,8 @@ def extra_authorization_and_confirmation
end

def confirmation_text_valid?
return true unless params.key?(:confirmation)
Copy link
Contributor

Choose a reason for hiding this comment

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

This means that one can theoretically skip the config check for everything by removing :confirmation from the request params with a tool like Charles Proxy or Burp Suite. Not the biggest issue but still something to keep in mind.

@msarit
Copy link
Contributor Author

msarit commented Aug 30, 2021

This means that one can theoretically skip the config check for everything by removing :confirmation from the request params with a tool like Charles Proxy or Burp Suite. Not the biggest issue but still something to keep in mind.

@citizen428 In response to your comment above MK, I determined that we only use the confirmation form within the sections at admin/customization/config. I checked with Pod AdminExp, and since I'm making all config updates async, I have removed the confirmation form code and refactored accordingly.

@msarit
Copy link
Contributor Author

msarit commented Aug 31, 2021

@nickytonline Ready for your re-review!

Copy link
Contributor

@nickytonline nickytonline left a comment

Choose a reason for hiding this comment

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

Thanks for making the changes @msarit! Looking forward to seeing this in production! 🚀

@nickytonline nickytonline merged commit 877cb5c into main Sep 2, 2021
@nickytonline nickytonline deleted the msarit/admin-save-confirmation-pt1-light branch September 2, 2021 15:49
@pr-triage pr-triage bot added PR: merged bot applied label for PR's that are merged and removed PR: unreviewed bot applied label for PR's with no review labels Sep 2, 2021
@msarit msarit changed the title Save Confirmation - Admin (Part 1 of 2) Save Confirmation - Admin (Part 1 of 3) Sep 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog: rollup Items that will be communicated in our monthly rollup changelogs merge by any core This tag is a signal that you are okay with any core team member merging your code for you. PR: merged bot applied label for PR's that are merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants