Skip to content

Commit 2fd7f8d

Browse files
views: add maintainer notes view
Signed-off-by: Victor Accarini <[email protected]>
1 parent 1990045 commit 2fd7f8d

File tree

8 files changed

+353
-78
lines changed

8 files changed

+353
-78
lines changed

htdocs/css/style.css

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,26 @@ table.patch-meta tr th, table.patch-meta tr td {
325325
color: #f7977a;
326326
}
327327

328+
.submission-message.maintainer a {
329+
color: blue;
330+
}
331+
332+
.submission-message.maintainer div.text-warning {
333+
color: yellow;
334+
}
335+
336+
.submission-message.maintainer div.text-success {
337+
color: lightgreen;
338+
}
339+
.submission-message.maintainer .meta {
340+
background-color: red;
341+
color: white;
342+
}
343+
344+
.submission-message.maintainer .content {
345+
background-color: #ff7d7d;
346+
}
347+
328348
.submission-message .meta {
329349
display: flex;
330350
align-items: center;
@@ -449,6 +469,16 @@ div.patch-form {
449469
align-items: center;
450470
}
451471

472+
#maintainer-note-form .form-actions {
473+
display: flex;
474+
justify-content: flex-start; /* Align buttons to the left */
475+
gap: 10px; /* Add space between buttons */
476+
}
477+
#maintainer-note-form div:first-of-type {
478+
display: flex;
479+
flex-direction: column;
480+
}
481+
452482
select[class^=change-property-], .archive-patch-select, .add-bundle {
453483
padding: 4px;
454484
margin-right: 8px;
@@ -476,7 +506,7 @@ select[class^=change-property-], .archive-patch-select, .add-bundle {
476506
padding: 4px;
477507
}
478508

479-
#patch-form-bundle, #add-to-bundle, #remove-bundle {
509+
#patch-form-bundle, #add-to-bundle, #remove-bundle, #note-button {
480510
margin-left: 16px;
481511
}
482512

patchwork/forms.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.template.backends import django as django_template_backend
1313

1414
from patchwork.models import Bundle
15+
from patchwork.models import PatchComment
1516
from patchwork.models import Patch
1617
from patchwork.models import State
1718
from patchwork.models import UserProfile
@@ -106,6 +107,19 @@ class DeleteBundleForm(forms.Form):
106107
bundle_id = forms.IntegerField(widget=forms.HiddenInput)
107108

108109

110+
class PatchMaintainerNoteForm(forms.ModelForm):
111+
name = 'patchnoteform'
112+
form_name = forms.CharField(initial=name, widget=forms.HiddenInput)
113+
content = forms.CharField(label='Content', widget=forms.Textarea)
114+
addressed = forms.BooleanField(
115+
label='Addressed', widget=forms.CheckboxInput, required=False
116+
)
117+
118+
class Meta:
119+
model = PatchComment
120+
fields = ['content', 'addressed']
121+
122+
109123
class EmailForm(forms.Form):
110124
email = forms.EmailField(max_length=200)
111125

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{% load person %}
2+
{% load utils %}
3+
{% load syntax %}
4+
5+
{% is_editable submission user as editable %}
6+
{% is_editable item user as comment_is_editable %}
7+
<a name="{{ item.id }}"></a>
8+
<div class="submission-message {{ item.msgid|yesno:",maintainer" }}">
9+
<div class="meta">
10+
{{ item.submitter|personify:project }}
11+
<span class="message-date">{{ item.date }} UTC |
12+
{% if not item.msgid %}
13+
<a href="{% url 'comment-redirect' comment_id=item.id %}"># Maintainer Note</a>
14+
{% else %}
15+
<a href="{% url 'comment-redirect' comment_id=item.id %}">#{{ forloop.counter}}</a>
16+
{% endif %}
17+
</span>
18+
{% if item.addressed == None %}
19+
<div class="comment-status-bar-action-required" data-comment-id={{item.id}}>
20+
{% else %}
21+
<div class="comment-status-bar-action-required hidden" data-comment-id={{item.id}}>
22+
{% endif %}
23+
{% if editable or comment_is_editable %}
24+
<button class="comment-action-unaddressed text-warning" value="false">
25+
<span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
26+
Mark Action Required
27+
</button>
28+
{% endif %}
29+
</div>
30+
{% if item.addressed == True %}
31+
<div class="comment-status-bar-addressed" data-comment-id={{item.id}}>
32+
{% else %}
33+
<div class="comment-status-bar-addressed hidden" data-comment-id={{item.id}}>
34+
{% endif %}
35+
<div class="comment-status-label text-success mx-3">
36+
<span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
37+
Addressed
38+
</div>
39+
{% if editable or comment_is_editable %}
40+
<button class="comment-action-unaddressed text-warning" value="false">
41+
<span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
42+
Mark Unaddressed
43+
</button>
44+
{% endif %}
45+
</div>
46+
{% if item.addressed == False %}
47+
<div class="comment-status-bar-unaddressed" data-comment-id={{item.id}}>
48+
{% else %}
49+
<div class="comment-status-bar-unaddressed hidden" data-comment-id={{item.id}}>
50+
{% endif %}
51+
<div class="comment-status-label text-warning mx-3">
52+
<span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
53+
Unaddressed
54+
</div>
55+
{% if editable or comment_is_editable %}
56+
<button class="comment-action-addressed text-success" value="true">
57+
<span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
58+
Mark Addressed
59+
</button>
60+
{% endif %}
61+
</div>
62+
</div>
63+
<pre class="content">
64+
{{ item|commentsyntax }}
65+
</pre>
66+
</div>

