Commit graph

6414 commits

Author SHA1 Message Date
Juan Esteban Nieto Cifuentes
efcab9d7db
Fix pause button (#16846)
* Fix pause button

* Fix gif button bug

* Add comment
2022-03-11 16:30:22 +00:00
Fernando Valverde
445b5ba584
Re-enable imageUpload native integration (#15487)
* Re-enable imageUpload native integration

* remove temporary inline comments

* move addEventListener to useEffect hook

* console.log on native messages from image upload integration

* Debug suggestions

* store text area in ref rather than state

* call error callback from native message handler

* Remove debug logs

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
2022-03-11 08:45:25 -06:00
Arit Amana
34bfc491b0
Check validity of embed URLs (#16704)
* start link validation check

* keep PRs small

* rearrange check flow

* need a change to switch accounts

* Rescue from SocketError to surface a better error message

* some updates

* handle 301s

* address Travis failures

* implement request stub

* add needed unified-embed tag spec

* add needed unified-embed tag spec

* nudge Travis

* Address PR review comments

* special-case displaying "base"

* undo change to errors.add

* nudge Travis

* more succinct code

Co-authored-by: aritmock <aritmock@example.com>
Co-authored-by: Dwight Scott <dwight@forem.com>
2022-03-10 13:18:59 -05:00
Julianna Tetreault
aa44786ebd
Remove admin_member_view Feature Flag-Related Conditionals (#16764)
* Removes admin_member_view feature flags and refactors  conditionals

* Removes unused admin/users/_email_tools partial and user_email_tools_spec

* Actually remove the admin/user_email_tools_spec this time

* Removes the edit route from admin.rb users

* Adds a DUS (and spec) to disable and remove admin_member_view flag

* Fixes admin/users_spec.rb failures by updating spec with Member Detail changes

* Fixes spec failures within admin_bans_or_warns_user_spec.rb

* Refactors Admin::UsersController#credit_params due to failing specs

* Removes last traces of edit_admin_user_path and fixes buttons, specs, etc.
2022-03-10 08:29:05 -07:00
Arit Amana
39bc67ec15
Test Solution for Forem-link Embed issues on Canary2 (#16843)
* solution

* fixing specs

* complete specs

* nudge Travis

* resolve database issues

* nudge Travis

* Check that the settings table exists before loading the class

This maybe fixes an issue in test-console-check accessing a missing
table `users` (because we're requiring
settings during the initializer, and we're initializing the app during
a schema load on a newly created db).

* refactor check

* privatize and rename

* add self

* reposition private class method

* Prevent accidentally deploying to DEV

* Skip tests to try deploying to benhalpern

* Allow PR to deploy to benhalpern

* Allow other branches to deploy

* Oops

* Revert changes to travis.yml

Co-authored-by: Dan Uber <dan@forem.com>
Co-authored-by: Andy Z <17884966+Zhao-Andy@users.noreply.github.com>
2022-03-09 18:26:02 -05:00
Mac Siri
63b5c9102d
Remove ForemStatsDriver abstraction (#16835)
* Remove ForemStatsDriver abstraction

* Remove stats.rb
2022-03-09 14:18:29 -05:00
Fernando Valverde
06cec96324
Rebranding from passport to forem account (#16754) 2022-03-09 10:03:16 -06:00
Jamie Gaskins
987c0a07a2
Allowlist character classes for post titles (#16787)
* Normalize article titles

* Change method name to match what it does

* Expand on allowed emoji ranges

This required a few changes to be in compliance with Rubocop because
that regex is a beast.
2022-03-09 10:36:33 -05:00
Daniel Uber
cc7c342bb5
Limit per-user feed import fanout to users with feed urls set (#16831)
* Limit feeds import fanout to users with feeds

This filtering for feed settings occurs in
Feeds::Import#filter_users_from already, so the enqueued ForUser
jobs were mostly no-op, but the queue latency spiked as hundreds of
thousands of jobs were added to default.

Prescreen users to avoid enqueuing a noop job every hour for every single
user without a feed.

* Update tests to check only jobs for users with feeds are enqueued

* spec cleanup

Only include alice when we check no job is enqueued for her.

Assert no job is enqueued for alice.

Rename bob to user when alice isnt there to contrast.

* Update spec

Use update_columns to bypass setting validation (checking feed is
valid/reachable)

Remove unneeded timecop block when passing a set time

Remove sidekiq: fake and allow Import.call to be received

* Empty commit to trigger CI rebuild
2022-03-09 08:51:00 -06:00
Jamie Gaskins
9423060299
Fan out Feeds::ImportArticlesWorker (#16818)
* Fan out Feeds::ImportArticlesWorker

Doing all that work within a single Sidekiq job has begun taking over an
hour on DEV. Regardless of the reasons we did it that way originally, we
should be able to handle this concurrently. If we cannot, we need to
investigate why and handle it properly rather than consigning it to
sequential work.

* Fix specs

The specs make assumptions about how the code under test is implemented.
This commit does not change that, as much as I would like to. Instead,
it just aligns the assumptions with the new implementation.

The previous tests didn't actually represent reality though, since we
can't get a Time or ActiveSupport::TimeWithZone instance inside of the
`perform` method while running it through Sidekiq. Instead, the specs
seem to be relying on the fact that the time instance gets serialized to
ISO-8601/RFC3339 format and that that format is understood by Postgres.
Otherwise, I'm not sure how it would work in production as written.

The new specs reflect reality more closely. The `earlier_than` value
will be converted into an ISO8601/RFC3339 string when passed through
Sidekiq.

* Add parens to perform_bulk call

Turns out, we actually do this pretty consistently. I could've sworn I
saw a bunch of these calls without parens. ¯\_(ツ)_/¯

* Improve variable naming

This is not a list of ids, it's a list of lists of arguments for Sidekiq
jobs, the inner of which contains an id, but that's not the only thing
it contains.
2022-03-08 15:39:16 -05:00
Jeremy Friesen
4db3e38174
Removing unused instance variable (#16826)
```shell
❯ rg "@notifications_index"
```

The above shell command exits status code 1, which means there are no
results found.

This relates to exploratory work for forem/forem#16821
2022-03-08 13:59:08 -05:00
Daniel Uber
ffc65bed81
Don't suggest author follows for anonymous visitors (#16825)
* Don't suggest users for an anonymous visitor to follow

The sidebar raises an error when rendering suggested users for a tag
when the user is signed out.

https://app.honeybadger.io/projects/66984/faults/79342962/

* Assert empty response returned for anonymous requests
2022-03-08 11:15:06 -06:00
Jeremy Friesen
76933284b7
Authorize Web Monetization If User Can Create Article (#16824)
* Authorize Web Monetization If User Can Create Article

There are three things I'm introducing in this PR:

1. Extracting a partial
2. Reworking the i18n keys
3. Adding a policy check regarding Web Monetization

In *extracting a partial*, I'm following the existing pattern where
other extensions have their own partial.

In *reworking the i18n keys*, I'm ensuring that the keys are part of the
same namespace.  This will make finding their usage easier.  Further, if
we decide to remove (or convert to a plugin) the web_monetization, then
we're just a bit closer to that possibility.

Last, and the reason for the work, is *Adding a policy check regarding
Web Monetization*.  This follows on the work in forem/forem#16790.

Closes forem/forem#16820
Related to forem/forem#15098

There are two things to test:

1. Does the feature flag work or not.
2. Are the i18n keys properly applied.

For the feature flag:

- checkout this branch
- in rails console `FeatureFlag.enable(:limit_post_creation_to_admins)`
- start the rails server
- login as a non-admin user
- go to /settings/extensions and scroll to the bottom, you **shouldn't** see
  the partial
- login as an admin user
- go to /settings/extensions and scroll to the bottom, you **should** see
  the partial

Or visually verify the relatively simple change (and accept that it
conforms to #16790's existing pattern).

For the i18n keys, I have a before screenshot (from DEV.to) and the
after (from the changes on this branch).

* Adjustments based on contributor feedback
2022-03-08 09:39:34 -05:00
Suzanne Aitchison
5ae9eb4257
Implement new color picker in listings category form, cleanup old code (#16770)
* remove old color picker initializer

* update listing category picker

* remove old color picker styles
2022-03-08 12:43:18 +00:00
Suzanne Aitchison
aff5f4ce0d
add new color picker to user experience config (#16769) 2022-03-08 12:43:01 +00:00
Suzanne Aitchison
d6056a2b5a
add new color picker to admin tag form (#16768) 2022-03-08 10:38:19 +00:00
Suzanne Aitchison
18877f6f1b
Avoid layout funkiness when non-breaking characters are used (#16782)
* Apply overflow-wrap fallback everywhere we use anywhere value

* fix some more non breaking spaces layout issues

* user with org sidebar

* comment index header
2022-03-08 10:37:52 +00:00
Jeremy Friesen
d1069af35c
Adding ArticlePolicy#moderate? (#16786)
This commit does three things:

1) Adds and tests the ArticlePolicy#moderate? feature
2) Refactors the spec helpers to be a bit more flexible
3) Adds a few more edge case tests around ArticlePolicy

My apologies for conflating these changes, as it makes this commit
more challenging to review.

The goal is to adequate demonstrate the logic around users who can or
cannot moderate.  At present, the rules for who can moderate is here:

841491c6ee/app/javascript/packs/articleModerationTools.js (L17-L27)

```js
if (user?.trusted) {
   if (user?.id !== articleAuthorId && !isModerationPage()) {
     initializeActionsPanel(user, path);
     initializeFlagUserModal(articleAuthorId);
     // "/mod" page
   } else if (isModerationPage()) {
     initializeActionsPanel(user, path);
     initializeFlagUserModal(articleAuthorId);
   }
}
```

- Related to forem/forem#16783
- Closes forem/forem#16784
2022-03-07 15:27:43 -05:00
Jeremy Friesen
61554af5e6
Ensuring the VideoPolicy adhears to article creation (#16762)
Videos are a conceptual subset of Articles (see
[VideosController#create][1] for supporting "evidence").  As such, we
want to ensure they conform to the expectations of the ArticlePolicy (as
described in forem/forem#16483).

This feature enhancement does a few things:

1. Renames swaps the `VideoPolicy#new?` and `VideoPolicy#create?`
   declarations (reversing the alias direction)
2. Moves methods out of the concrete ArticlesPolicy into the
   ApplicationPolicy.
3. Exposes these user oriented methods for external
   consumers (e.g. making future refactoring work easier).  The happy
   benefit is that this already removes a bit of duplicated logic.
4. Highlights that while yes the Policy is correct, we also may be
   flirting with the concept of some sort of User "properties as it relates
   to authorization" logic (good standing users, established users,
   etc.)
5. Reworked the timing of a guard clause and setting of instance variables.

[1]:
33e9bac0f7/app/controllers/videos_controller.rb (L18-L22))

Relates to #16483
Closes forem/forem#16728

To test this, I'm relying on the existing test suite.  I envision that
shifting from returning false for suspended users to raising an
exception might cause some false positive errors.  Note, in the
[AppliciationController][2] we handle the responses.  Paired with
[config/appliciation.rb][3], we handle the policy exceptions.

[2]:33e9bac0f7/app/controllers/application_controller.rb (L32)
[3]:33e9bac0f7/config/application.rb (L71-L81)
2022-03-07 15:27:18 -05:00
Jeremy Friesen
3ddea544d7
Conditionally rendering RSS feed settings (#16790)
With this commit, we're only allowing users who can create articles to
enter RSS feed information for fetching of articles.

Note: I chose not to indent body of the if conditional to ease the code
review.  I also chose to place the if statement in this partial instead
of in the [app/views/users/_extensions.html.erb][1] file; this helps
contain the logic around the policy.

For sleuthing this mirrors the approach of forem/forem#16735

Closes forem/forem#16788
Related to forem/forem#16766, forem/forem#16732, and forem/forem#16763

[1]:b87fd77992/app/views/users/_extensions.html.erb (L3)
2022-03-07 12:56:54 -05:00
Jeremy Friesen
b0ba8bb9e5
Renaming method for clarity (#16791)
In looking at forem/forem#16787, it felt like we would benefit from a
similar approach as we adopted for nullifying blank strings.

This refactor helps pave the way for a "normalize_text_for" method (or
some such thing; naming things is hard).

This change also involved introducing a `describe` block into the
associated spec.
2022-03-07 12:55:56 -05:00
Daniel Uber
1bf350c321
Fix broken email settings documentation link (#16792)
* Fix broken documentation link

When sending an invitation, and smtp isn't configured, we show a link
to the old smtp-settings page, which has been renamed
email-server-settings in the admin documentation site.

* Remove explicit link target, assert link text is present

This spec failed when I changed the link target to match the
documentation. Rather than moving the target, I'm just asserting we
show a link to the docs (not where the docs are located).
2022-03-07 10:45:35 -06:00
Jeremy Friesen
1b337b85d9
Only fetch RSS of users who can create articles (#16766)
* Only fetch RSS of users who can create articles

This commit leverages changes from forem/forem#16732 and
forem/forem#16763 to ensure that we're only fetching RSS feeds for
folks who have permission to create articles.

In addition, I chose to rename the variable `user_scope` to
`users_scope` to bring consistency in the variable names.

I also chose to refactor a private method so that it wasn't setting two
instance variables but was instead returning a value that could be used
to set an instance variable.

Closes forem/forem#16487

* Amending method name
2022-03-04 14:06:38 -05:00
Jeremy Friesen
1d7436702f
Conditionally removing the "configure" editor (#16778)
Note, I'm not overly keen on writing permission tests for this
component.  Why?  Robust permissioning tests can create combinatorial
explosions.  And there are presently no Rspec request specs for this.
So to add an automated test, we'd need to add a set of seed data that
seeds data that conforms to the emerging business logic of the policy.

And while this is easy with use case 1-1, it gets harder as we move
into more nuanced use cases.  Instead we should rely on bombarding our
policy classes with lots of tests to let them demonstrate what we mean
when we say `if p.olicy(Article).create?`

Note, there is a potential relation to forem/forem#14807, namely if we
add a rich text editor to our comments, we may need to explore the
purpose and intention of this setting.

Closes forem/forem#16516
2022-03-04 12:41:56 -05:00
Suzanne Aitchison
4d612ed525
Prevent hidden link skewing layout of home page (#16773)
* Prevent hidden link skewing layout of home page

* add some contextual notes
2022-03-04 16:12:35 +00:00
Jeremy Friesen
d7784fa8a1
Removing before_action in favor of explicity call (#16777)
While in essence an idempotent change the purpose of this PR is to also
favor explicit method calls over callbacks.  Note, we don't have an
associated model (e.g. Video) and instead rely on `:video` which Pundit
converts to VideoPolicy.

From my experience in rails it can become challenging to mentally parse
the various before/after action paired with the only and except.  As
well as considering the timing of what happens when.

Further this commit helps provide a record of "work" towards an issue.

Closes forem/forem#16729

Reverses forem/forem#3806
2022-03-04 11:08:53 -05:00
Andy Zhao
841491c6ee
Redirect appended /moderate and /admin to the same page (admin member view) (#16779)
* Make /moderate and /admin the same redirect

* Fix view constraint limitations

* Update test
2022-03-03 19:40:03 -05:00
Julianna Tetreault
7b944c8327
Reword Copy within "Delete" Modal in Admin Member Detail View (#16755)
* Replaces for with of in _delete.html.erb modal copy

* Removes strong tags around text for conistency in modal

* Adjusts copy within _delete.html.erb
2022-03-03 08:23:05 -07:00
Suzanne Aitchison
33488ba88e
fix grid col overflow in right sidebar in safari (#16771) 2022-03-03 07:51:16 -06:00
Suzanne Aitchison
db288c0b4b
Use the Preact ColorPicker in creator onboarding (#16731)
* use Preact ColorPicker in creator onboarding

* update tests

* update comments

* Update app/javascript/packs/admin/creatorOnboarding.jsx

Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>

Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>
2022-03-03 08:22:10 +00:00
Jeremy Friesen
4e76771867
Favoring User scope as parameter for feed fetching (#16763)
This change makes it easier to resolve forem/forem#16487.

What do I mean by that?  To address forem/forem#16487, I need to only
select user's who are authorized to create articles.  In
forem/forem#16732 I added a method that will allow chaining of a User
scope.  So with this current commit and forem/forem#16732, I'm
triangulating on an approach that will make that change easier.

I did not want to conflate those two, as mixing this PR's change and
what is necessary for the closing PR would create a more complicated
review.  Not unduly complicated, but one that will require more tests
and a change in logic.  And for someone reviewing the diff, those
concerns could easily be lost.

Yes, I have changed the method signature, but that method signature is
limited to one location:

```shell
❯ rg "Feeds::Import.call"

app/workers/feeds/import_articles_worker.rb
21:      ::Feeds::Import.call(users_scope: users_scope, earlier_than: earlier_than)
```

So I look to the method signature a bit as an internal API, hence the change.

Related to forem/forem#16487
2022-03-02 16:45:06 -05:00
Suzanne Aitchison
ac7f1a6db6
Fix error in feed follow buttons where user name has apostrophe (#16758)
* escape apostrophes in names

* woops
2022-03-02 15:53:48 -05:00
Andy Zhao
33e9bac0f7
Filter admin users by status (#16238)
* Use correct table heading for username

* WIP add role filter and crayonsify forms

* styling

* responsive

* Add form back in that was removed by merge conflict fix

* Suggest only valid search options

* Add basic tests for search and filter by role

* Add aria for search field

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>

* Add email to aria

Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>

Co-authored-by: Paweł Ludwiczak <ludwiczakpawel@gmail.com>
Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>
2022-03-02 11:13:59 -05:00
Jeremy Friesen
eff161ba58
Adding ArticlePolicy.scope_users_authorized_to_action (#16732)
As I'm looking at limiting feed fetching only for users who are able to
create articles, I needed a means of querying "Who are the users who can
create articles?"  This bit of work was the smallest chunk that I could
think of.

These kinds of questsions are going to propogate (e.g. give me a list of
all the people who can comment? who can create articles in this space?)
For now, this pattern should suffice.

Yes, there's duplication of knowledge between the policy's instance
method and class method.  And there's a bit of knowledge bleed between a
user's method (e.g. `user.any_admin?` and
`*Authorizer::RoleBasedQueries::ANY_ADMIN`) but that's a small "evil".

Related to #16486
2022-03-02 11:02:04 -05:00
Daniel Uber
c5a90173bd
handle getElementById failures in articlePage (#16743)
* when there is no div for it, don't render CommentSubscription

* Retrigger CI

* Retrigger CI

* don't write an error to the comment div if its gone

This fixes an issue seen in tests, where the page transitioned while
we were running the articlePage async handler, so the article-body
element was gone (can't access dataset of null), and the error handler
catch block tried to access the innerHTML of another getElementById.

* Use existing found element `root` when setting the error message

No need to find a new comment-subscription div to write the error to,
we already named the one we're interested in at the beginning of the function
2022-03-02 09:56:53 -06:00
Miguel Nieto A
6cc341e70e
Remove dots from chart when time range is Infinity (#16720)
* Remove dots from chart when time range is Infinity

* refactor: 🐛 Remove dots using the chart options

* refactor: ♻️ Improve params of drawChart func

* refactor: ♻️ Use a variable showPoints
2022-03-02 15:20:36 +00:00
Suzanne Aitchison
9e19b71e7b
Only init mod tools if we're still on article page (#16733)
* only init mod tools if we're still on article page

* Update app/javascript/packs/articleModerationTools.js

Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>

Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>
2022-03-01 16:59:28 +00:00
Jeremy Friesen
dce7c4b275
Ensuring VideoPolicy#new? is canonical (#16735)
This commit compresses the policy check that spanned both :new? and
:enabled?.  We hide the ability to upload a video (as per the altered
html.erb files of this commit) but we didn't enforce the same logic in
the controller.

Further, as Videos are a subset of Article, I'm adding the "verify the
user is not suspended" test.

Directly relates to #16483

For sleuthing this relates:

- #16728
- forem/forem#16537
- #16634

And for historical context, this relates to:

- #10955
- #10954
- forem/internalEngineering#149
2022-03-01 11:46:31 -05:00
ludwiczakpawel
b321d1ec11
Removing bootstrap: admin sidebar navigation (#16618)
* nav

* nav

* move cheese around

* helpers

* optimize

* optimize

* optimization

* optimization

* children helper

* children helper

* Update app/views/admin/shared/_nested_sidebar.html.erb

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
2022-03-01 15:46:45 +01:00
Suzanne Aitchison
68b2824063
use getCsrfToken helper, refactor to fetch (#16717) 2022-03-01 09:11:42 +00:00
Suzanne Aitchison
3b42c01804
Favour fetch to XmlHttpRequest (#16715)
* refactor out xmlhttprequest

* rework
2022-03-01 09:11:22 +00:00
Jeremy Friesen
3bdcde6496
Adding indirection for Tag#name to ease future work (#16703)
* Adding indirection for Tag#name to ease future work

In pairing with Arit, we were able to capture a few small wins in
regards to favoring an accessible tag name.  In other words, where ever
you see a tag's name, we want to render it as camel-case.  This will
greatly help those using a screen reader and frankly visually scanning
the tag (idontknowaboutyoubutthisiskindahardtoread).

However, as we explored the
code base, we found several places that will require further
consideration.  These revolve around the API and caching of tags for
articles and listings as well as the JSON documents we use for
populating drop-down lists.

So, instead of unleashing a large pull request, we're opting to provide
a small non-breaking refactor that demonstrates where we're going and
keeps production working as expected while allowing future
development/testing to benefit from these captured gains.

Our next steps are to revisit the related issue and do a proper task
breakdown, becuase there are too many considerations to call this a
"small win".

I also encourage reviewers to read the comments.  This is an emerging
mental pattern that I believe helps us conceptually move our codebase
forward while also guarding against the mega-PR with oodles of commits
and file changes that span numerous contexts.

Related to forem/forem-internal-eng#269

* Expanding specs to address feedback
2022-02-28 16:32:04 -05:00
Julianna Tetreault
5652a89cd6
Update the Copy for all Modals in the Admin Member Detail View (#16708)
* Updates the copy for all modals within Admin Member Detail view

* Resolve most failing tests within managaUserOptions.spec.js

* Update app/views/admin/users/show/profile/actions/_export.html.erb

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>

* Update cypress/integration/seededFlows/adminFlows/users/manageUserOptions.spec.js

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
2022-02-28 13:02:57 -07:00
Daniel Uber
c8515967ff
Don't send notification for invalid reactions (#16721)
* Don't send notification for invalid reactions

When a moderator flags a user,
and an admin marks this invalid
and the moderator tries to flag the user again
then destroy the existing reaction, and check whether to notify

Since the points for invalid reactions are set to 0, this was not being
skipped. Now it will be.

* cleanup test cases for reaction skip notification
2022-02-28 12:36:44 -06:00
Suzanne Aitchison
a70bb4811c
amend csrf token retries (#16714) 2022-02-28 15:05:13 +00:00
Jeremy Friesen
acd5b175ed
Ensuring POST api/v0/articles authorizes by policy (#16685)
As part of the [Authorization System Use Case
1:1](https://github.com/orgs/forem/projects/46) project, we are driving
towards the feature of: "Only admin's may post articles in this Forem."

This commit ensures that the API's "create an article" end-point
delivers on that feature.

Along the way, I've added reading notes and comments, to help us further
flex in the future (namely move all authorization checks into a policy
object).

Closes forem/forem#16488
2022-02-28 08:50:33 -05:00
Julianna Tetreault
2be6ecfc14
Updates the copy for the Flags tab (#16697) 2022-02-25 08:41:47 -07:00
Ridhwana
92e59d76c4
remove verify emails from the dropdown (#16699) 2022-02-25 17:36:46 +02:00
Michael Kohl
3322b49e84
✂️ Remove myself from core contributors (#16672)
* Remove myself from core contributors

* Update comments

* Update more comments
2022-02-25 09:56:19 -05:00
Julianna Tetreault
0fd55d1c14
Update the Copy for the "Emails" Tab in the Admin Member Detail View (#16693)
* Adjusts the copy and layout of the Emails section

* Revert design changes to the Emails tab
2022-02-25 07:33:52 -07:00