[Patchew-devel] [PATCH v2 04/12] maintainer: Queue operations in extra ops

Fam Zheng fam at euphon.net
Wed Nov 28 14:34:57 UTC 2018


From: Fam Zheng <famz at redhat.com>

Aside 'review' and 'reject' we add operations to add and drop whole
series from/to ustom queues.

Initially a "add to new queue..." link is shown in the extra ops menu,
which prompts for a queue name before creating and adding the current
series there. Implementing the prompt takes a little enhancement to the
HTML js.

Once added to a queue, the series will show a new op "drop from queue
'...'".

A convenient op will show in the ops, "add to queue 'foo'", if the user
has previously created and added some other series. This saves typing
the queue name.

Signed-off-by: Fam Zheng <famz at redhat.com>
---
 mods/maintainer.py               | 152 +++++++++++++++++++++++--------
 www/templates/series-detail.html |  30 +++++-
 2 files changed, 141 insertions(+), 41 deletions(-)

diff --git a/mods/maintainer.py b/mods/maintainer.py
index 7f4f5fe..541d6f3 100644
--- a/mods/maintainer.py
+++ b/mods/maintainer.py
@@ -8,17 +8,27 @@
 # This work is licensed under the MIT License.  Please see the LICENSE file or
 # http://opensource.org/licenses/MIT.
 
+import re
 from django.conf.urls import url
-from django.http import Http404, HttpResponseRedirect
+from django.http import Http404, HttpResponseRedirect, HttpResponseBadRequest
 from django.urls import reverse
 from mod import PatchewModule
-from api.models import Message, Queue
+from api.models import Message, Queue, WatchedQuery
 
 class MaintainerModule(PatchewModule):
     """ Project maintainer related tasks """
 
     name = "maintainer"
 
+    def _add_to_queue(self, user, m, queue):
+        for x in [m] + list(m.get_patches()):
+            Queue.objects.get_or_create(user=user, message=x, name=queue)
+
+    def _drop_from_queue(self, user, m, queue):
+        query = Queue.objects.filter(user=user, message__in=m.get_patches() + [m],
+                                     name=queue)
+        q.delete()
+
     def _update_review_state(self, request, message_id, accept):
         if not request.user.is_authenticated:
             return HttpResponseForbidden()
@@ -69,6 +79,27 @@ class MaintainerModule(PatchewModule):
     def www_view_clear_reviewed(self, request, message_id):
         return self._delete_review(request, message_id)
 
