Skip to content

Commit

Permalink
Match reports UI to the table shown inside media items
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvkb committed May 27, 2024
1 parent 2c05cae commit 515c682
Showing 1 changed file with 48 additions and 116 deletions.
164 changes: 48 additions & 116 deletions api/api/admin/media_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@
import structlog
from elasticsearch import NotFoundError
from elasticsearch_dsl import Search
from openverse_attribution.license import License

from api.admin.forms import MediaDecisionForm
from api.models import PENDING
from api.models.audio import AudioDecision, AudioDecisionThrough
from api.models.image import ImageDecision, ImageDecisionThrough
from api.utils.moderation_lock import LockManager
Expand Down Expand Up @@ -380,131 +378,65 @@ def get_changelist(self, request, **kwargs):


class MediaReportAdmin(admin.ModelAdmin):
change_form_template = "admin/api/media_report/change_form.html"
list_display = ("id", "reason", "is_pending", "description", "created_at", "url")
media_type = None

@admin.display(description="Is pending?", boolean=True)
def is_pending(self, obj):
"""Shadow the ``is_pending`` property but render as icon in Django admin."""
return obj.is_pending

#############
# List view #
#############

list_display = (
"id",
"created_at",
"reason",
"description",
"is_pending",
"media_id", # used because ``media_obj`` does not render a link
)
list_filter = (
("decision", admin.EmptyFieldListFilter), # ~status, i.e. pending or moderated
"reason",
("decision", admin.EmptyFieldListFilter), # ~is_pending
)
list_display_links = ("id",)
list_select_related = ("media_obj",)
search_fields = _production_deferred("description", "media_obj__identifier")
autocomplete_fields = _production_deferred("media_obj")
actions = None
media_type = None
search_fields = ("description", *_production_deferred("media_obj__identifier"))

def get_fieldsets(self, request, obj=None):
if obj is None:
return [
(
"Report details",
{"fields": ["status", "decision", "reason", "description"]},
),
("Media details", {"fields": ["media_obj"]}),
]
return [
(
"Report details",
{
"fields": [
"created_at",
"status",
"decision",
"reason",
"description",
"has_sensitive_text",
],
},
),
]
@admin.display(description="Media obj")
def media_id(self, obj):
path = reverse(f"admin:api_{self.media_type}_change", args=(obj.media_obj.id,))
return format_html(f'<a href="{path}">{obj.media_obj}</a>')

def get_exclude(self, request, obj=None):
# ``identifier`` cannot be edited on an existing report.
if request.path.endswith("/change/"):
return ["media_obj"]
###############
# Change view #
###############

autocomplete_fields = ("decision", *_production_deferred("media_obj"))
raw_id_fields = _non_production_deferred("media_obj")
actions = None

def get_readonly_fields(self, request, obj=None):
if obj is None:
return []
readonly_fields = [
if obj is None: # Create form
return ()
# These fields only make sense after a report has been created.
# Hence they are only shown in the change form.
return (
"created_at",
"reason",
"description",
"has_sensitive_text",
"media_obj_id",
]
# ``status`` cannot be changed on a finalised report.
if obj.status != PENDING:
readonly_fields.append("status")
return readonly_fields

@admin.display(description="Has sensitive text")
def has_sensitive_text(self, obj):
"""
Return `True` if the item cannot be found in the filtered index - which means the item
was filtered out due to text sensitivity.
"""
if not self.media_type or not obj:
return None

filtered_index = f"{settings.MEDIA_INDEX_MAPPING[self.media_type]}-filtered"
try:
search = (
Search(index=filtered_index)
.query("term", identifier=obj.media_obj.identifier)
.execute()
)
if search.hits:
return False
except NotFoundError:
logger.error(f"Could not resolve index {filtered_index}")
return None
return True

def get_other_reports(self, obj):
if not self.media_type or not obj:
return []

reports = (
self.model.objects.filter(media_obj__identifier=obj.media_obj.identifier)
.exclude(id=obj.id)
.order_by("created_at")
"is_pending",
"media_obj",
)
return reports

def _get_media_obj_data(self, obj):
tags_by_provider = {}
if obj.media_obj.tags:
for tag in obj.media_obj.tags:
tags_by_provider.setdefault(tag["provider"], []).append(tag["name"])
additional_data = {
"other_reports": self.get_other_reports(obj),
"media_obj": obj.media_obj,
"license": License(
obj.media_obj.license,
obj.media_obj.license_version,
).full_name,
"tags": tags_by_provider,
"description": obj.media_obj.meta_data.get("description", ""),
}
logger.info(f"Additional data: {additional_data}")
return additional_data

def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context["media_type"] = self.media_type

obj = self.get_object(request, object_id)
if obj and obj.media_obj:
additional_data = self._get_media_obj_data(obj)
extra_context = {**extra_context, **additional_data}

return super().change_view(
request,
object_id,
form_url,
extra_context=extra_context,
)
def get_exclude(self, request, obj=None):
if obj is None: # Create form
# The decision will be linked to the report after it has
# been created, not during.
return ("decision",)
else: # Change form
# In the change form, we do not want to allow the media
# object to be changed.
return ("media_obj",)


class MediaDecisionAdmin(admin.ModelAdmin):
Expand Down

0 comments on commit 515c682

Please sign in to comment.