[PATCH 08/11] views: Add patch labels to web UI
Stephen Finucane
stephen at that.guru
Mon Apr 16 08:54:02 AEST 2018
Nothing too complicated here. The forms we have for this need some
serious cleanup/beautification, but that's a problem for another day.
Signed-off-by: Stephen Finucane <stephen at that.guru>
---
patchwork/forms.py | 17 ++++++++++++++++-
patchwork/templates/patchwork/patch-list.html | 8 ++++++++
patchwork/templates/patchwork/submission.html | 7 +++++++
patchwork/templatetags/patch.py | 24 ++++++++++++++++++++++++
patchwork/views/__init__.py | 2 +-
5 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/patchwork/forms.py b/patchwork/forms.py
index e8a4955e..2c425a81 100644
--- a/patchwork/forms.py
+++ b/patchwork/forms.py
@@ -26,6 +26,7 @@ from django.db.utils import ProgrammingError
from patchwork.models import Bundle
from patchwork.models import Patch
+from patchwork.models import Label
from patchwork.models import State
from patchwork.models import UserProfile
@@ -136,10 +137,14 @@ class PatchForm(forms.ModelForm):
super(PatchForm, self).__init__(instance=instance, *args, **kwargs)
self.fields['delegate'] = forms.ModelChoiceField(
queryset=_get_delegate_qs(project, instance), required=False)
+ self.fields['labels'] = forms.ModelMultipleChoiceField(
+ queryset=Label.objects.filter(
+ Q(project=project) | Q(project=None)),
+ required=False)
class Meta:
model = Patch
- fields = ['state', 'archived', 'delegate']
+ fields = ['state', 'archived', 'delegate', 'labels']
class OptionalModelChoiceField(forms.ModelChoiceField):
@@ -192,6 +197,10 @@ class MultiplePatchForm(forms.Form):
super(MultiplePatchForm, self).__init__(*args, **kwargs)
self.fields['delegate'] = OptionalModelChoiceField(
queryset=_get_delegate_qs(project=project), required=False)
+ self.fields['labels'] = forms.ModelMultipleChoiceField(
+ queryset=Label.objects.filter(
+ Q(project=project) | Q(project=None)),
+ required=False)
def save(self, instance, commit=True):
opts = instance.__class__._meta
@@ -213,6 +222,12 @@ class MultiplePatchForm(forms.Form):
setattr(instance, f.name, data[f.name])
+ for f in opts.many_to_many:
+ if f.name not in data:
+ continue
+
+ setattr(instance, f.name, data[f.name])
+
if commit:
instance.save()
return instance
diff --git a/patchwork/templates/patchwork/patch-list.html b/patchwork/templates/patchwork/patch-list.html
index 71c1ba92..2361170e 100644
--- a/patchwork/templates/patchwork/patch-list.html
+++ b/patchwork/templates/patchwork/patch-list.html
@@ -192,6 +192,7 @@ $(document).ready(function() {
<a href="{% url 'patch-detail' patch_id=patch.id %}">
{{ patch.name|default:"[no subject]"|truncatechars:100 }}
</a>
+ {{ patch|patch_labels }}
</td>
<td>
{% with patch.series.all.0 as series %}
@@ -247,6 +248,13 @@ $(document).ready(function() {
{{ patchform.archived.errors }}
</td>
</tr>
+ <tr>
+ <th>Label:</th>
+ <td>
+ {{ patchform.labels }}
+ {{ patchform.labels.errors }}
+ </td>
+ </tr>
<tr>
<td></td>
<td>
diff --git a/patchwork/templates/patchwork/submission.html b/patchwork/templates/patchwork/submission.html
index e817713f..538d35ee 100644
--- a/patchwork/templates/patchwork/submission.html
+++ b/patchwork/templates/patchwork/submission.html
@@ -152,6 +152,13 @@ function toggle_div(link_id, headers_id)
{{ patchform.archived.errors }}
</td>
</tr>
+ <tr>
+ <th>Labels:</th>
+ <td>
+ {{ patchform.labels }}
+ {{ patchform.labels.errors }}
+ </td>
+ </tr>
<tr>
<td></td>
<td>
diff --git a/patchwork/templatetags/patch.py b/patchwork/templatetags/patch.py
index 4350e092..1dc96f95 100644
--- a/patchwork/templatetags/patch.py
+++ b/patchwork/templatetags/patch.py
@@ -57,6 +57,30 @@ def patch_checks(patch):
' '.join([str(counts[state]) for state in required])))
+ at register.filter(name='patch_labels')
+def patch_labels(patch):
+
+ def text_color(hex_color):
+ """Generate the ideal text color given a background color.
+
+ From https://www.w3.org/TR/AERT/#color-contrast
+ """
+ red, green, blue = [
+ int(hex_color.lstrip('#')[i:i + 2], 16) for i in (0, 2, 4)]
+ brightness = (red * 299 + green * 587 + blue * 114) / 1000
+
+ return '#000' if brightness >= 123 else '#fff'
+
+ output = []
+ for label in patch.labels.all():
+ style = 'background-color: %s; color: %s' % (
+ label.color, text_color(label.color))
+ output.append('<span class="label" style="%s">%s</span>' % (
+ style, label.name))
+
+ return mark_safe(''.join(output))
+
+
@register.filter(name='state_class')
def state_class(state):
return '-'.join(state.split())
diff --git a/patchwork/views/__init__.py b/patchwork/views/__init__.py
index f8d23a38..654cf42f 100644
--- a/patchwork/views/__init__.py
+++ b/patchwork/views/__init__.py
@@ -288,7 +288,7 @@ def generic_list(request, project, view, view_args=None, filter_settings=None,
patches = patches.select_related('state', 'submitter', 'delegate')
# we also need checks and series
- patches = patches.prefetch_related('check_set', 'series')
+ patches = patches.prefetch_related('check_set', 'series', 'labels')
paginator = Paginator(request, patches)
--
2.14.3
More information about the Patchwork
mailing list