patchwork/templates/patchwork/partials/patch-forms.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@
4444
</button>
4545
</div>
4646
{% endif %}
47+
{% if is_maintainer %}
48+
<div id="note-button">
49+
{% if not note %}
50+
<button class="patch-form-submit btn btn-primary" name="action" value="note:add">
51+
Add Note
52+
</button>
53+
{% else %}
54+
<button class="patch-form-submit btn btn-primary" name="action" value="note:edit">
55+
Edit Note
56+
</button>
57+
<button class="patch-form-submit btn btn-primary" name="action" value="note:remove">
58+
Remove Note
59+
</button>
60+
{% endif %}
61+
</div>
62+
{% endif %}
4763
</div>
4864
{% endif %}
4965
</div>

patchwork/templates/patchwork/submission.html

Lines changed: 25 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,25 @@ <h1>{{ submission.name }}</h1>
136136
{% csrf_token %}
137137
{% include "patchwork/partials/patch-forms.html" %}
138138
</form>
139+
{% if create_note_form %}
140+
<form id="maintainer-note-form" method="post">
141+
<h2>New Note</h2>
142+
{% csrf_token %}
143+
{{ create_note_form.as_div }}
144+
<input type="submit" class="patch-form-submit btn btn-primary" value="Add">
145+
</form>
146+
{% endif %}
147+
{% if edit_note_form %}
148+
<form id="maintainer-note-form" method="post">
149+
<h2>Edit Note</h2>
150+
{% csrf_token %}
151+
{{ edit_note_form.as_div }}
152+
<div class="form-actions">
153+
<input type="submit" class="patch-form-submit btn btn-primary" value="Save">
154+
<button type="submit" name="cancel" value="Cancel">Cancel</button>
155+
</div>
156+
</form>
157+
{% endif %}
139158

140159
{% if submission.pull_url %}
141160
<h2>Pull-request</h2>
@@ -187,68 +206,15 @@ <h2>Message</h2>
187206
</pre>
188207
</div>
189208

