From d4464ff54e4ac385c27f04203eece95764499b21 Mon Sep 17 00:00:00 2001
From: Lova ANDRIARIMALALA <43842786+Xpirix@users.noreply.github.com>
Date: Tue, 30 Jul 2024 17:01:35 +0300
Subject: [PATCH 1/6] Add new list for resolved comments plugins
---
qgis-app/plugins/models.py | 60 +++++++++++++++++++
.../templates/plugins/plugin_base.html | 5 +-
qgis-app/plugins/urls.py | 7 +++
qgis-app/plugins/views.py | 19 +++++-
4 files changed, 86 insertions(+), 5 deletions(-)
diff --git a/qgis-app/plugins/models.py b/qgis-app/plugins/models.py
index 763dba05..04a4108e 100644
--- a/qgis-app/plugins/models.py
+++ b/qgis-app/plugins/models.py
@@ -14,6 +14,8 @@
from taggit_autosuggest.managers import TaggableManager
from rest_framework_simplejwt.token_blacklist.models import OutstandingToken
+from django.db.models import OuterRef, Count, Subquery, F
+
PLUGINS_STORAGE_PATH = getattr(settings, "PLUGINS_STORAGE_PATH", "packages/%Y")
PLUGINS_FRESH_DAYS = getattr(settings, "PLUGINS_FRESH_DAYS", 30)
@@ -274,6 +276,43 @@ def get_queryset(self):
return super(ServerPlugins, self).get_queryset().filter(server=True).distinct()
+class FeedbackCompletedPlugins(models.Manager):
+ """
+ Show only unapproved plugins with resolved feedbacks
+ """
+ def get_queryset(self):
+ feedback_count_subquery = PluginVersionFeedback.objects.filter(
+ id=OuterRef('pluginversion__feedback'),
+ is_completed=True
+ ).values('version').annotate(
+ completed_count=Count('id')
+ ).values('completed_count')
+
+ return (
+ super(FeedbackCompletedPlugins, self)
+ .get_queryset()
+ .filter(
+ pluginversion__approved=False
+ )
+ .annotate(
+ total_feedback_count=Count('pluginversion__feedback'),
+ completed_feedback_count=Subquery(feedback_count_subquery)
+ )
+ .filter(
+ total_feedback_count=F('completed_feedback_count')
+ )
+ .extra(
+ select={
+ "average_vote": "rating_score/(rating_votes+0.001)",
+ "latest_version_date": (
+ "SELECT created_on FROM plugins_pluginversion WHERE "
+ "plugins_pluginversion.plugin_id = plugins_plugin.id "
+ "ORDER BY created_on DESC LIMIT 1"
+ ),
+ }
+ ).distinct()
+ )
+
class FeedbackReceivedPlugins(models.Manager):
"""
Show only unapproved plugins with a feedback
@@ -285,6 +324,16 @@ def get_queryset(self):
.filter(
pluginversion__approved=False,
pluginversion__feedback__isnull=False
+ )
+ .extra(
+ select={
+ "average_vote": "rating_score/(rating_votes+0.001)",
+ "latest_version_date": (
+ "SELECT created_on FROM plugins_pluginversion WHERE "
+ "plugins_pluginversion.plugin_id = plugins_plugin.id "
+ "ORDER BY created_on DESC LIMIT 1"
+ ),
+ }
).distinct()
)
@@ -300,6 +349,16 @@ def get_queryset(self):
.filter(
pluginversion__approved=False,
pluginversion__feedback__isnull=True
+ )
+ .extra(
+ select={
+ "average_vote": "rating_score/(rating_votes+0.001)",
+ "latest_version_date": (
+ "SELECT created_on FROM plugins_pluginversion WHERE "
+ "plugins_pluginversion.plugin_id = plugins_plugin.id "
+ "ORDER BY created_on DESC LIMIT 1"
+ ),
+ }
).distinct()
)
@@ -407,6 +466,7 @@ class Plugin(models.Model):
most_voted_objects = MostVotedPlugins()
most_rated_objects = MostRatedPlugins()
server_objects = ServerPlugins()
+ feedback_completed_objects = FeedbackCompletedPlugins()
feedback_received_objects = FeedbackReceivedPlugins()
feedback_pending_objects = FeedbackPendingPlugins()
diff --git a/qgis-app/plugins/templates/plugins/plugin_base.html b/qgis-app/plugins/templates/plugins/plugin_base.html
index ffc44a31..16b87c8e 100644
--- a/qgis-app/plugins/templates/plugins/plugin_base.html
+++ b/qgis-app/plugins/templates/plugins/plugin_base.html
@@ -23,8 +23,9 @@
{% trans "Plugins" %}
{% if user.is_staff %}
{% trans "Unapproved"%}
{% trans "Deprecated"%}
{% endif %}
diff --git a/qgis-app/plugins/urls.py b/qgis-app/plugins/urls.py
index af5f08d5..0d2f3482 100644
--- a/qgis-app/plugins/urls.py
+++ b/qgis-app/plugins/urls.py
@@ -205,6 +205,13 @@
),
name="most_rated_plugins",
),
+ url(
+ r"^feedback_completed/$",
+ FeedbackCompletedPluginsList.as_view(
+ additional_context={"title": _("Feedback completed plugins")}
+ ),
+ name="feedback_completed_plugins",
+ ),
url(
r"^feedback_pending/$",
FeedbackPendingPluginsList.as_view(
diff --git a/qgis-app/plugins/views.py b/qgis-app/plugins/views.py
index 6f517f6b..57ef6a8e 100644
--- a/qgis-app/plugins/views.py
+++ b/qgis-app/plugins/views.py
@@ -971,13 +971,27 @@ def get_context_data(self, **kwargs):
return context
+class FeedbackCompletedPluginsList(PluginsList):
+ """List of Plugins that has feedback resolved in its versions.
+
+ The plugins editor can only see their plugin feedbacks.
+ The staff can see all plugin feedbacks.
+ """
+ queryset = Plugin.feedback_completed_objects.all().order_by("-latest_version_date")
+
+ def get_filtered_queryset(self, qs):
+ user = get_object_or_404(User, username=self.request.user)
+ if not user.is_staff:
+ raise Http404
+ return qs
+
class FeedbackReceivedPluginsList(PluginsList):
"""List of Plugins that has feedback received in its versions.
The plugins editor can only see their plugin feedbacks.
The staff can see all plugin feedbacks.
"""
- queryset = Plugin.feedback_received_objects.all()
+ queryset = Plugin.feedback_received_objects.all().order_by("-latest_version_date")
def get_filtered_queryset(self, qs):
user = get_object_or_404(User, username=self.request.user)
@@ -985,13 +999,12 @@ def get_filtered_queryset(self, qs):
raise Http404
return qs
-
class FeedbackPendingPluginsList(PluginsList):
"""List of Plugins that has feedback pending in its versions.
Only staff can see plugin feedback list.
"""
- queryset = Plugin.feedback_pending_objects.all()
+ queryset = Plugin.feedback_pending_objects.all().order_by("-latest_version_date")
def get_filtered_queryset(self, qs):
user = get_object_or_404(User, username=self.request.user)
From 140601d4e6988fb7bcd329615c8df0a830b9ffdb Mon Sep 17 00:00:00 2001
From: Lova ANDRIARIMALALA <43842786+Xpirix@users.noreply.github.com>
Date: Wed, 31 Jul 2024 12:24:46 +0300
Subject: [PATCH 2/6] Fix resolved comments and awaiting resolution list
---
qgis-app/plugins/models.py | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/qgis-app/plugins/models.py b/qgis-app/plugins/models.py
index 04a4108e..73cda03b 100644
--- a/qgis-app/plugins/models.py
+++ b/qgis-app/plugins/models.py
@@ -282,7 +282,7 @@ class FeedbackCompletedPlugins(models.Manager):
"""
def get_queryset(self):
feedback_count_subquery = PluginVersionFeedback.objects.filter(
- id=OuterRef('pluginversion__feedback'),
+ version=OuterRef('pluginversion'),
is_completed=True
).values('version').annotate(
completed_count=Count('id')
@@ -315,15 +315,27 @@ def get_queryset(self):
class FeedbackReceivedPlugins(models.Manager):
"""
- Show only unapproved plugins with a feedback
+ Show only unapproved plugins with a pending feedback
"""
def get_queryset(self):
+ feedback_count_subquery = PluginVersionFeedback.objects.filter(
+ version=OuterRef('pluginversion'),
+ is_completed=False
+ ).values('version').annotate(
+ received_count=Count('id')
+ ).values('received_count')
+
return (
super(FeedbackReceivedPlugins, self)
.get_queryset()
.filter(
- pluginversion__approved=False,
- pluginversion__feedback__isnull=False
+ pluginversion__approved=False
+ )
+ .annotate(
+ received_feedback_count=Subquery(feedback_count_subquery)
+ )
+ .filter(
+ received_feedback_count__gte=1
)
.extra(
select={
From 591f2ea11806f71212d8b303fd14abae3633b8a8 Mon Sep 17 00:00:00 2001
From: Lova ANDRIARIMALALA <43842786+Xpirix@users.noreply.github.com>
Date: Wed, 31 Jul 2024 14:17:26 +0300
Subject: [PATCH 3/6] Update unit test for resolved comments list
---
.../tests/test_plugin_version_feedback.py | 67 +++++++++++++++++--
1 file changed, 63 insertions(+), 4 deletions(-)
diff --git a/qgis-app/plugins/tests/test_plugin_version_feedback.py b/qgis-app/plugins/tests/test_plugin_version_feedback.py
index e770dcae..278454ac 100644
--- a/qgis-app/plugins/tests/test_plugin_version_feedback.py
+++ b/qgis-app/plugins/tests/test_plugin_version_feedback.py
@@ -122,6 +122,66 @@ def test_add_recipient_in_email_notification(self):
settings.EMAIL_HOST_USER
)
+class TestPluginFeedbackCompletedList(SetupMixin, TestCase):
+ fixtures = ["fixtures/simplemenu.json", "fixtures/auth.json"]
+
+ def setUp(self):
+ super().setUp()
+ self.feedback_1.is_completed = True
+ self.feedback_1.save()
+ self.url = reverse("feedback_completed_plugins")
+
+ def test_non_staff_should_not_see_plugin_feedback_completed_list(self):
+ response = self.client.get(self.url)
+ self.assertEqual(response.status_code, 404)
+
+ self.client.force_login(user=self.creator)
+ response = self.client.get(self.url)
+ self.assertEqual(response.status_code, 404)
+
+ def test_staff_should_see_plugin_feedback_completed(self):
+ self.client.force_login(user=self.staff)
+ response = self.client.get(self.url)
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(
+ response, 'plugins/plugin_list.html'
+ )
+ self.assertEqual(
+ list(response.context['object_list']),
+ [self.plugin_1]
+ )
+ self.assertContains(response, "test plugin 1")
+ self.assertNotContains(response, "test plugin 2")
+
+ # add feedback for plugin 2
+ PluginVersionFeedback.objects.create(
+ version=self.version_2,
+ reviewer=self.staff,
+ task="test comment in a feedback for plugin 2."
+ )
+ response = self.client.get(self.url)
+
+ # The plugin should not appear in the feedback completed list
+ self.assertEqual(
+ list(response.context['object_list']),
+ [self.plugin_1]
+ )
+ self.assertNotContains(response, "test plugin 2")
+
+ def test_approved_plugin_should_not_show_in_feedback_completed_list(self):
+ self.client.force_login(user=self.staff)
+ response = self.client.get(self.url)
+ self.assertEqual(
+ list(response.context['object_list']),
+ [self.plugin_1]
+ )
+ self.version_1.approved = True
+ self.version_1.save()
+ response = self.client.get(self.url)
+ self.assertEqual(
+ list(response.context['object_list']),
+ []
+ )
class TestPluginFeedbackReceivedList(SetupMixin, TestCase):
fixtures = ["fixtures/simplemenu.json", "fixtures/auth.json"]
@@ -159,10 +219,9 @@ def test_staff_should_see_plugin_feedback_received(self):
task="test comment in a feedback for plugin 2."
)
response = self.client.get(self.url)
- self.assertEqual(
- list(response.context['object_list']),
- [self.plugin_1, self.plugin_2]
- )
+ object_list = set(response.context['object_list'])
+ expected_objects = {self.plugin_1, self.plugin_2}
+ self.assertEqual(object_list, expected_objects)
self.assertContains(response, "test plugin 2")
def test_approved_plugin_should_not_show_in_feedback_received_list(self):
From 42d6e9dd912f4d2f156cbb0d04bb7fbcafb9ab47 Mon Sep 17 00:00:00 2001
From: Lova ANDRIARIMALALA <43842786+Xpirix@users.noreply.github.com>
Date: Wed, 31 Jul 2024 15:07:43 +0300
Subject: [PATCH 4/6] Fix unapproved and awaiting review list
---
qgis-app/plugins/models.py | 24 ++++++++++++++++---
.../templates/plugins/plugin_base.html | 4 ++--
qgis-app/plugins/urls.py | 8 +++----
3 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/qgis-app/plugins/models.py b/qgis-app/plugins/models.py
index 73cda03b..5b4a7ff2 100644
--- a/qgis-app/plugins/models.py
+++ b/qgis-app/plugins/models.py
@@ -170,6 +170,16 @@ def get_queryset(self):
super(UnapprovedPlugins, self)
.get_queryset()
.filter(pluginversion__approved=False, deprecated=False)
+ .extra(
+ select={
+ "average_vote": "rating_score/(rating_votes+0.001)",
+ "latest_version_date": (
+ "SELECT created_on FROM plugins_pluginversion WHERE "
+ "plugins_pluginversion.plugin_id = plugins_plugin.id "
+ "ORDER BY created_on DESC LIMIT 1"
+ ),
+ }
+ )
.distinct()
)
@@ -292,7 +302,8 @@ def get_queryset(self):
super(FeedbackCompletedPlugins, self)
.get_queryset()
.filter(
- pluginversion__approved=False
+ pluginversion__approved=False,
+ deprecated=False
)
.annotate(
total_feedback_count=Count('pluginversion__feedback'),
@@ -329,7 +340,8 @@ def get_queryset(self):
super(FeedbackReceivedPlugins, self)
.get_queryset()
.filter(
- pluginversion__approved=False
+ pluginversion__approved=False,
+ deprecated=False
)
.annotate(
received_feedback_count=Subquery(feedback_count_subquery)
@@ -360,7 +372,13 @@ def get_queryset(self):
.get_queryset()
.filter(
pluginversion__approved=False,
- pluginversion__feedback__isnull=True
+ deprecated=False
+ )
+ .annotate(
+ total_feedback_count=Count('pluginversion__feedback'),
+ )
+ .filter(
+ total_feedback_count=0
)
.extra(
select={
diff --git a/qgis-app/plugins/templates/plugins/plugin_base.html b/qgis-app/plugins/templates/plugins/plugin_base.html
index 16b87c8e..6cf76bd9 100644
--- a/qgis-app/plugins/templates/plugins/plugin_base.html
+++ b/qgis-app/plugins/templates/plugins/plugin_base.html
@@ -23,8 +23,8 @@ {% trans "Plugins" %}
{% if user.is_staff %}
{% trans "Unapproved"%}
{% trans "Deprecated"%}
diff --git a/qgis-app/plugins/urls.py b/qgis-app/plugins/urls.py
index 0d2f3482..ccc95158 100644
--- a/qgis-app/plugins/urls.py
+++ b/qgis-app/plugins/urls.py
@@ -120,7 +120,7 @@
url(
r"^unapproved/$",
PluginsList.as_view(
- queryset=Plugin.unapproved_objects.all(),
+ queryset=Plugin.unapproved_objects.all().order_by("-latest_version_date"),
additional_context={"title": _("Unapproved plugins")},
),
name="unapproved_plugins",
@@ -208,21 +208,21 @@
url(
r"^feedback_completed/$",
FeedbackCompletedPluginsList.as_view(
- additional_context={"title": _("Feedback completed plugins")}
+ additional_context={"title": _("Reviewed plugins (Resolved comments)")}
),
name="feedback_completed_plugins",
),
url(
r"^feedback_pending/$",
FeedbackPendingPluginsList.as_view(
- additional_context={"title": _("Feedback pending plugins")}
+ additional_context={"title": _("Awaiting review")}
),
name="feedback_pending_plugins",
),
url(
r"^feedback_received/$",
FeedbackReceivedPluginsList.as_view(
- additional_context={"title": _("Feedback received plugins")}
+ additional_context={"title": _("Reviewed plugins (Awaiting comments resolution)")}
),
name="feedback_received_plugins",
),
From 9eba09f3ef7ebf8ba639c1f972d6a365cb9e7f52 Mon Sep 17 00:00:00 2001
From: Lova ANDRIARIMALALA <43842786+Xpirix@users.noreply.github.com>
Date: Mon, 5 Aug 2024 17:04:36 +0300
Subject: [PATCH 5/6] Fix GH workflow
---
.github/workflows/test.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index bfc5cf81..24befe05 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -52,7 +52,7 @@ jobs:
- name: Run the containers
- run: docker-compose up -d db devweb
+ run: docker compose up -d db devweb
- name: Wait for the containers to start
@@ -60,7 +60,7 @@ jobs:
- name: Run test
run: |
- docker-compose exec -T devweb bash -c '
+ docker compose exec -T devweb bash -c '
set -e # Exit immediately if any command fails
python manage.py makemigrations &&
python manage.py migrate &&
From d156278739a1b5c61da05245852e31c4793b929c Mon Sep 17 00:00:00 2001
From: Lova ANDRIARIMALALA <43842786+Xpirix@users.noreply.github.com>
Date: Mon, 5 Aug 2024 17:07:01 +0300
Subject: [PATCH 6/6] Simplify texts
---
qgis-app/plugins/templates/plugins/plugin_base.html | 4 ++--
qgis-app/plugins/urls.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/qgis-app/plugins/templates/plugins/plugin_base.html b/qgis-app/plugins/templates/plugins/plugin_base.html
index 6cf76bd9..31badff6 100644
--- a/qgis-app/plugins/templates/plugins/plugin_base.html
+++ b/qgis-app/plugins/templates/plugins/plugin_base.html
@@ -23,8 +23,8 @@ {% trans "Plugins" %}
{% if user.is_staff %}
{% trans "Unapproved"%}
{% trans "Deprecated"%}
diff --git a/qgis-app/plugins/urls.py b/qgis-app/plugins/urls.py
index ccc95158..e7b2d636 100644
--- a/qgis-app/plugins/urls.py
+++ b/qgis-app/plugins/urls.py
@@ -208,7 +208,7 @@
url(
r"^feedback_completed/$",
FeedbackCompletedPluginsList.as_view(
- additional_context={"title": _("Reviewed plugins (Resolved comments)")}
+ additional_context={"title": _("Reviewed Plugins (Resolved)")}
),
name="feedback_completed_plugins",
),
@@ -222,7 +222,7 @@
url(
r"^feedback_received/$",
FeedbackReceivedPluginsList.as_view(
- additional_context={"title": _("Reviewed plugins (Awaiting comments resolution)")}
+ additional_context={"title": _("Reviewed Plugins (Pending)")}
),
name="feedback_received_plugins",
),