diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 9fb018c8c..0601d6ca2 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -369,6 +369,8 @@ jobs: - run: yarn cypress install - name: cypress env: + CYPRESS_RAILS_HOST: localhost + CYPRESS_RAILS_PORT: 3000 KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }} KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }} KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS }} diff --git a/app/javascript/packs/commentModPage.js b/app/javascript/packs/commentModPage.js index 398f25d06..0d8772008 100644 --- a/app/javascript/packs/commentModPage.js +++ b/app/javascript/packs/commentModPage.js @@ -1,20 +1,32 @@ import { updateExperienceLevel } from '../actionsPanel/actionsPanel'; -function applyReactedClass(category) { - const upVote = document.querySelector("[data-category='thumbsup']"); - const downVote = document.querySelector("[data-category='thumbsdown']"); - const vomitVote = document.querySelector("[data-category='vomit']"); +/** + * A thumbsup reaction on a comment/article will invalidate a previous thumbsdown + * or vomit reaction (they will be deleted on the server by the reaction handler) + * and vice versa. This function updates the UI to match. + * @param {HTMLButtonElement} clickedBtn The reaction button that was clicked + */ +function toggleContradictoryReactions(clickedBtn) { + const contentActions = document.querySelector('#content-mod-actions'); - if (category === 'thumbsup') { - downVote.classList.remove('reacted'); - vomitVote.classList.remove('reacted'); - } else { - upVote.classList.remove('reacted'); + if (clickedBtn.parentElement === contentActions) { + const upVote = contentActions.querySelector("[data-category='thumbsup']"); + const downVote = contentActions.querySelector( + "[data-category='thumbsdown']", + ); + const vomitVote = contentActions.querySelector("[data-category='vomit']"); + + if (clickedBtn.dataset.category === 'thumbsup') { + downVote.classList.remove('reacted'); + vomitVote.classList.remove('reacted'); + } else { + upVote.classList.remove('reacted'); + } } } -async function updateMainReactions(reactableType, category, reactableId) { - const clickedBtn = document.querySelector(`[data-category="${category}"]`); +async function updateMainReactions(clickedBtn) { + const { reactableType, category, reactableId } = clickedBtn.dataset; try { const response = await fetch('/reactions', { method: 'POST', @@ -34,6 +46,7 @@ async function updateMainReactions(reactableType, category, reactableId) { const outcome = await response.json(); if (outcome.result === 'create') { + toggleContradictoryReactions(clickedBtn); clickedBtn.classList.add('reacted'); } else if (outcome.result === 'destroy') { clickedBtn.classList.remove('reacted'); @@ -66,20 +79,17 @@ Array.from(document.getElementsByClassName('level-rating-button')).forEach( document .querySelectorAll('.reaction-button, .reaction-vomit-button') .forEach((btn) => { - btn.addEventListener('click', () => { - applyReactedClass(btn.dataset.category); - updateMainReactions( - btn.dataset.reactableType, - btn.dataset.category, - btn.dataset.reactableId, - ); + btn.addEventListener('click', async () => { + await updateMainReactions(btn); }); }); const form = document.getElementsByClassName('button_to')[0]; -form.addEventListener('submit', (e) => { - e.preventDefault(); - if (confirm('Are you SURE you want to delete this comment?')) { - form.submit(); - } -}); +if (form) { + form.addEventListener('submit', (e) => { + e.preventDefault(); + if (confirm('Are you SURE you want to delete this comment?')) { + form.submit(); + } + }); +} diff --git a/app/services/reaction_handler.rb b/app/services/reaction_handler.rb index 0157ff70c..d7445c46f 100644 --- a/app/services/reaction_handler.rb +++ b/app/services/reaction_handler.rb @@ -37,14 +37,14 @@ class ReactionHandler delegate :rate_limiter, to: :current_user def create - destroy_contradictory_mod_reactions if reactable_type == "Article" + destroy_contradictory_mod_reactions if %w[Article Comment].include?(reactable_type) return noop_result if existing_reaction create_new_reaction end def toggle - destroy_contradictory_mod_reactions if reactable_type == "Article" + destroy_contradictory_mod_reactions if %w[Article Comment].include?(reactable_type) return handle_existing_reaction if existing_reaction create_new_reaction diff --git a/app/views/moderations/mod.html.erb b/app/views/moderations/mod.html.erb index 3eadccbf5..c35e08f90 100644 --- a/app/views/moderations/mod.html.erb +++ b/app/views/moderations/mod.html.erb @@ -33,7 +33,7 @@
<% end %> -
+