Oleg Komarov
13ac2436ad
see #238 This change improves the listing performance: old code had to process all ApprovalActivity to compute an extension's moderation status and position in the queue. Now we maintain a sortkey, a reference to the latest "meaningful" activity object, and a total comment count. These fields are updated in a post_save signal. "Meaningful" activity means moderation status changes: approved, awaiting changes, awaiting review. "Non-meaningful" activity shouldn't affect queue position anymore and extensions without "meaningful" activity should not appear in the queue, but their respective detail pages should still be reachable via a direct link. This UX may still need improvement, and #210 may be relevant here. Reviewed-on: #240 Reviewed-by: Anna Sirota <annasirota@noreply.localhost>
75 lines
2.3 KiB
Python
75 lines
2.3 KiB
Python
from actstream import action
|
|
from actstream.actions import follow
|
|
from django.db.models.signals import post_save, pre_delete
|
|
from django.dispatch import receiver
|
|
|
|
from constants.activity import Flag, Verb
|
|
from reviewers.models import ApprovalActivity, ApprovalQueue
|
|
|
|
|
|
@receiver(post_save, sender=ApprovalActivity)
|
|
def _create_action_from_review_and_follow(
|
|
sender: object,
|
|
instance: ApprovalActivity,
|
|
created: bool,
|
|
raw: bool,
|
|
**kwargs: object,
|
|
) -> None:
|
|
if raw:
|
|
return
|
|
if not created:
|
|
return
|
|
|
|
# automatically follow after an interaction
|
|
# if a user had unfollowed this extension before,
|
|
# we are making them a follower again
|
|
follow(instance.user, instance.extension, send_action=False, flag=Flag.REVIEWER)
|
|
|
|
activity_type2verb = {
|
|
ApprovalActivity.ActivityType.APPROVED: Verb.APPROVED,
|
|
ApprovalActivity.ActivityType.AWAITING_CHANGES: Verb.REQUESTED_CHANGES,
|
|
ApprovalActivity.ActivityType.AWAITING_REVIEW: Verb.REQUESTED_REVIEW,
|
|
ApprovalActivity.ActivityType.COMMENT: Verb.COMMENTED,
|
|
ApprovalActivity.ActivityType.UPLOADED_NEW_VERSION: Verb.UPLOADED_NEW_VERSION,
|
|
}
|
|
action.send(
|
|
instance.user,
|
|
verb=activity_type2verb.get(instance.type),
|
|
action_object=instance,
|
|
target=instance.extension,
|
|
)
|
|
|
|
|
|
@receiver(post_save, sender=ApprovalActivity)
|
|
def _update_approval_queue(
|
|
sender: object,
|
|
instance: ApprovalActivity,
|
|
created: bool,
|
|
raw: bool,
|
|
**kwargs: object,
|
|
) -> None:
|
|
if raw:
|
|
return
|
|
if not created:
|
|
return
|
|
|
|
activity_count = ApprovalActivity.objects.filter(extension=instance.extension).count()
|
|
if instance.type in ApprovalActivity.STATUS_CHANGE_TYPES:
|
|
ApprovalQueue.objects.update_or_create(
|
|
extension=instance.extension,
|
|
defaults={
|
|
'activity_count': activity_count,
|
|
'latest_activity': instance,
|
|
'sortkey': instance.queue_sortkey,
|
|
},
|
|
)
|
|
else:
|
|
if item := ApprovalQueue.objects.filter(extension=instance.extension).first():
|
|
item.activity_count = activity_count
|
|
item.save(update_fields={'activity_count'})
|
|
|
|
|
|
@receiver(pre_delete, sender=ApprovalActivity)
|
|
def _log_deletion(sender: object, instance: ApprovalActivity, **kwargs: object) -> None:
|
|
instance.record_deletion()
|