[Notice] Announcing the End of Demo Server [Read me]
search: Support issue search with 'commented by me' option
@5a4aa6fce13af0f70348027b604876cbd0646250
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
... | ... | @@ -108,7 +108,8 @@ |
108 | 108 |
} |
109 | 109 |
|
110 | 110 |
private static boolean hasNotConditions(models.support.SearchCondition searchCondition) { |
111 |
- return searchCondition.assigneeId == null && searchCondition.authorId == null && searchCondition.mentionId == null; |
|
111 |
+ return searchCondition.assigneeId == null && searchCondition.authorId == null && searchCondition.mentionId == null |
|
112 |
+ && searchCondition.commenterId == null; |
|
112 | 113 |
} |
113 | 114 |
|
114 | 115 |
@Transactional |
--- app/models/support/SearchCondition.java
+++ app/models/support/SearchCondition.java
... | ... | @@ -53,6 +53,8 @@ |
53 | 53 |
public Organization organization; |
54 | 54 |
public List<String> projectNames; |
55 | 55 |
|
56 |
+ public Long commenterId; |
|
57 |
+ |
|
56 | 58 |
@Formats.DateTime(pattern = "yyyy-MM-dd") |
57 | 59 |
public Date dueDate; |
58 | 60 |
|
... | ... | @@ -72,6 +74,7 @@ |
72 | 74 |
one.labelIds = new HashSet<>(this.labelIds); |
73 | 75 |
one.authorId = this.authorId; |
74 | 76 |
one.assigneeId = this.assigneeId; |
77 |
+ one.commenterId = this.commenterId; |
|
75 | 78 |
one.mentionId = this.mentionId; |
76 | 79 |
one.dueDate = this.dueDate; |
77 | 80 |
one.projectNames = this.projectNames; |
... | ... | @@ -135,6 +138,11 @@ |
135 | 138 |
|
136 | 139 |
public SearchCondition setAssigneeId(Long assigneeId) { |
137 | 140 |
this.assigneeId = assigneeId; |
141 |
+ return this; |
|
142 |
+ } |
|
143 |
+ |
|
144 |
+ public SearchCondition setCommenterId(Long commenterId) { |
|
145 |
+ this.commenterId = commenterId; |
|
138 | 146 |
return this; |
139 | 147 |
} |
140 | 148 |
|
... | ... | @@ -220,6 +228,23 @@ |
220 | 228 |
} |
221 | 229 |
} |
222 | 230 |
|
231 |
+ private void setCommenterIfExist(ExpressionList<Issue> el, Project project) { |
|
232 |
+ // TODO: access control |
|
233 |
+ if (commenterId != null) { |
|
234 |
+ User commenter = User.find.byId(commenterId); |
|
235 |
+ if(!commenter.isAnonymous()) { |
|
236 |
+ List<Long> ids = getCommentedIssueIds(commenter, project); |
|
237 |
+ |
|
238 |
+ if (ids.isEmpty()) { |
|
239 |
+ // No need to progress because the query matches nothing. |
|
240 |
+ el.idEq(-1); |
|
241 |
+ } else { |
|
242 |
+ el.idIn(ids); |
|
243 |
+ } |
|
244 |
+ } |
|
245 |
+ } |
|
246 |
+ } |
|
247 |
+ |
|
223 | 248 |
private void setAssigneeIfExists(ExpressionList<Issue> el) { |
224 | 249 |
if (assigneeId != null) { |
225 | 250 |
if (assigneeId.equals(User.anonymous.id)) { |
... | ... | @@ -252,6 +277,7 @@ |
252 | 277 |
|
253 | 278 |
setAssigneeIfExists(el); |
254 | 279 |
setAuthorIfExist(el); |
280 |
+ setCommenterIfExist(el, null); |
|
255 | 281 |
setMentionedIssuesIfExist(el); |
256 | 282 |
setFilteredStringIfExist(el); |
257 | 283 |
|
... | ... | @@ -292,6 +318,33 @@ |
292 | 318 |
} |
293 | 319 |
} |
294 | 320 |
} |
321 |
+ } |
|
322 |
+ |
|
323 |
+ private List<Long> getCommentedIssueIds(User commenter, Project project) { |
|
324 |
+ Set<Long> issueIds = new HashSet<>(); |
|
325 |
+ |
|
326 |
+ for (Comment comment : IssueComment.find.where() |
|
327 |
+ .eq("authorId", commenter.id) |
|
328 |
+ .findList()) { |
|
329 |
+ |
|
330 |
+ switch (comment.asResource().getType()) { |
|
331 |
+ case ISSUE_COMMENT: |
|
332 |
+ if(project == null) { |
|
333 |
+ issueIds.add(comment.getParent().id); |
|
334 |
+ break; |
|
335 |
+ } else { |
|
336 |
+ if(comment.getParent().project.id.equals(project.id)){ |
|
337 |
+ issueIds.add(comment.getParent().id); |
|
338 |
+ } |
|
339 |
+ } |
|
340 |
+ break; |
|
341 |
+ default: |
|
342 |
+ play.Logger.warn("'" + comment.asResource().getType() + "' is not supported."); |
|
343 |
+ break; |
|
344 |
+ } |
|
345 |
+ } |
|
346 |
+ |
|
347 |
+ return new ArrayList<>(issueIds); |
|
295 | 348 |
} |
296 | 349 |
|
297 | 350 |
private List<Long> getMentioningIssueIds(User mentionUser) { |
... | ... | @@ -368,6 +421,8 @@ |
368 | 421 |
} |
369 | 422 |
} |
370 | 423 |
|
424 |
+ setCommenterIfExist(el, project); |
|
425 |
+ |
|
371 | 426 |
if (milestoneId != null) { |
372 | 427 |
if (milestoneId.equals(Milestone.NULL_MILESTONE_ID)) { |
373 | 428 |
el.isNull("milestone"); |
--- app/views/issue/my_partial_list_quicksearch.scala.html
+++ app/views/issue/my_partial_list_quicksearch.scala.html
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 |
<a pjax-filter href="#" |
27 | 27 |
data-author-id="" |
28 | 28 |
data-assignee-id="@UserApp.currentUser.id" |
29 |
+ data-commenter-id="" |
|
29 | 30 |
data-milestone-id="@param.milestoneId" |
30 | 31 |
data-mention-id=""> |
31 | 32 |
@Messages("issue.list.assignedToMe") |
... | ... | @@ -35,15 +36,27 @@ |
35 | 36 |
<a pjax-filter href="#" |
36 | 37 |
data-author-id="@UserApp.currentUser.id" |
37 | 38 |
data-assignee-id="" |
39 |
+ data-commenter-id="" |
|
38 | 40 |
data-milestone-id="@param.milestoneId" |
39 | 41 |
data-mention-id=""> |
40 | 42 |
@Messages("issue.list.authoredByMe") |
43 |
+ </a> |
|
44 |
+ </li> |
|
45 |
+ <li @if(param.commenterId == UserApp.currentUser().id){ class="active"}> |
|
46 |
+ <a pjax-filter href="#" |
|
47 |
+ data-author-id="" |
|
48 |
+ data-assignee-id="" |
|
49 |
+ data-commenter-id="@UserApp.currentUser.id" |
|
50 |
+ data-milestone-id="@param.milestoneId" |
|
51 |
+ data-mention-id=""> |
|
52 |
+ @Messages("issue.list.commentedByMe") |
|
41 | 53 |
</a> |
42 | 54 |
</li> |
43 | 55 |
<li @if(param.mentionId == UserApp.currentUser().id){ class="active"}> |
44 | 56 |
<a pjax-filter href="#" |
45 | 57 |
data-author-id="" |
46 | 58 |
data-assignee-id="" |
59 |
+ data-commenter-id="" |
|
47 | 60 |
data-milestone-id="@param.milestoneId" |
48 | 61 |
data-mention-id="@UserApp.currentUser.id"> |
49 | 62 |
@Messages("issue.list.mentionedOfMe") |
--- app/views/issue/my_partial_search.scala.html
+++ app/views/issue/my_partial_search.scala.html
... | ... | @@ -45,6 +45,7 @@ |
45 | 45 |
<input type="hidden" name="orderDir" value="@param.orderDir"> |
46 | 46 |
<input type="hidden" name="state" value="@param.state"> |
47 | 47 |
<input type="hidden" name="authorId" value="@param.authorId" data-search="authorId"> |
48 |
+ <input type="hidden" name="commenterId" value="@param.commenterId" data-search="commenterId"> |
|
48 | 49 |
<input type="hidden" name="assigneeId" value="@param.assigneeId" data-search="assigneeId"> |
49 | 50 |
<input type="hidden" name="mentionId" value="@param.mentionId" data-search="mentionId"> |
50 | 51 |
<div class="search"> |
--- app/views/issue/partial_list_quicksearch.scala.html
+++ app/views/issue/partial_list_quicksearch.scala.html
... | ... | @@ -20,38 +20,56 @@ |
20 | 20 |
**@ |
21 | 21 |
@(param:models.support.SearchCondition, project:Project) |
22 | 22 |
|
23 |
-@paramForEveryone = @{ param.clone().setState(param.state).setAssigneeId(null).setAuthorId(null) } |
|
24 |
-@paramForIssuesAssignedToMe = @{ param.clone().setState(param.state).setAssigneeId(UserApp.currentUser().id).setAuthorId(null) } |
|
25 |
-@paramForIssuesAuthoredByMe = @{ param.clone().setState(param.state).setAssigneeId(null).setAuthorId(UserApp.currentUser().id) } |
|
23 |
+@paramForEveryone = @{ param.clone().setState(param.state).setAssigneeId(null).setAuthorId(null).setCommenterId(null) } |
|
24 |
+@paramForIssuesAssignedToMe = @{ param.clone().setState(param.state).setAssigneeId(UserApp.currentUser().id).setAuthorId(null).setCommenterId(null) } |
|
25 |
+@paramForIssuesAuthoredByMe = @{ param.clone().setState(param.state).setAssigneeId(null).setAuthorId(UserApp.currentUser().id).setCommenterId(null) } |
|
26 |
+@paramForIssuesCommentedByMe = @{ param.clone().setState(param.state).setAssigneeId(null).setAuthorId(null).setCommenterId(UserApp.currentUser().id) } |
|
26 | 27 |
|
27 | 28 |
<ul class="lst-stacked unstyled"> |
28 |
- <li @if(param.assigneeId == null && param.authorId == null){class="active"}> |
|
29 |
+ <li @if(param.assigneeId == null && param.authorId == null && param.commenterId == null){class="active"}> |
|
29 | 30 |
<a pjax-filter href="#" |
30 |
- data-assignee-id="" |
|
31 |
- data-author-id="" |
|
32 |
- data-milestone-id="@param.milestoneId"> |
|
33 |
- @Messages("issue.list.all") |
|
31 |
+ data-assignee-id="" |
|
32 |
+ data-author-id="" |
|
33 |
+ data-commenter-id="" |
|
34 |
+ data-milestone-id="@param.milestoneId"> |
|
35 |
+ @if(param.state.equals("closed")){ |
|
36 |
+ @Messages("issue.list.all.closed") |
|
37 |
+ } else { |
|
38 |
+ @Messages("issue.list.all.open") |
|
39 |
+ } |
|
34 | 40 |
<span class="num-badge pull-right">@Issue.countIssuesBy(project.id, paramForEveryone)</span> |
35 | 41 |
</a> |
36 | 42 |
</li> |
37 | 43 |
@if(!UserApp.currentUser().isAnonymous){ |
38 | 44 |
<li @if(param.assigneeId == UserApp.currentUser().id){ class="active"}> |
39 | 45 |
<a pjax-filter href="#" |
40 |
- data-assignee-id="@UserApp.currentUser.id" |
|
41 |
- data-author-id="" |
|
42 |
- data-milestone-id="@param.milestoneId"> |
|
46 |
+ data-assignee-id="@UserApp.currentUser.id" |
|
47 |
+ data-author-id="" |
|
48 |
+ data-commenter-id="" |
|
49 |
+ data-milestone-id="@param.milestoneId"> |
|
43 | 50 |
@Messages("issue.list.assignedToMe") |
44 | 51 |
<span class="num-badge pull-right">@Issue.countIssuesBy(project.id, paramForIssuesAssignedToMe)</span> |
45 | 52 |
</a> |
46 | 53 |
</li> |
47 | 54 |
<li @if(param.authorId == UserApp.currentUser().id){ class="active"}> |
48 | 55 |
<a pjax-filter href="#" |
49 |
- data-assignee-id="" |
|
50 |
- data-author-id="@UserApp.currentUser.id" |
|
51 |
- data-milestone-id="@param.milestoneId"> |
|
56 |
+ data-assignee-id="" |
|
57 |
+ data-author-id="@UserApp.currentUser.id" |
|
58 |
+ data-commenter-id="" |
|
59 |
+ data-milestone-id="@param.milestoneId"> |
|
52 | 60 |
@Messages("issue.list.authoredByMe") |
53 | 61 |
<span class="num-badge pull-right">@Issue.countIssuesBy(project.id, paramForIssuesAuthoredByMe)</span> |
54 | 62 |
</a> |
55 | 63 |
</li> |
64 |
+ <li @if(param.commenterId == UserApp.currentUser().id){ class="active"}> |
|
65 |
+ <a pjax-filter href="#" |
|
66 |
+ data-assignee-id="" |
|
67 |
+ data-author-id="" |
|
68 |
+ data-commenter-id="@UserApp.currentUser.id" |
|
69 |
+ data-milestone-id="@param.milestoneId"> |
|
70 |
+ @Messages("issue.list.commentedByMe") |
|
71 |
+ <span class="num-badge pull-right">@Issue.countIssuesBy(project.id, paramForIssuesCommentedByMe)</span> |
|
72 |
+ </a> |
|
73 |
+ </li> |
|
56 | 74 |
} |
57 | 75 |
</ul> |
--- app/views/issue/partial_searchform.scala.html
+++ app/views/issue/partial_searchform.scala.html
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 |
<input type="hidden" name="orderBy" value="@param.orderBy"> |
27 | 27 |
<input type="hidden" name="orderDir" value="@param.orderDir"> |
28 | 28 |
<input type="hidden" name="state" value="@param.state"> |
29 |
+ <input type="hidden" name="commenterId" value="@param.commenterId" data-search="commenterId"> |
|
29 | 30 |
<hr class="hide-in-mobile"> |
30 | 31 |
<div class="search"> |
31 | 32 |
<div class="search-bar"> |
--- conf/messages
+++ conf/messages
... | ... | @@ -263,8 +263,11 @@ |
263 | 263 |
issue.is.empty = No issue found |
264 | 264 |
issue.label = Issue Label |
265 | 265 |
issue.list.all = All issues |
266 |
+issue.list.all.closed = All closed issues |
|
267 |
+issue.list.all.open = All open issues |
|
266 | 268 |
issue.list.assignedToMe = Assigned to me |
267 | 269 |
issue.list.authoredByMe = Created by me |
270 |
+issue.list.commentedByMe = Commented by me |
|
268 | 271 |
issue.list.mentionedOfMe = Mentioned of me |
269 | 272 |
issue.menu.new = New issue |
270 | 273 |
issue.myIssue = My issues |
--- conf/messages.ko-KR
+++ conf/messages.ko-KR
... | ... | @@ -263,8 +263,11 @@ |
263 | 263 |
issue.is.empty = 등록된 이슈가 없습니다. |
264 | 264 |
issue.label = 이슈 라벨 |
265 | 265 |
issue.list.all = 전체 이슈 |
266 |
+issue.list.all.closed = 전체 닫힌 이슈 |
|
267 |
+issue.list.all.open = 전체 열린 이슈 |
|
266 | 268 |
issue.list.assignedToMe = 나에게 할당된 이슈 |
267 | 269 |
issue.list.authoredByMe = 내가 작성한 이슈 |
270 |
+issue.list.commentedByMe = 내가 코멘트를 남긴 이슈 |
|
268 | 271 |
issue.list.mentionedOfMe = 나를 언급한 이슈 |
269 | 272 |
issue.menu.new = 새 이슈 |
270 | 273 |
issue.myIssue = 내 이슈 |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?