From 0678603a5b3cd86b5f2f4f2725bb18a3c13e2121 Mon Sep 17 00:00:00 2001 From: Tasos Katsoulas Date: Wed, 27 Nov 2024 13:47:40 +0200 Subject: [PATCH] Filter moderation queue per product --- .../jinja2/flagit/content_moderation.html | 12 +++++ kitsune/flagit/jinja2/flagit/flagit_base.html | 6 +-- .../flagit/jinja2/flagit/includes/macros.html | 16 ++++++ kitsune/flagit/jinja2/flagit/queue.html | 16 ++---- kitsune/flagit/views.py | 21 ++++++-- kitsune/sumo/static/sumo/js/flagit.js | 53 ++++++++++--------- 6 files changed, 79 insertions(+), 45 deletions(-) diff --git a/kitsune/flagit/jinja2/flagit/content_moderation.html b/kitsune/flagit/jinja2/flagit/content_moderation.html index 861ddddcb56..dae149f4f95 100644 --- a/kitsune/flagit/jinja2/flagit/content_moderation.html +++ b/kitsune/flagit/jinja2/flagit/content_moderation.html @@ -1,4 +1,5 @@ {% extends "flagit/flagit_base.html" %} +{% from "flagit/includes/macros.html" import filter_dropdown %} {% block flagged_items %} {% for object in objects %} @@ -39,6 +40,17 @@


{{ _('Update Status:') }}