190-
{% for item in comments %}
191-
{% if forloop.first %}
209+
{% if note or comments %}
192210
<h2>Comments</h2>
211+
{% if note %}
212+
{% include "patchwork/partials/comment.html" with item=note %}
193213
{% endif %}
194-
{% is_editable item user as comment_is_editable %}
195-
<a name="{{ item.id }}"></a>
196-
<div class="submission-message">
197-
<div class="meta">
198-
{{ item.submitter|personify:project }}
199-
<span class="message-date">{{ item.date }} UTC |
200-
<a href="{% url 'comment-redirect' comment_id=item.id %}">#{{ forloop.counter }}</a>
201-
</span>
202-
{% if item.addressed == None %}
203-
<div class="comment-status-bar-action-required" data-comment-id={{item.id}}>
204-
{% else %}
205-
<div class="comment-status-bar-action-required hidden" data-comment-id={{item.id}}>
206-
{% endif %}
207-
{% if editable or comment_is_editable %}
208-
<button class="comment-action-unaddressed text-warning" value="false">
209-
<span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
210-
Mark Action Required
211-
</button>
212-
{% endif %}
213-
</div>
214-
{% if item.addressed == True %}
215-
<div class="comment-status-bar-addressed" data-comment-id={{item.id}}>
216-
{% else %}
217-
<div class="comment-status-bar-addressed hidden" data-comment-id={{item.id}}>
218-
{% endif %}
219-
<div class="comment-status-label text-success mx-3">
220-
<span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
221-
Addressed
222-
</div>
223-
{% if editable or comment_is_editable %}
224-
<button class="comment-action-unaddressed text-warning" value="false">
225-
<span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
226-
Mark Unaddressed
227-
</button>
228-
{% endif %}
229-
</div>
230-
{% if item.addressed == False %}
231-
<div class="comment-status-bar-unaddressed" data-comment-id={{item.id}}>
232-
{% else %}
233-
<div class="comment-status-bar-unaddressed hidden" data-comment-id={{item.id}}>
234-
{% endif %}
235-
<div class="comment-status-label text-warning mx-3">
236-
<span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
237-
Unaddressed
238-
</div>
239-
{% if editable or comment_is_editable %}
240-
<button class="comment-action-addressed text-success" value="true">
241-
<span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
242-
Mark Addressed
243-
</button>
244-
{% endif %}
245-
</div>
246-
</div>
247-
<pre class="content">
248-
{{ item|commentsyntax }}
249-
</pre>
250-
</div>
214+
{% for item in comments %}
215+
{% include "patchwork/partials/comment.html" %}
251216
{% endfor %}
217+
{% endif %}
252218

253219
{% if submission.diff %}
254220
<div>

patchwork/tests/views/test_patch.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,53 @@ def test_comment_redirect(self):
247247
response = self.client.get(requested_url)
248248
self.assertRedirects(response, redirect_url)
249249

250+
def test_show_maintainer_note(self):
251+
patch = create_patch()
252+
note = create_patch_comment(patch=patch, msgid='')
253+
requested_url = reverse(
254+
'patch-detail',
255+
kwargs={
256+
'project_id': patch.project.linkname,
257+
'msgid': patch.encoded_msgid,
258+
},
259+
)
260+
response = self.client.get(requested_url)
261+
self.assertIn('# Maintainer Note'.encode('utf-8'), response.content)
262+
self.assertIn(note.content.encode('utf-8'), response.content)
263+
264+
def test_maintainer_notes_controls(self):
265+
project = create_project()
266+
user = create_maintainer(project)
267+
patch = create_patch(project=project)
268+
requested_url = reverse(
269+
'patch-detail',
270+
kwargs={
271+
'project_id': patch.project.linkname,
272+
'msgid': patch.encoded_msgid,
273+
},
274+
)
275+
276+
# No authentication
277+
response = self.client.get(requested_url)
278+
self.assertNotIn('Add Note'.encode('utf-8'), response.content)
279+
self.assertNotIn('Edit Note'.encode('utf-8'), response.content)
280+
self.assertNotIn('Remove Note'.encode('utf-8'), response.content)
281+
282+
# Auth with no note
283+
self.client.login(username=user.username, password=user.username)
284+
response = self.client.get(requested_url)
285+
self.assertIn('Add Note'.encode('utf-8'), response.content)
286+
self.assertNotIn('Edit Note'.encode('utf-8'), response.content)
287+
self.assertNotIn('Remove Note'.encode('utf-8'), response.content)
288+
289+
# Auth with note
290+
note = create_patch_comment(patch=patch, msgid='')
291+
response = self.client.get(requested_url)
292+
self.assertNotIn('Add Note'.encode('utf-8'), response.content)
293+
self.assertIn('Edit Note'.encode('utf-8'), response.content)
294+
self.assertIn('Remove Note'.encode('utf-8'), response.content)
295+
self.assertIn(note.content.encode('utf-8'), response.content)
296+
250297
def test_old_detail_url(self):
251298
patch = create_patch()
252299

0 commit comments

Comments
 (0)