Commit f1f804d6 authored by Arkadiusz Hiler's avatar Arkadiusz Hiler

Allow navigating to other patches from a patch

If navigating to a patch from a series/revision view a ?series=x&rev=y
are appended to the URL.

This is later used on the patch view to determine whether browsing this
patch from the series view. If that's the case new navigation options to
go to next and previous patches in series are available.

Closes #13Signed-off-by: Arkadiusz Hiler's avatarArkadiusz Hiler <arkadiusz.hiler@intel.com>
parent d4532ccd
Pipeline #22229 passed with stage
in 2 minutes and 26 seconds
......@@ -342,6 +342,11 @@ class Patch(models.Model):
except Exception:
return None
def all_revisions(self):
srp = SeriesRevisionPatch.objects.filter(patch=self)
revs = [x.revision for x in srp]
return revs
def _set_tag(self, tag, count):
if count == 0:
self.patchtag_set.filter(tag=tag).delete()
......@@ -565,6 +570,24 @@ class Series(models.Model):
verbose_name_plural = 'Series'
ordering = ["-id"]
def __lt__(self, other):
return self.pk < other.pk
def __le__(self, other):
return self.pk <= other.pk
def __eq__(self, other):
return self.pk == other.pk
def __ne__(self, other):
return self.pk != other.pk
def __gt__(self, other):
return self.pk > other.pk
def __ge__(self, other):
return self.pk >= other.pk
# Signal one can listen to to know when a revision is complete (ie. has all of
# its patches)
......
......@@ -32,45 +32,79 @@ function toggle_headers(link_id, headers_id)
</div>
<h2>Details</h2>
<div style="display: flex; width: 100%">
<table class="patchmeta">
<tr>
<th>Message ID</th>
<td>{{ patch.msgid|msgid }}</td>
</tr>
<tr>
<th>State</th>
<td>{{ patch.state.name }}{% if patch.archived %}, archived{% endif %}</td>
</tr>
{% if series %}
<tr>
<th>Series</th>
<td><a href="{% url 'series' series=series.id %}"/>"{{ series }}"</a></td>
</tr>
{% endif %}
{% if patch.commit_ref %}
<tr>
<th>Commit</th>
<td>{{ patch.commit_ref }}</td>
</tr>
{% endif %}
{% if patch.delegate %}
<tr>
<th>Delegated to:</th>
<td>{{ patch.delegate.profile.name }}</td>
</tr>
{% endif %}
<tr>
<th>Headers</th>
<td><a id="togglepatchheaders"
href="javascript:toggle_headers('togglepatchheaders', 'patchheaders')"
>show</a>
<div id="patchheaders" class="patchheaders" style="display:none;">
<pre>{{patch.headers}}</pre>
</div>
</td>
</tr>
</table>
<div style="width: 50%">
<table class="patchmeta">
<tr>
<th>Message ID</th>
<td>{{ patch.msgid|msgid }}</td>
</tr>
<tr>
<th>State</th>
<td>{{ patch.state.name }}{% if patch.archived %}, archived{% endif %}</td>
</tr>
{% if patch.commit_ref %}
<tr>
<th>Commit</th>
<td>{{ patch.commit_ref }}</td>
</tr>
{% endif %}
{% if patch.delegate %}
<tr>
<th>Delegated to:</th>
<td>{{ patch.delegate.profile.name }}</td>
</tr>
{% endif %}
<tr>
<th>Headers</th>
<td><a id="togglepatchheaders"
href="javascript:toggle_headers('togglepatchheaders', 'patchheaders')"
>show</a>
<div id="patchheaders" class="patchheaders" style="display:none;">
<pre>{{patch.headers}}</pre>
</div>
</td>
</tr>
{% for series, revs in seriesrevisions %}
<tr>
<th>{% if forloop.first %} Series{% endif %}</th>
<td>
<a href="{% url 'series' series=series.id %}"/>"{{ series }}"</a>
( rev:
{% for rev in revs %}
<a href="{% url 'series' series=series.id %}#rev{{ rev.version }}"/>{{ rev.version }}</a>
{% endfor %})
in
<a href="{% url 'series_list' project=series.project.linkname %}"/>{{ series.project.name }}</a> <br/>
</td>
</tr>
{% endfor %}
</table>
</div>
<div style="width: 50%; text-align: right;" class="series-info">
<br/>
{% if current_revision %}
<b>Browsing this patch as part of:</b><br/>
<a href="{% url 'series' series=current_revision.series.id %}#rev{{ current_revision.version }}"/>"{{ current_revision.series }}" rev {{ current_revision.version }}</a> in
<a href="{% url 'series_list' project=current_revision.series.project.linkname %}"/>{{ current_revision.series.project.name }}</a> <br/>
{% if prev_patch %}
<a href="{% url 'patch' patch_id=prev_patch.id %}?series={{ current_revision.series.id }}&rev={{ current_revision.version }}">&lt;&lt; prev patch</a>
{% else %}
&lt;&lt; prev patch
{% endif %}
[{{ current_patch_number }}/{{ patch_count }}]
{% if next_patch %}
<a href="{% url 'patch' patch_id=next_patch.id %}?series={{ current_revision.series.id }}&rev={{ current_revision.version }}">next patch &gt;&gt;</a>
{% else %}
next patch &gt;&gt;
{% endif %}
{% else %}
<b>Not browsing as part of any series.</b>
{% endif %}
</div>
</div>
<div class="patchforms">
......
......@@ -174,7 +174,7 @@ $(document).ready(function() {
{% for patch in revision.patch_list %}
<tr>
<td></td>
<td><a href="{% url 'patch' patch_id=patch.id %}"
<td><a href="{% url 'patch' patch_id=patch.id %}?series={{ revision.series_id }}&rev={{ revision.version }}"
>{{ patch.name|default:"[no subject]"|truncatechars:100 }}</a></td>
<td>{{ patch.submitter|personify:project }}</td>
<td>{{ patch.state }}</td>
......
......@@ -36,6 +36,13 @@ from patchwork.models import (Bundle, BundlePatch, PatchChangeNotification,
EmailOptout, EmailConfirmation)
def group(iterable, key):
"""Sort and group in one go"""
sorted_iterable = sorted(iterable, key=key)
groupped = itertools.groupby(sorted_iterable, key)
return [(k, list(v)) for k, v in groupped]
def get_patch_ids(d, prefix='patch_id'):
ids = []
......
......@@ -41,8 +41,8 @@ from patchwork.serializers import (ProjectSerializer, SeriesSerializer,
from patchwork.views import patch_to_mbox, revision_cover_letter_to_mbox
from patchwork.views.patch import mbox as patch_mbox
from patchwork.permissions import Can
from patchwork.utils import group
import django_filters
import itertools
API_REVISION = 4
......@@ -568,12 +568,6 @@ class PatchViewSet(mixins.ListModelMixin,
return patch_mbox(request, pk)
def group(iterable, key):
"""Sort and group in one go"""
sorted_iterable = sorted(iterable, key=key)
return itertools.groupby(sorted_iterable, key)
class MsgidResultsView(views.APIView):
def get(self, request, msgid):
output = []
......
......@@ -23,8 +23,9 @@ from django.http import HttpResponse, HttpResponseForbidden, Http404
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import six
from patchwork.utils import group
from patchwork.forms import PatchForm, CreateBundleForm
from patchwork.models import Patch, Project, Bundle, TestResult
from patchwork.models import Patch, Project, Bundle, TestResult, SeriesRevision
from patchwork.views import generic_list, patch_to_mbox
from patchwork.permissions import Can
......@@ -37,6 +38,19 @@ def patch(request, patch_id):
form = None
createbundleform = None
current_revision = None
if request.method == 'GET':
series = request.GET.get('series', None)
rev = request.GET.get('rev', None)
if series and rev:
try:
current_revision = SeriesRevision.objects.get(
series_id=int(series),
version=int(rev))
except Exception:
raise Http404("Wrong series/revision")
if editable:
form = PatchForm(instance=patch)
if request.user.is_authenticated():
......@@ -79,9 +93,31 @@ def patch(request, patch_id):
form.save()
messages += ['Patch updated']
prev_patch = None
next_patch = None
patch_count = 0
current_patch_number = 0
if current_revision:
all_patches = [x for x in current_revision.patches.all()]
patch_count = len(all_patches)
current_patch_index = all_patches.index(patch)
current_patch_number = current_patch_index + 1
if (current_patch_index + 1) < patch_count:
next_patch = all_patches[current_patch_index + 1]
if current_patch_index > 0:
prev_patch = all_patches[current_patch_index - 1]
context = {
'series': patch.series(),
'seriesrevisions': group(patch.all_revisions(), lambda r: r.series),
'patch': patch,
'current_revision': current_revision,
'prev_patch': prev_patch,
'next_patch': next_patch,
'patch_count': patch_count,
'current_patch_number': current_patch_number,
'patchform': form,
'createbundleform': createbundleform,
'project': patch.project,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment