From patchwork Thu Jul 22 17:12:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raxel Gutierrez X-Patchwork-Id: 1508810 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=U8/Bj4R9; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GVzYl43FZz9sRR for ; Fri, 23 Jul 2021 03:13:31 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4GVzYl2vM4z30Hd for ; Fri, 23 Jul 2021 03:13:31 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=U8/Bj4R9; dkim-atps=neutral X-Original-To: patchwork@lists.ozlabs.org Delivered-To: patchwork@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=flex--raxel.bounces.google.com (client-ip=2607:f8b0:4864:20::f4a; helo=mail-qv1-xf4a.google.com; envelope-from=3l6f5yaukcxihqnubweewbu.secfqjsxmehabyiji.epbqri.ehw@flex--raxel.bounces.google.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=U8/Bj4R9; dkim-atps=neutral Received: from mail-qv1-xf4a.google.com (mail-qv1-xf4a.google.com [IPv6:2607:f8b0:4864:20::f4a]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4GVzYY4kfnz30FM for ; Fri, 23 Jul 2021 03:13:21 +1000 (AEST) Received: by mail-qv1-xf4a.google.com with SMTP id d17-20020a0cfe910000b02902e01fc8ee77so4085464qvs.21 for ; Thu, 22 Jul 2021 10:13:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=LmJVcRZsGFFdxNx0pkLoyvV2fnnKVS3t+di+8jS1LCM=; b=U8/Bj4R9CXMItcAb55+JrB448ON8NmOOs28gMbVeXKFOVu9WdoGjA/xGQMUusBLoFw x2xH2veUibpoJKQBAEJINwtzItPcjvPG2nPvi6K/vRPpimhPPDMCyl6HPEbMD7jnIxU3 w1tdwF4knDx0yw6QnYBQ9/7/koiBlbRsa3oI7Qw7lRsPOIYNGBThUFi9sILItvAQ2jMk dP4RxlTWHem9ZfJb931pvc7zNSObt0FsWjuSRp0W0WJdVPXu+AYp5/iywV0zWKC3J53G GDpcBsMluJgRpskdbF0pUqiSt3WRwfy9F3pPkjoACdai+5+aYHUDCBQ+6HjjDAvA16+j sAEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=LmJVcRZsGFFdxNx0pkLoyvV2fnnKVS3t+di+8jS1LCM=; b=HG8rmTJSHBYLuNStuWzPaAieZSZUHC/QceoiqseA9eGUkzDyGa1Xun1N7RhroEXVai omX1lPCiAKvy9ejtsKut4VzXNjaCmRtjEcy1IiqRCFdsWtuDR9eu/ax5/YWp+jcxI1qd 4+FfCra03j8+ejkPEZ2FJsRrGDDWLl7kpp4nqL1IkI7xUFI7ysXFpvySjShOV8eJyKIU 5Ngwe6CCBDb3tvBYAxgGhR/aiif5uap/xTPL8wRs+5qLgDK5ZhksvYfY7qE5x1wYD7J2 2pm7ZMttQAvvWIuAg0F+HRFmSKql++0/Um1k867JJp8pVz7cvinGY4BGEi6sbXDLogqV HCSw== X-Gm-Message-State: AOAM533gasT4ynibZer0gWap6lD68Kz1LgjY3CcGVBY2TPkzYerhm1oW WNiGBj99s4JBjLTik0C1lOfzIZ75QB+fiBbUpdOSot7lku2SxTpj6Q48Jk6zmIB9RfqBb+LZQoG B14GOh3tWOrXbBpyy9HvYAYtFampgorZT2jsCfkRItojbAQguKomCWJhgZDVNb1ln X-Google-Smtp-Source: ABdhPJyTKSv6gHqIv1Bn6uYWi1Q1jKg8/WMkzfrYZRBuNpWVQskbSFFYs7EGI5UFK0ly+YgyWBOdgYkkIA== X-Received: from raxel-pw.c.googlers.com ([fda3:e722:ac3:cc00:14:4d90:c0a8:2fda]) (user=raxel job=sendgmr) by 2002:ad4:56e8:: with SMTP id cr8mr754991qvb.53.1626973999290; Thu, 22 Jul 2021 10:13:19 -0700 (PDT) Date: Thu, 22 Jul 2021 17:12:48 +0000 In-Reply-To: <20210722171251.2554142-1-raxel@google.com> Message-Id: <20210722171251.2554142-3-raxel@google.com> Mime-Version: 1.0 References: <20210722171251.2554142-1-raxel@google.com> X-Mailer: git-send-email 2.32.0.432.gabb21c7263-goog Subject: [PATCH v2 2/5] patch-list: clean up patch-list page and refactor patch forms From: Raxel Gutierrez To: patchwork@lists.ozlabs.org X-BeenThere: patchwork@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Patchwork development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Patchwork" Clean up the patch-list page by moving forms to a new template file patch-forms.html and moving them to the top of the page, adding ids to table cells, and renaming selectors using hyphen delimited strings where the relevant changes were made. Also, created a partial template for errors that render with form submission. These changes improve the discoverability of the patch-list forms and makes the code healthier, ready for change, and overall more readable. Also, move patch-list related js code to a new patch-list.js file, to make the JavaScript easy to read and change in one place. This makes automatic code formatting easier, makes it more straightforward to measure test coverage and discover opportunities for refactoring, and simplifies a possible future migration to TypeScript if the project chooses to go in that direction. Refactor forms.py, __init__.py, patch.py, and test_bundles.py files so that the shared bundle form in patch-forms.html works for both the patch-list and patch-detail pages. Error messages and success/warning messages are now normalized throughout these files for testing and functionality. Also, important to these change is that CreateBundleForm in forms.py handles the validation of the bundle form input so that now the patch-list bundle form also makes use of the Django forms API. Signed-off-by: Raxel Gutierrez --- htdocs/README.rst | 7 + htdocs/css/style.css | 10 +- htdocs/js/patch-list.js | 12 ++ patchwork/forms.py | 20 ++- patchwork/templates/patchwork/list.html | 11 +- .../templates/patchwork/partials/errors.html | 9 ++ .../patchwork/partials/patch-forms.html | 45 ++++++ .../patchwork/partials/patch-list.html | 131 +++--------------- patchwork/templates/patchwork/submission.html | 91 +----------- patchwork/tests/views/test_bundles.py | 44 +++--- patchwork/tests/views/test_patch.py | 4 +- patchwork/views/__init__.py | 73 +++++----- patchwork/views/patch.py | 33 ++--- 13 files changed, 194 insertions(+), 296 deletions(-) create mode 100644 htdocs/js/patch-list.js create mode 100644 patchwork/templates/patchwork/partials/errors.html create mode 100644 patchwork/templates/patchwork/partials/patch-forms.html diff --git a/htdocs/README.rst b/htdocs/README.rst index fa1616c..a018f31 100644 --- a/htdocs/README.rst +++ b/htdocs/README.rst @@ -131,6 +131,13 @@ js :GitHub: https://github.com/js-cookie/js-cookie/ :Version: 2.2.1 +``patch-list.js.`` + + Utility functions for patch list manipulation (inline dropdown changes, + etc.) + + Part of Patchwork. + ``selectize.min.js`` Selectize is the hybrid of a ``textbox`` and `` + + {% if bundles %} +
+ + +
+ {% endif %} + {% if bundle %} +
+ + +
+ {% endif %} + +{% endif %} + diff --git a/patchwork/templates/patchwork/partials/patch-list.html b/patchwork/templates/patchwork/partials/patch-list.html index 02d6dff..339cf42 100644 --- a/patchwork/templates/patchwork/partials/patch-list.html +++ b/patchwork/templates/patchwork/partials/patch-list.html @@ -4,9 +4,11 @@ {% load project %} {% load static %} -{% include "patchwork/partials/filters.html" %} +{% block headers %} + +{% endblock %} -{% include "patchwork/partials/pagination.html" %} +{% include "patchwork/partials/filters.html" %} {% if order.editable %} @@ -29,31 +31,20 @@ {% if page.paginator.long_page and user.is_authenticated %} {% endif %} - - - + {% csrf_token %} - + +
+ {% include "patchwork/partials/patch-forms.html" %} + {% include "patchwork/partials/pagination.html" %} +
@@ -174,9 +165,9 @@ $(document).ready(function() { {% for patch in page.object_list %} - + {% if user.is_authenticated %} - {% endif %} @@ -188,24 +179,24 @@ $(document).ready(function() { {% endif %} - - - - - - - - + + + + + + {% empty %} @@ -217,86 +208,6 @@ $(document).ready(function() { {% if page.paginator.count %} {% include "patchwork/partials/pagination.html" %} - -
- -{% if patchform %} -
-

Properties

-
+ + {{ patch.name|default:"[no subject]"|truncatechars:100 }} + {% if patch.series %} {{ patch.series|truncatechars:100 }} {% endif %} {{ patch|patch_tags }}{{ patch|patch_checks }}{{ patch.date|date:"Y-m-d" }}{{ patch.submitter|personify:project }}{{ patch.delegate.username }}{{ patch.state }}{{ patch|patch_tags }}{{ patch|patch_checks }}{{ patch.date|date:"Y-m-d" }}{{ patch.submitter|personify:project }}{{ patch.delegate.username }}{{ patch.state }}
- - - - - - - - - - - - - - - - -
Change state: - {{ patchform.state }} - {{ patchform.state.errors }} -
Delegate to: - {{ patchform.delegate }} - {{ patchform.delegate.errors }} -
Archive: - {{ patchform.archived }} - {{ patchform.archived.errors }} -
- -
- - -{% endif %} - -{% if user.is_authenticated %} -
-

Bundling

- - - - - - {% if bundles %} - - - - - {% endif %} - {% if bundle %} - - - - - {% endif %} -
Create bundle: - - -
Add to bundle: - - -
Remove from bundle: - - -
-
-{% endif %} - -
-
- - {% endif %} diff --git a/patchwork/templates/patchwork/submission.html b/patchwork/templates/patchwork/submission.html index 978559b..17255ee 100644 --- a/patchwork/templates/patchwork/submission.html +++ b/patchwork/templates/patchwork/submission.html @@ -27,6 +27,8 @@ function toggle_div(link_id, headers_id, label_show, label_hide) } +{% include "patchwork/partials/errors.html" %} +
{% include "patchwork/partials/download-buttons.html" %}

{{ submission.name }}

@@ -149,91 +151,10 @@ function toggle_div(link_id, headers_id, label_show, label_hide) {% endif %} -
-{% if patchform %} -
-

Patch Properties

-
- {% csrf_token %} - - - - - - - - - - - - - - - - - -
Change state: - {{ patchform.state }} - {{ patchform.state.errors }} -
Delegate to: - {{ patchform.delegate }} - {{ patchform.delegate.errors }} -
Archived: - {{ patchform.archived }} - {{ patchform.archived.errors }} -
- -
-
-
-{% endif %} - -{% if createbundleform %} -
-

Bundling

- - - - - -{% if bundles %} - - - - -{% endif %} -
Create bundle: - {% if createbundleform.non_field_errors %} -
{{createbundleform.non_field_errors}}
- {% endif %} -
- {% csrf_token %} - - {% if createbundleform.name.errors %} -
{{createbundleform.name.errors}}
- {% endif %} - {{ createbundleform.name }} - -
-
Add to bundle: -
- {% csrf_token %} - - - -
-
- -
-{% endif %} - -
-
-
+
+ {% csrf_token %} + {% include "patchwork/partials/patch-forms.html" %} +
{% if submission.pull_url %}

Pull-request

diff --git a/patchwork/tests/views/test_bundles.py b/patchwork/tests/views/test_bundles.py index 6a74409..2233c21 100644 --- a/patchwork/tests/views/test_bundles.py +++ b/patchwork/tests/views/test_bundles.py @@ -146,7 +146,7 @@ class BundleUpdateTest(BundleTestBase): data = { 'form': 'bundle', 'action': 'update', - 'name': newname, + 'bundle_name': newname, 'public': '', } response = self.client.post(bundle_url(self.bundle), data) @@ -159,7 +159,7 @@ class BundleUpdateTest(BundleTestBase): data = { 'form': 'bundle', 'action': 'update', - 'name': self.bundle.name, + 'bundle_name': self.bundle.name, 'public': 'on', } response = self.client.post(bundle_url(self.bundle), data) @@ -243,7 +243,7 @@ class BundlePublicModifyTest(BundleTestBase): data = { 'form': 'bundle', 'action': 'update', - 'name': newname, + 'bundle_name': newname, } self.bundle.name = oldname self.bundle.save() @@ -353,7 +353,7 @@ class BundleCreateFromListTest(BundleTestBase): def test_create_empty_bundle(self): newbundlename = 'testbundle-new' - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'bundle_name': newbundlename, 'action': 'Create', 'project': self.project.id} @@ -369,7 +369,7 @@ class BundleCreateFromListTest(BundleTestBase): newbundlename = 'testbundle-new' patch = self.patches[0] - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'bundle_name': newbundlename, 'action': 'Create', 'project': self.project.id, @@ -393,7 +393,7 @@ class BundleCreateFromListTest(BundleTestBase): n_bundles = Bundle.objects.count() - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'bundle_name': '', 'action': 'Create', 'project': self.project.id, @@ -414,7 +414,7 @@ class BundleCreateFromListTest(BundleTestBase): newbundlename = 'testbundle-dup' patch = self.patches[0] - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'bundle_name': newbundlename, 'action': 'Create', 'project': self.project.id, @@ -440,7 +440,9 @@ class BundleCreateFromListTest(BundleTestBase): params) self.assertNotContains(response, 'Bundle %s created' % newbundlename) - self.assertContains(response, 'You already have a bundle called') + self.assertContains( + response, + 'A bundle called %s already exists' % newbundlename) self.assertEqual(Bundle.objects.count(), n_bundles) self.assertEqual(bundle.patches.count(), 1) @@ -451,8 +453,8 @@ class BundleCreateFromPatchTest(BundleTestBase): newbundlename = 'testbundle-new' patch = self.patches[0] - params = {'name': newbundlename, - 'action': 'createbundle'} + params = {'bundle_name': newbundlename, + 'action': 'Create'} response = self.client.post( reverse('patch-detail', @@ -470,8 +472,8 @@ class BundleCreateFromPatchTest(BundleTestBase): newbundlename = self.bundle.name patch = self.patches[0] - params = {'name': newbundlename, - 'action': 'createbundle'} + params = {'bundle_name': newbundlename, + 'action': 'Create'} response = self.client.post( reverse('patch-detail', @@ -489,7 +491,7 @@ class BundleAddFromListTest(BundleTestBase): def test_add_to_empty_bundle(self): patch = self.patches[0] - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'action': 'Add', 'project': self.project.id, 'bundle_id': self.bundle.id, @@ -509,7 +511,7 @@ class BundleAddFromListTest(BundleTestBase): def test_add_to_non_empty_bundle(self): self.bundle.append_patch(self.patches[0]) patch = self.patches[1] - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'action': 'Add', 'project': self.project.id, 'bundle_id': self.bundle.id, @@ -538,7 +540,7 @@ class BundleAddFromListTest(BundleTestBase): count = self.bundle.patches.count() patch = self.patches[0] - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'action': 'Add', 'project': self.project.id, 'bundle_id': self.bundle.id, @@ -559,7 +561,7 @@ class BundleAddFromListTest(BundleTestBase): count = self.bundle.patches.count() patch = self.patches[0] - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'action': 'Add', 'project': self.project.id, 'bundle_id': self.bundle.id, @@ -584,7 +586,7 @@ class BundleAddFromPatchTest(BundleTestBase): def test_add_to_empty_bundle(self): patch = self.patches[0] - params = {'action': 'addtobundle', + params = {'action': 'Add', 'bundle_id': self.bundle.id} response = self.client.post( @@ -594,7 +596,7 @@ class BundleAddFromPatchTest(BundleTestBase): self.assertContains( response, - 'added to bundle "%s"' % self.bundle.name, + 'added to bundle %s' % self.bundle.name, count=1) self.assertEqual(self.bundle.patches.count(), 1) @@ -603,7 +605,7 @@ class BundleAddFromPatchTest(BundleTestBase): def test_add_to_non_empty_bundle(self): self.bundle.append_patch(self.patches[0]) patch = self.patches[1] - params = {'action': 'addtobundle', + params = {'action': 'Add', 'bundle_id': self.bundle.id} response = self.client.post( @@ -613,7 +615,7 @@ class BundleAddFromPatchTest(BundleTestBase): self.assertContains( response, - 'added to bundle "%s"' % self.bundle.name, + 'added to bundle %s' % self.bundle.name, count=1) self.assertEqual(self.bundle.patches.count(), 2) @@ -650,7 +652,7 @@ class BundleInitialOrderTest(BundleTestBase): newbundlename = 'testbundle-new' # need to define our querystring explicity to enforce ordering - params = {'form': 'patchlistform', + params = {'form': 'patch-list-form', 'bundle_name': newbundlename, 'action': 'Create', 'project': self.project.id, diff --git a/patchwork/tests/views/test_patch.py b/patchwork/tests/views/test_patch.py index 1a1243c..483ab99 100644 --- a/patchwork/tests/views/test_patch.py +++ b/patchwork/tests/views/test_patch.py @@ -304,7 +304,7 @@ class PatchViewTest(TestCase): class PatchUpdateTest(TestCase): - properties_form_id = 'patchform-properties' + properties_form_id = 'patch-form-properties' def setUp(self): self.project = create_project() @@ -318,7 +318,7 @@ class PatchUpdateTest(TestCase): self.base_data = { 'action': 'Update', 'project': str(self.project.id), - 'form': 'patchlistform', + 'form': 'patch-list-form', 'archived': '*', 'delegate': '*', 'state': '*' diff --git a/patchwork/views/__init__.py b/patchwork/views/__init__.py index 3efe90c..178d185 100644 --- a/patchwork/views/__init__.py +++ b/patchwork/views/__init__.py @@ -2,6 +2,7 @@ # Copyright (C) 2008 Jeremy Kerr # # SPDX-License-Identifier: GPL-2.0-or-later +import json from django.contrib import messages from django.shortcuts import get_object_or_404 @@ -9,6 +10,7 @@ from django.db.models import Prefetch from patchwork.filters import Filters from patchwork.forms import MultiplePatchForm +from patchwork.forms import CreateBundleForm from patchwork.models import Bundle from patchwork.models import BundlePatch from patchwork.models import Patch @@ -16,7 +18,6 @@ from patchwork.models import Project from patchwork.models import Check from patchwork.paginator import Paginator - bundle_actions = ['create', 'add', 'remove'] @@ -108,46 +109,35 @@ class Order(object): # TODO(stephenfin): Refactor this to break it into multiple, testable functions -def set_bundle(request, project, action, data, patches, context): +def set_bundle(request, project, action, data, patches): # set up the bundle bundle = None user = request.user if action == 'create': bundle_name = data['bundle_name'].strip() - if '/' in bundle_name: - return ['Bundle names can\'t contain slashes'] - - if not bundle_name: - return ['No bundle name was specified'] - - if Bundle.objects.filter(owner=user, name=bundle_name).count() > 0: - return ['You already have a bundle called "%s"' % bundle_name] - bundle = Bundle(owner=user, project=project, name=bundle_name) - bundle.save() - messages.success(request, "Bundle %s created" % bundle.name) + create_bundle_form = CreateBundleForm(instance=bundle, + data=request.POST) + if create_bundle_form.is_valid(): + create_bundle_form.save() + addBundlePatches(request, patches, bundle) + bundle.save() + create_bundle_form = CreateBundleForm() + messages.success(request, 'Bundle %s created' % bundle.name) + else: + formErrors = json.loads(create_bundle_form.errors.as_json()) + errors = [formErrors['name'][0]['message']] + return errors elif action == 'add': + if not data['bundle_id']: + return ['No bundle was selected'] bundle = get_object_or_404(Bundle, id=data['bundle_id']) + addBundlePatches(request, patches, bundle) elif action == 'remove': bundle = get_object_or_404(Bundle, id=data['removed_bundle_id']) - - if not bundle: - return ['no such bundle'] - - for patch in patches: - if action in ['create', 'add']: - bundlepatch_count = BundlePatch.objects.filter(bundle=bundle, - patch=patch).count() - if bundlepatch_count == 0: - bundle.append_patch(patch) - messages.success(request, "Patch '%s' added to bundle %s" % - (patch.name, bundle.name)) - else: - messages.warning(request, "Patch '%s' already in bundle %s" % - (patch.name, bundle.name)) - elif action == 'remove': + for patch in patches: try: bp = BundlePatch.objects.get(bundle=bundle, patch=patch) bp.delete() @@ -158,10 +148,21 @@ def set_bundle(request, project, action, data, patches, context): request, "Patch '%s' removed from bundle %s\n" % (patch.name, bundle.name)) + return [] - bundle.save() - return [] +def addBundlePatches(request, patches, bundle): + for patch in patches: + bundlepatch_count = BundlePatch.objects.filter(bundle=bundle, + patch=patch).count() + if bundlepatch_count == 0: + bundle.append_patch(patch) + bundle.save() + messages.success(request, "Patch '%s' added to bundle %s" % + (patch.name, bundle.name)) + else: + messages.warning(request, "Patch '%s' already in bundle %s" % + (patch.name, bundle.name)) def generic_list(request, project, view, view_args=None, filter_settings=None, @@ -216,17 +217,20 @@ def generic_list(request, project, view, view_args=None, filter_settings=None, data = None user = request.user properties_form = None + create_bundle_form = None if user.is_authenticated: # we only pass the post data to the MultiplePatchForm if that was # the actual form submitted data_tmp = None - if data and data.get('form', '') == 'patchlistform': + if data and data.get('form', '') == 'patch-list-form': data_tmp = data properties_form = MultiplePatchForm(project, data=data_tmp) + if request.user.is_authenticated: + create_bundle_form = CreateBundleForm() - if request.method == 'POST' and data.get('form') == 'patchlistform': + if request.method == 'POST' and data.get('form') == 'patch-list-form': action = data.get('action', '').lower() # special case: the user may have hit enter in the 'create bundle' @@ -237,7 +241,7 @@ def generic_list(request, project, view, view_args=None, filter_settings=None, ps = Patch.objects.filter(id__in=get_patch_ids(data)) if action in bundle_actions: - errors = set_bundle(request, project, action, data, ps, context) + errors = set_bundle(request, project, action, data, ps) elif properties_form and action == properties_form.action: errors = process_multiplepatch_form(request, properties_form, @@ -288,6 +292,7 @@ def generic_list(request, project, view, view_args=None, filter_settings=None, context.update({ 'page': paginator.current_page, 'patchform': properties_form, + 'createbundleform': create_bundle_form, 'project': project, 'order': order, }) diff --git a/patchwork/views/patch.py b/patchwork/views/patch.py index 3e6874a..5ef6916 100644 --- a/patchwork/views/patch.py +++ b/patchwork/views/patch.py @@ -14,11 +14,11 @@ from django.urls import reverse from patchwork.forms import CreateBundleForm from patchwork.forms import PatchForm -from patchwork.models import Bundle from patchwork.models import Cover from patchwork.models import Patch from patchwork.models import Project from patchwork.views import generic_list +from patchwork.views import set_bundle from patchwork.views.utils import patch_to_mbox from patchwork.views.utils import series_patch_to_mbox @@ -60,6 +60,7 @@ def patch_detail(request, project_id, msgid): form = None createbundleform = None + errors = None if editable: form = PatchForm(instance=patch) @@ -71,30 +72,10 @@ def patch_detail(request, project_id, msgid): if action: action = action.lower() - if action == 'createbundle': - bundle = Bundle(owner=request.user, project=project) - createbundleform = CreateBundleForm(instance=bundle, - data=request.POST) - if createbundleform.is_valid(): - createbundleform.save() - bundle.append_patch(patch) - bundle.save() - createbundleform = CreateBundleForm() - messages.success(request, 'Bundle %s created' % bundle.name) - elif action == 'addtobundle': - bundle = get_object_or_404( - Bundle, id=request.POST.get('bundle_id')) - if bundle.append_patch(patch): - messages.success(request, - 'Patch "%s" added to bundle "%s"' % ( - patch.name, bundle.name)) - else: - messages.error(request, - 'Failed to add patch "%s" to bundle "%s": ' - 'patch is already in bundle' % ( - patch.name, bundle.name)) - - # all other actions require edit privs + if action in ['create', 'add']: + errors = set_bundle(request, project, action, + request.POST, [patch]) + elif not editable: return HttpResponseForbidden() @@ -133,6 +114,8 @@ def patch_detail(request, project_id, msgid): context['project'] = patch.project context['related_same_project'] = related_same_project context['related_different_project'] = related_different_project + if errors: + context['errors'] = errors return render(request, 'patchwork/submission.html', context)