diff --git a/app/javascript/admin/__tests__/controllers/article_controller.test.js b/app/javascript/admin/__tests__/controllers/article_controller.test.js index f8b7e5656..4880e8283 100644 --- a/app/javascript/admin/__tests__/controllers/article_controller.test.js +++ b/app/javascript/admin/__tests__/controllers/article_controller.test.js @@ -3,12 +3,15 @@ import ArticleController from '../../controllers/article_controller'; describe('ArticleController', () => { beforeEach(() => { - document.body.innerHTML = `
-
+ document.body.innerHTML = ` +
+
- +
`; @@ -23,7 +26,7 @@ describe('ArticleController', () => { it('increases the featured number input', () => { const button = document.getElementsByTagName('button')[0]; const input = document.querySelector( - "[data-target='article.featuredNumber']", + "[data-article-target='featuredNumber']", ); input.value = initialValue; @@ -37,7 +40,7 @@ describe('ArticleController', () => { it('increases the featured number input', () => { const button = document.getElementsByTagName('button')[1]; const input = document.querySelector( - "[data-target='article.featuredNumber']", + "[data-article-target='featuredNumber']", ); input.value = initialValue; diff --git a/app/javascript/admin/__tests__/controllers/buffer_controller.test.js b/app/javascript/admin/__tests__/controllers/buffer_controller.test.js index 4094c7ffb..276e1873c 100644 --- a/app/javascript/admin/__tests__/controllers/buffer_controller.test.js +++ b/app/javascript/admin/__tests__/controllers/buffer_controller.test.js @@ -3,8 +3,11 @@ import BufferController from '../../controllers/buffer_controller'; describe('BufferController', () => { beforeEach(() => { - document.body.innerHTML = `
-

+ document.body.innerHTML = ` +
+

diff --git a/app/javascript/admin/__tests__/controllers/config_controller.test.js b/app/javascript/admin/__tests__/controllers/config_controller.test.js index f5cd7291e..cd5408ac6 100644 --- a/app/javascript/admin/__tests__/controllers/config_controller.test.js +++ b/app/javascript/admin/__tests__/controllers/config_controller.test.js @@ -3,11 +3,12 @@ import ConfigController from '../../controllers/config_controller'; describe('ConfigController', () => { beforeEach(() => { - document.body.innerHTML = `
+ document.body.innerHTML = ` +
-
+
`; global.scrollTo = jest.fn(); @@ -20,7 +21,7 @@ describe('ConfigController', () => { it('builds and adds a Modal to the page', () => { const button = document.getElementsByTagName('button')[0]; const modalAnchor = document.querySelector( - '[data-target="config.configModalAnchor"]', + '[data-config-target="configModalAnchor"]', ); button.click(); diff --git a/app/javascript/admin/controllers/article_controller.js b/app/javascript/admin/controllers/article_controller.js index 443bff49d..ab8981e9d 100644 --- a/app/javascript/admin/controllers/article_controller.js +++ b/app/javascript/admin/controllers/article_controller.js @@ -1,7 +1,8 @@ import { Controller } from 'stimulus'; export default class ArticleController extends Controller { - static targets = ['featuredNumber']; + static classes = ['bgHighlighted', 'borderHighlighted']; + static targets = ['featuredNumber', 'cardBody']; increaseFeaturedNumber() { // Increases the article's chances of being seen @@ -16,18 +17,12 @@ export default class ArticleController extends Controller { } highlightElement() { - const card = this.element.getElementsByClassName('card-body')[0]; - card.classList.add('bg-highlighted', 'border-highlighted'); + const card = this.cardBodyTarget; + + card.classList.add(this.bgHighlightedClass, this.borderHighlightedClass); + setTimeout(() => { - card.classList.remove('bg-highlighted'); + card.classList.remove(this.bgHighlightedClass); }, 350); } - - get articleId() { - return parseInt(this.data.get('id'), 10); - } - - set articleId(value) { - this.data.set('id', value); - } } diff --git a/app/javascript/admin/controllers/buffer_controller.js b/app/javascript/admin/controllers/buffer_controller.js index 23f54d0a2..81691d7e0 100644 --- a/app/javascript/admin/controllers/buffer_controller.js +++ b/app/javascript/admin/controllers/buffer_controller.js @@ -1,26 +1,33 @@ import { Controller } from 'stimulus'; +const CONFIRM_BADGE_HTML = + 'Confirm'; +const DISMISS_BADGE_HTML = + 'Dismiss'; + export default class BufferController extends Controller { + static classes = ['bgHighlighted', 'borderHighlighted']; static targets = ['header', 'bodyText']; tagBufferUpdateConfirmed() { this.clearPreviousBadge(); - this.headerTarget.innerHTML += - 'Confirm'; + this.headerTarget.innerHTML += CONFIRM_BADGE_HTML; } tagBufferUpdateDismissed() { this.clearPreviousBadge(); - this.headerTarget.innerHTML += - 'Dismiss'; + this.headerTarget.innerHTML += DISMISS_BADGE_HTML; } highlightElement() { - this.element.classList.add('bg-highlighted', 'border-highlighted'); + this.element.classList.add( + this.bgHighlightedClass, + this.borderHighlightedClass, + ); setTimeout(() => { - this.element.classList.remove('bg-highlighted'); + this.element.classList.remove(this.bgHighlightedClass); }, 350); } @@ -36,12 +43,4 @@ export default class BufferController extends Controller { badge.remove(); } } - - get bufferUpdateId() { - return parseInt(this.data.get('id'), 10); - } - - set bufferUpdateId(value) { - this.data.set('id', value); - } } diff --git a/app/javascript/admin/controllers/config_controller.js b/app/javascript/admin/controllers/config_controller.js index fa266a907..ea8577308 100644 --- a/app/javascript/admin/controllers/config_controller.js +++ b/app/javascript/admin/controllers/config_controller.js @@ -11,8 +11,10 @@ const emailAuthSettingsSection = document.getElementById( const emailAuthModalTitle = 'Disable Email address registration'; // TODO: Remove the sentence "You must update site config to save this action!" // once we build more robust flow for Admin/Config -const emailAuthModalBody = - '

If you disable Email address as a registration option, people cannot create an account with their email address.

However, people who have already created an account using their email address can continue to login.

You must confirm and update site config to save below this action.

'; +const emailAuthModalBody = ` +

If you disable Email address as a registration option, people cannot create an account with their email address.

+

However, people who have already created an account using their email address can continue to login.

+

You must confirm and update site config to save below this action.

`; export default class ConfigController extends Controller { static targets = [ diff --git a/app/javascript/admin/controllers/image_upload_controller.js b/app/javascript/admin/controllers/image_upload_controller.js index 9f1369050..4118aa75e 100644 --- a/app/javascript/admin/controllers/image_upload_controller.js +++ b/app/javascript/admin/controllers/image_upload_controller.js @@ -2,20 +2,22 @@ import { Controller } from 'stimulus'; export default class ImageUploadController extends Controller { static targets = ['fileField', 'imageResult']; + static values = { url: String }; onFormSubmit(event) { event.preventDefault(); - let token = document.getElementsByName('authenticity_token')[0].value; - let image = this.fileFieldTarget.files[0]; + + const token = document.getElementsByName('authenticity_token')[0].value; + const image = this.fileFieldTarget.files[0]; let formData = new FormData(); formData.append('authenticity_token', token); formData.append('image', image); - fetch('/image_uploads', { + fetch(this.urlValue, { method: 'POST', headers: { - 'X-CSRF_Token': window.csrfToken, + 'X-CSRF-Token': window.csrfToken, }, body: formData, credentials: 'same-origin', diff --git a/app/javascript/admin/controllers/modal_controller.js b/app/javascript/admin/controllers/modal_controller.js index 1bd569119..dc47db382 100644 --- a/app/javascript/admin/controllers/modal_controller.js +++ b/app/javascript/admin/controllers/modal_controller.js @@ -1,11 +1,12 @@ import { Controller } from 'stimulus'; export default class ModalController extends Controller { + static classes = ['hidden']; static targets = ['toggle']; toggleModal() { - if (this.toggleTarget) { - this.toggleTarget.classList.toggle('hidden'); + if (this.hasToggleTarget) { + this.toggleTarget.classList.toggle(this.hiddenClass); } } } diff --git a/app/javascript/admin/controllers/reaction_controller.js b/app/javascript/admin/controllers/reaction_controller.js index be2d68a2e..e33f2940d 100644 --- a/app/javascript/admin/controllers/reaction_controller.js +++ b/app/javascript/admin/controllers/reaction_controller.js @@ -1,13 +1,16 @@ -/* eslint-disable no-alert */ import { Controller } from 'stimulus'; export default class ReactionController extends Controller { static targets = ['invalid', 'confirmed']; + static values = { + id: Number, + url: String, + }; - // eslint-disable-next-line class-methods-use-this - /* eslint no-alert: "error" */ - updateReaction(id, status) { - fetch(`/admin/reactions/${id}`, { + updateReaction(status) { + const id = this.idValue; + + fetch(this.urlValue, { method: 'PATCH', headers: { Accept: 'application/json', @@ -28,46 +31,45 @@ export default class ReactionController extends Controller { this.element.remove(); document.getElementById(`js__reaction__div__hr__${id}`).remove(); } else { - alert(json.error); + window.alert(json.error); } }) .catch((error) => { - alert(error); + window.alert(error); }), ); } updateReactionInvalid() { - this.updateReaction(this.reactionId, this.invalidStatus); + this.updateReaction(this.invalidStatus); } updateReactionConfirmed() { - this.updateReaction(this.reactionId, this.confirmedStatus); + this.updateReaction(this.confirmedStatus); } reactableUserCheck() { if (this.reactableType === 'user') { - // eslint-disable-next-line no-restricted-globals - if (confirm('You are confirming a User vomit reaction; are you sure?')) { - this.updateReaction(this.reactionId, this.confirmedStatus); + if ( + window.confirm( + 'You are confirming a User vomit reaction; are you sure?', + ) + ) { + this.updateReaction(this.confirmedStatus); } } else { - this.updateReaction(this.reactionId, this.confirmedStatus); + this.updateReaction(this.confirmedStatus); } } - get reactionId() { - return parseInt(this.data.get('id'), 10); - } - - get confirmedStatus() { - return this.confirmedTarget.dataset.status; - } - get reactableType() { return this.confirmedTarget.dataset.reactable; } + get confirmedStatus() { + return this.confirmedTarget.dataset.status; + } + get invalidStatus() { return this.invalidTarget.dataset.altstatus; } diff --git a/app/views/admin/articles/_individual_article.html.erb b/app/views/admin/articles/_individual_article.html.erb index 14241a5c6..9ccd4b444 100644 --- a/app/views/admin/articles/_individual_article.html.erb +++ b/app/views/admin/articles/_individual_article.html.erb @@ -4,19 +4,29 @@ } -
+
+

<%= article.title %>

+
Edit + - Manage User - @<%= article.user&.username %> + + Manage User + + @<%= article.user&.username %> + ❤️ <%= article.public_reactions_count %> 💬 <%= article.comments_count %> + <% if article.published_from_feed? && !article.published? %> RSS Import <%= article.created_at.strftime("%b %d, %Y") %> @@ -28,10 +38,10 @@ <%= article.published_at&.strftime("%b %d, %Y") %> <% end %> - <% article.decorate.cached_tag_list_array.each do |tag| %> - #<%= tag %> - <% end %> + <% article.decorate.cached_tag_list_array.each do |tag| %> + #<%= tag %> + <% end %>
@@ -40,6 +50,7 @@ <% background_color = approved %>
"> <% if article.video %> @@ -60,7 +71,7 @@ <%= note.author_id ? User.find(note.author_id).username : "No Author" %> - <%= note.content %>

<% end %> -

View All

+

View All

<% end %> <% end %> <% if article.main_image.present? %> @@ -77,8 +88,11 @@
- +
diff --git a/app/views/admin/articles/index.html.erb b/app/views/admin/articles/index.html.erb index a2c217230..9b4635bb1 100644 --- a/app/views/admin/articles/index.html.erb +++ b/app/views/admin/articles/index.html.erb @@ -18,28 +18,40 @@
<% if params[:state] && params[:state].include?("top-") && params[:state] != "top-3" && params[:state] != "top-6" %> @@ -54,31 +66,53 @@ Suggested Tweets (<%= @pending_buffer_updates.size %>) <% @pending_buffer_updates.each do |buffer_update| %> <% next unless buffer_update.article %> -
+
-

<%= buffer_update.article.title %>

+

<%= buffer_update.article.title %>

Score: <%= buffer_update.article.score %>

- <%= HTML_Truncator.truncate(buffer_update.article.processed_html, 50, ellipsis: "... Read Entire Post").html_safe %> + <%= HTML_Truncator.truncate( + buffer_update.article.processed_html, + 50, + ellipsis: "... Read Entire Post", + ).html_safe %>

<%= Tag.find_by(id: buffer_update.tag_id)&.name || buffer_update.social_service_name %>: - <%= form_with url: admin_buffer_update_path(buffer_update.id), class: "buffer-form buffer-confirm", html: { data: { action: "submit->buffer#highlightElement" } } do |f| %> + <%= form_with( + url: admin_buffer_update_path(buffer_update.id), + class: "buffer-form buffer-confirm", + html: { data: { action: "submit->buffer#highlightElement" } }, + ) do |f| %>
- +
<% end %> - <%= form_with url: admin_buffer_update_path(buffer_update.id), class: "buffer-form buffer-dismiss", html: { data: { action: "submit->buffer#highlightElement" } } do |f| %> + <%= form_with( + url: admin_buffer_update_path(buffer_update.id), + class: "buffer-form buffer-dismiss", + html: { data: { action: "submit->buffer#highlightElement" } }, + ) do |f| %>
diff --git a/app/views/admin/configs/show.html.erb b/app/views/admin/configs/show.html.erb index ef0b8956a..3ec62e58f 100644 --- a/app/views/admin/configs/show.html.erb +++ b/app/views/admin/configs/show.html.erb @@ -135,7 +135,9 @@

General settings

-
" data-tooltip="Unchecking this will enable Email Registration"> +
" + data-tooltip="Unchecking this will enable Email Registration"> <%= f.check_box :invite_only_mode, checked: invite_only_mode_or_no_enabled_auth_options, data: { action: "config#adjustAuthenticationOptions", target: "config.inviteOnlyMode" }, @@ -171,7 +173,7 @@

" - data-target="config.enabledIndicator"> + data-config-target="enabledIndicator"> <%= inline_svg_tag("checkmark.svg", aria: true, class: "crayons-icon admin-config-checkmark", title: "Checkmark") %> Enabled
@@ -181,7 +183,7 @@ class="crayons-btn crayons-btn--secondary" id="email-auth-enable-edit-btn" data-button-text="<%= SiteConfig.allow_email_password_registration ? "edit" : "enable" %>" - data-target="config.emailAuthSettingsBtn" + data-config-target="emailAuthSettingsBtn" data-action="click->config#enableOrEditEmailAuthSettings" <%= disabled_attr_on_auth_provider_enablebtn %>> <%= SiteConfig.allow_email_password_registration ? "Edit" : "Enable" %> @@ -217,7 +219,10 @@
<%= f.check_box :require_captcha_for_email_password_registration, checked: SiteConfig.require_captcha_for_email_password_registration, - data: { action: "config#toggleGoogleRecaptchaFields", target: "config.requireCaptchaForEmailPasswordRegistration" }, + data: { + action: "config#toggleGoogleRecaptchaFields", + "config-target": "requireCaptchaForEmailPasswordRegistration" + }, class: "crayons-checkbox mt-2" %>
<%= admin_config_label :require_captcha_for_email_password_registration, "Enable Google reCAPTCHA for email password registration" %> diff --git a/app/views/admin/feedback_messages/_abuse_reports.html.erb b/app/views/admin/feedback_messages/_abuse_reports.html.erb index 1758c184a..d4d2a523f 100644 --- a/app/views/admin/feedback_messages/_abuse_reports.html.erb +++ b/app/views/admin/feedback_messages/_abuse_reports.html.erb @@ -23,16 +23,21 @@
<% @vomits.each do |reaction| %> <% next if (reaction.reactable_type == "Article" && !reaction.reactable.published) || (reaction.reactable_type == "User" && reaction.reactable&.banished?) %> -
+ +
- 🤢 @<%= reaction.user.username %> + 🤢 @<%= reaction.user.username %> <% if reaction.user_id == SiteConfig.mascot_user_id %> (auto-generated) <% end %> <%= reaction.reactable_type %>: - <%= reaction.reactable_type == "User" ? reaction.reactable.username : reaction.reactable.title %> + <%= reaction.reactable_type == "User" ? reaction.reactable.username : reaction.reactable.title %> <% if reaction.reactable_type == "User" && reaction.reactable.banned %> Suspended <% end %> @@ -48,7 +53,7 @@ type="button" data-reactable="user" data-status="confirmed" - data-target="reaction.confirmed" + data-reaction-target="confirmed" data-action="reaction#reactableUserCheck"> CONFIRM @@ -58,7 +63,7 @@ type="button" data-reactable="non-user" data-status="confirmed" - data-target="reaction.confirmed" + data-reaction-target="confirmed" data-action="reaction#reactableUserCheck"> CONFIRM @@ -67,7 +72,7 @@ class="btn btn-danger btn-sm" type="button" data-altstatus="invalid" - data-target="reaction.invalid" + data-reaction-target="invalid" data-action="reaction#updateReactionInvalid"> INVALID @@ -77,7 +82,7 @@ class="btn btn-warning text-white btn-sm" type="button" data-altstatus="invalid" - data-target="reaction.invalid" + data-reaction-target="invalid" data-action="reaction#updateReactionInvalid"> INVALIDATE @@ -86,7 +91,7 @@ class="btn btn-success btn-sm" type="button" data-status="confirmed" - data-target="reaction.confirmed" + data-reaction-target="confirmed" data-action="reaction#updateReactionConfirmed"> MARK AS VALID diff --git a/app/views/admin/listings/index.html.erb b/app/views/admin/listings/index.html.erb index e9b28cc32..d2b166e29 100644 --- a/app/views/admin/listings/index.html.erb +++ b/app/views/admin/listings/index.html.erb @@ -1,9 +1,11 @@

Listings

- + + Listing Categories
@@ -57,8 +59,19 @@ <%= listing.bumped_at ? "#{time_ago_in_words(listing.bumped_at)} ago" : "Draft" %> - - @@ -73,7 +86,7 @@ <%= form_with url: admin_buffer_updates_path, html: { data: { action: "submit->buffer#highlightElement" } } do %> -