{% endfor %} {% endblock %} +{% block filter_dropdown %} + {{ filter_dropdown( + form_id='product-filter-form', + select_id='flagit-product-filter', + label='Filter by product:', + name='product', + default_option='All products', + options=products, + selected_filter=selected_product + ) }} +{% endblock %} {# Hide the deactivation log on content moderation #} {% block deactivation_log %} {% endblock %} diff --git a/kitsune/flagit/jinja2/flagit/flagit_base.html b/kitsune/flagit/jinja2/flagit/flagit_base.html index 3fa0280a503..b47198b3cc3 100644 --- a/kitsune/flagit/jinja2/flagit/flagit_base.html +++ b/kitsune/flagit/jinja2/flagit/flagit_base.html @@ -6,8 +6,8 @@ {% block content %}
-

{{ _('Content Pending Moderation') }}

- +

{{ _('Content Pending Moderation') }}

+ - {% block side_top_reason %} + {% block filter_dropdown %} {% endblock %} {% endblock %} diff --git a/kitsune/flagit/jinja2/flagit/includes/macros.html b/kitsune/flagit/jinja2/flagit/includes/macros.html index ef8185e7119..2981f6a9284 100644 --- a/kitsune/flagit/jinja2/flagit/includes/macros.html +++ b/kitsune/flagit/jinja2/flagit/includes/macros.html @@ -3,3 +3,19 @@ {{date}} by {{user}} {% endtrans %} {%- endmacro %} + +{% macro filter_dropdown(form_id, select_id, label, name, default_option, options, selected_filter) %} +
+
+ + +
+
+{% endmacro %} diff --git a/kitsune/flagit/jinja2/flagit/queue.html b/kitsune/flagit/jinja2/flagit/queue.html index 8eae3ad548f..6555593d484 100644 --- a/kitsune/flagit/jinja2/flagit/queue.html +++ b/kitsune/flagit/jinja2/flagit/queue.html @@ -1,4 +1,5 @@ {% extends "flagit/flagit_base.html" %} +{% from "flagit/includes/macros.html" import filter_dropdown %} {% block flagged_items %} {% for object in objects %} @@ -49,17 +50,6 @@


{{ _('Update Status:') }}

{% endfor %} {% endblock %} -{% block side_top_reason %} - -
-
- - -
-
+{% block filter_dropdown %} + {{ filter_dropdown("reason-filter-form", "flagit-reason-filter", "Filter by reason:", "reason", "All reasons", reasons, selected_reason) }} {% endblock %} diff --git a/kitsune/flagit/views.py b/kitsune/flagit/views.py index 2e154e6ee2b..58f04b04a39 100644 --- a/kitsune/flagit/views.py +++ b/kitsune/flagit/views.py @@ -9,7 +9,7 @@ from kitsune.access.decorators import login_required, permission_required from kitsune.flagit.models import FlaggedObject -from kitsune.products.models import Topic +from kitsune.products.models import Product, Topic from kitsune.questions.events import QuestionReplyEvent from kitsune.questions.models import Answer, Question from kitsune.sumo.templatetags.jinja_helpers import urlparams @@ -17,7 +17,7 @@ from kitsune.tags.models import SumoTag -def get_flagged_objects(reason=None, exclude_reason=None, content_model=None): +def get_flagged_objects(reason=None, exclude_reason=None, content_model=None, product_slug=None): """Retrieve pending flagged objects with optional filtering, eager loading related fields.""" queryset = FlaggedObject.objects.pending().select_related("content_type", "creator") if exclude_reason: @@ -26,6 +26,14 @@ def get_flagged_objects(reason=None, exclude_reason=None, content_model=None): queryset = queryset.filter(reason=reason) if content_model: queryset = queryset.filter(content_type=content_model) + if product_slug: + matching_product_ids = [ + obj.id + for obj in queryset + if hasattr(obj.content_object, "product") + and obj.content_object.product.slug == product_slug + ] + queryset = queryset.filter(id__in=matching_product_ids) return queryset @@ -119,11 +127,14 @@ def get_hierarchical_topics(topics, parent=None, level=0): @permission_required("flagit.can_moderate") def moderate_content(request): """Display flagged content that needs moderation.""" - content_type = ContentType.objects.get_for_model(Question) + product_slug = request.GET.get("product") + content_type = ContentType.objects.get_for_model(Question) objects = ( get_flagged_objects( - reason=FlaggedObject.REASON_CONTENT_MODERATION, content_model=content_type + reason=FlaggedObject.REASON_CONTENT_MODERATION, + content_model=content_type, + product_slug=product_slug, ) .select_related("content_type", "creator") .prefetch_related("content_object__product") @@ -143,6 +154,8 @@ def moderate_content(request): { "objects": objects, "locale": request.LANGUAGE_CODE, + "products": [(p.slug, p.title) for p in Product.active.filter(codename="")], + "selected_product": product_slug, }, ) diff --git a/kitsune/sumo/static/sumo/js/flagit.js b/kitsune/sumo/static/sumo/js/flagit.js index 47dc66995d8..a7a9544ed1f 100644 --- a/kitsune/sumo/static/sumo/js/flagit.js +++ b/kitsune/sumo/static/sumo/js/flagit.js @@ -126,37 +126,40 @@ document.addEventListener('DOMContentLoaded', () => { }); } - async function updateReasonAndFetchContent(reason) { - const url = new URL(window.location.href); - if (reason) { - url.searchParams.set('reason', reason); - window.history.pushState({}, '', url); - } else { - url.searchParams.delete('reason'); - window.history.replaceState({}, '', url.pathname); - } + const flaggedQueue = document.getElementById('flagged-queue'); + initializeFilterDropdown('flagit-reason-filter', 'reason'); + initializeFilterDropdown('flagit-product-filter', 'product'); - const response = await fetchData(url); - if (response) { - const parser = new DOMParser(); - const doc = parser.parseFromString(await response.text(), 'text/html'); - flaggedQueue.innerHTML = doc.querySelector('#flagged-queue').innerHTML; - disableUpdateStatusButtons(); - initializeDropdownsAndTags(); + function initializeFilterDropdown(filterId, queryParam) { + const filterElement = document.getElementById(filterId); + if (!filterElement) return; + + const currentFilter = new URL(window.location.href).searchParams.get(queryParam); + if (currentFilter) { + filterElement.value = currentFilter; } - } - const reasonFilter = document.getElementById('flagit-reason-filter'); - const flaggedQueue = document.getElementById('flagged-queue'); + filterElement.addEventListener('change', async () => { + const selectedValue = filterElement.value; + const url = new URL(window.location.href); - if (reasonFilter) { - const reason = new URL(window.location.href).searchParams.get('reason'); - if (reason) reasonFilter.value = reason; + if (selectedValue) { + url.searchParams.set(queryParam, selectedValue); + } else { + url.searchParams.delete(queryParam); + } + window.history.pushState({}, '', url); - reasonFilter.addEventListener('change', async () => { - const selectedReason = reasonFilter.value; - await updateReasonAndFetchContent(selectedReason); + const response = await fetchData(url); + if (response) { + const parser = new DOMParser(); + const doc = parser.parseFromString(await response.text(), 'text/html'); + flaggedQueue.innerHTML = doc.querySelector('#flagged-queue').innerHTML; + disableUpdateStatusButtons(); + initializeDropdownsAndTags(); + } }); } + initializeDropdownsAndTags(); });