+    def www_view_add_to_queue(self, request, message_id):
+        if not request.user.is_authenticated:
+            raise PermissionDenied()
+        m = Message.objects.filter(message_id=message_id).first()
+        if not m:
+            raise Http404("Series not found")
+        queue = request.GET.get("queue")
+        if not queue or re.match(r'[^_a-zA-Z0-9\-]', queue):
+            return HttpResponseBadRequest("Invalid queue name")
+        self._add_to_queue(request.user, m, queue)
+        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
+
+    def www_view_drop_from_queue(self, request, queue, message_id):
+        if not request.user.is_authenticated:
+            raise PermissionDenied()
+        m = Message.objects.filter(message_id=message_id).first()
+        if not m:
+            raise Http404("Series not found")
+        self._drop_from_queue(request.user, m, queue)
+        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
+
     def www_url_hook(self, urlpatterns):
         urlpatterns.append(url(r"^mark-as-merged/(?P<message_id>.*)/",
                                self.www_view_mark_as_merged,
@@ -85,50 +116,91 @@ class MaintainerModule(PatchewModule):
         urlpatterns.append(url(r"^clear-reviewed/(?P<message_id>.*)/",
                                self.www_view_clear_reviewed,
                                name="clear-reviewed"))
+        urlpatterns.append(url(r"^add-to-queue/(?P<message_id>.*)/",
+                               self.www_view_add_to_queue,
+                               name="add-to-queue"))
+        urlpatterns.append(url(r"^drop-from-queue/(?P<queue>[^/]*)/(?P<message_id>.*)/",
+                               self.www_view_drop_from_queue,
+                               name="drop-from-queue"))
 
     def prepare_message_hook(self, request, message, detailed):
         if not detailed or not request.user.is_authenticated:
             return
-        if message.is_series_head:
-            if message.is_merged:
-                message.extra_ops.append({"url": reverse("clear-merged",
-                                                         kwargs={"message_id": message.message_id}),
-                                          "icon": "eraser",
-                                          "title": "Clear merged state"})
+        if not message.is_series_head:
+            return
+        if message.is_merged:
+            message.extra_ops.append({"url": reverse("clear-merged",
+                                                     kwargs={"message_id": message.message_id}),
+                                      "icon": "eraser",
+                                      "title": "Clear merged state"})
+        else:
+            message.extra_ops.append({"url": reverse("mark-as-merged",
+                                                     kwargs={"message_id": message.message_id}),
+                                      "icon": "check",
+                                      "title": "Mark series as merged"})
+
+        accepted = False
+        rejected = False
+        queues = []
+        for r in Queue.objects.filter(user=request.user, message=message):
+            if r.name == 'accept':
+                message.extra_status.append({
+                    "icon": "fa-check",
+                    "html": 'The series is marked for merging'
+                })
+                accepted = True
+            elif r.name == 'reject':
+                message.extra_status.append({
+                    "icon": "fa-times",
+                    "html": 'The series is marked as rejected'
+                })
+                rejected = True
             else:
-                message.extra_ops.append({"url": reverse("mark-as-merged",
-                                                         kwargs={"message_id": message.message_id}),
-                                          "icon": "check",
-                                          "title": "Mark series as merged"})
-
-        r = Queue.objects.filter(user=request.user, message=message,
-                                 name__in=['accept', 'reject']).first()
-        if r and r.name == 'accept':
-            message.extra_status.append({
-                "icon": "fa-check",
-                "html": 'The series is marked for merging'
-            })
-        else:
-            if message.is_series_head:
-                message.extra_ops.append({"url": reverse("mark-as-accepted",
-                                                         kwargs={"message_id": message.message_id}),
-                                          "icon": "check",
-                                          "title": "Mark series as accepted"})
-
-        if r and r.name == 'reject':
-            message.extra_status.append({
-                "icon": "fa-times",
-                "html": 'The series is marked as rejected'
-            })
-        else:
-            if message.is_series_head:
-                message.extra_ops.append({"url": reverse("mark-as-rejected",
-                                                         kwargs={"message_id": message.message_id}),
-                                          "icon": "times",
-                                          "title": "Mark series as rejected"})
-
-        if r:
+                queues.append(r.name)
+                message.extra_ops.append({
+                    "url": reverse("drop-from-queue",
+                                   kwargs={
+                                       "queue": r.name,
+                                       "message_id": message.message_id
+                                   }),
+                                   "icon": "remove",
+                                   "title": "Drop from queue '%s'" % r.name})
+        if not accepted:
+            message.extra_ops.append({"url": reverse("mark-as-accepted",
+                                                     kwargs={"message_id": message.message_id}),
+                                      "icon": "check",
+                                      "title": "Mark series as accepted"})
+        if not rejected:
+            message.extra_ops.append({"url": reverse("mark-as-rejected",
+                                                     kwargs={"message_id": message.message_id}),
+                                      "icon": "times",
+                                      "title": "Mark series as rejected"})
+        if accepted or rejected:
             message.extra_ops.append({"url": reverse("clear-reviewed",
                                                      kwargs={"message_id": message.message_id}),
                                       "icon": "eraser",
                                       "title": "Clear review state"})
+
+        if queues:
+            message.extra_status.append({
+                "icon": "fa-bookmark",
+                "html": 'The series is queued in: %s' % ', '.join(queues),
+            })
+        for q in Queue.objects.filter(user=request.user).values("name").distinct():
+            qn = q["name"]
+            if qn in queues + ['reject', 'accept']:
+                continue
+            message.extra_ops.append({
+                "url": "%s?queue=%s" % (\
+                        reverse("add-to-queue",
+                                kwargs={"message_id": message.message_id}),
+                        qn),
+                "icon": "bookmark",
+                "title": "Add to '%s' queue" % qn})
+
+        message.extra_ops.append({
+            "url": reverse("add-to-queue",
+                           kwargs={"message_id": message.message_id}),
+            "get_prompt": {"queue": "What is the name of the new queue?" },
+            "icon": "bookmark",
+            "title": "Add to new queue..."})
diff --git a/www/templates/series-detail.html b/www/templates/series-detail.html
index c7b7f1d..dcf7b79 100644
--- a/www/templates/series-detail.html
+++ b/www/templates/series-detail.html
@@ -40,11 +40,39 @@
   <ul>
     {% for op in series.extra_ops %}
     <li>
+      {% if op.get_prompt %}
+          {% for k, v in op.get_prompt.items %}
+            <input type="hidden" name="{{ k }}" value="{{ v }}" />
+          {% endfor %}
+      {% endif %}
       <span class="fa fa-{{ op.icon | default:"question" }}"></span><a
-        href="{{ op.url }}">{{ op.title }}</a></li>
+        {% if op.get_prompt %}
+         href="#"
+         onclick="prompt_and_open(this, '{{ op.url }}')"
+        {% else %}
+         href="{{ op.url }}"
+        {% endif %}">{{ op.title }}</a></li>
     {% endfor %}
   </ul>
 </div>
+<script type="text/javascript">
+function prompt_and_open(obj, url) {
+    params = {};
+    cancel = false;
+    $(obj).parent().find("input").each(function() {
+            field = this.name;
+            val = prompt(this.value);
+            if (!val) {
+                cancel = true;
+                return false;
+            }
+            params[field] = val;
+    });
+    if (!cancel) {
+        window.location.href = url + "?" + $.param(params);
+    }
+}
+</script>
 {% endif %}
 
 <div class="status">
-- 
2.17.2





More information about the Patchew-devel mailing list