[Notice] Announcing the End of Demo Server [Read me]
issue: Display label changing history at issue timeline
See: Yona Github issue #355
@a56074b207bb53f7a2fe77aa0593cc4eadee0f0d
--- app/assets/stylesheets/less/_common.less
+++ app/assets/stylesheets/less/_common.less
... | ... | @@ -304,3 +304,5 @@ |
304 | 304 |
.fixed-height-my-issues-list { |
305 | 305 |
line-height: 36px; |
306 | 306 |
} |
307 |
+ |
|
308 |
+.dimgray { color:dimgray; }(No newline at end of file) |
--- app/assets/stylesheets/less/_page.less
+++ app/assets/stylesheets/less/_page.less
... | ... | @@ -3074,6 +3074,14 @@ |
3074 | 3074 |
background-color: #FFCCBC; |
3075 | 3075 |
color: #F4511E; |
3076 | 3076 |
} |
3077 |
+ &.label-added { |
|
3078 |
+ background-color: #B2EBF2; |
|
3079 |
+ color: #0097A7; |
|
3080 |
+ } |
|
3081 |
+ &.label-deleted { |
|
3082 |
+ background-color: #FFCCBC; |
|
3083 |
+ color: #F4511E; |
|
3084 |
+ } |
|
3077 | 3085 |
} |
3078 | 3086 |
|
3079 | 3087 |
em { font-size:12px; color:#7F8C8D; margin-right:5px;} |
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
... | ... | @@ -1,7 +1,7 @@ |
1 | 1 |
/** |
2 | 2 |
* Yona, 21st Century Project Hosting SW |
3 | 3 |
* <p> |
4 |
- * Copyright Yona & Yobi Authors & NAVER Corp. |
|
4 |
+ * Copyright Yona & Yobi Authors & NAVER Corp. & NAVER LABS Corp. |
|
5 | 5 |
* https://yona.io |
6 | 6 |
**/ |
7 | 7 |
package controllers; |
... | ... | @@ -424,17 +424,35 @@ |
424 | 424 |
|
425 | 425 |
private static void updateLabelIfChanged(List<Long> attachingLabelIds, List<Long> detachingLabelIds, |
426 | 426 |
Issue issue) { |
427 |
+ boolean isLabelChanged = false; |
|
428 |
+ StringBuilder addedLabels = new StringBuilder(); |
|
429 |
+ StringBuilder deletedLabels = new StringBuilder(); |
|
430 |
+ |
|
427 | 431 |
if (attachingLabelIds != null) { |
428 | 432 |
for (Long labelId : attachingLabelIds) { |
429 |
- issue.labels.add(IssueLabel.finder.byId(labelId)); |
|
433 |
+ IssueLabel label = IssueLabel.finder.byId(labelId); |
|
434 |
+ issue.labels.add(label); |
|
435 |
+ isLabelChanged = true; |
|
436 |
+ addedLabels.append(label.category.name).append(" - ").append(label.name); |
|
430 | 437 |
} |
431 | 438 |
} |
432 | 439 |
|
433 | 440 |
if (detachingLabelIds != null) { |
434 | 441 |
for (Long labelId : detachingLabelIds) { |
435 |
- issue.labels.remove(IssueLabel.finder.byId(labelId)); |
|
442 |
+ IssueLabel label = IssueLabel.finder.byId(labelId); |
|
443 |
+ issue.labels.remove(label); |
|
444 |
+ isLabelChanged = true; |
|
445 |
+ deletedLabels.append(label.category.name).append(" - ").append(label.name); |
|
436 | 446 |
} |
437 | 447 |
} |
448 |
+ |
|
449 |
+ if(isLabelChanged) { |
|
450 |
+ NotificationEvent notiEvent = NotificationEvent.afterIssueLabelChanged( |
|
451 |
+ addedLabels.toString(), |
|
452 |
+ deletedLabels.toString(), |
|
453 |
+ issue); |
|
454 |
+ IssueEvent.addFromNotificationEventWithoutSkipEvent(notiEvent, issue, UserApp.currentUser().loginId); |
|
455 |
+ } |
|
438 | 456 |
} |
439 | 457 |
|
440 | 458 |
private static void updateMilestoneIfChanged(Milestone milestone, Issue issue) { |
--- app/models/NotificationEvent.java
+++ app/models/NotificationEvent.java
... | ... | @@ -201,6 +201,12 @@ |
201 | 201 |
} else if (StringUtils.isNotBlank(oldValue)) { |
202 | 202 |
return Messages.get(lang, "notification.issue.sharer.deleted"); |
203 | 203 |
} |
204 |
+ case ISSUE_LABEL_CHANGED: |
|
205 |
+ if (StringUtils.isNotBlank(newValue)) { |
|
206 |
+ return Messages.get(lang, "notification.issue.label.added", User.findByLoginId(newValue).getDisplayName()); |
|
207 |
+ } else if (StringUtils.isNotBlank(oldValue)) { |
|
208 |
+ return Messages.get(lang, "notification.issue.label.deleted"); |
|
209 |
+ } |
|
204 | 210 |
default: |
205 | 211 |
play.Logger.error("Unknown event message: " + this); |
206 | 212 |
return null; |
... | ... | @@ -893,6 +899,18 @@ |
893 | 899 |
return receivers; |
894 | 900 |
} |
895 | 901 |
|
902 |
+ public static NotificationEvent afterIssueLabelChanged(String addedLabels, String deletedLabels, Issue issue) { |
|
903 |
+ NotificationEvent notiEvent = createFromCurrentUser(issue); |
|
904 |
+ notiEvent.title = formatReplyTitle(issue); |
|
905 |
+ notiEvent.receivers = null; // no receivers |
|
906 |
+ notiEvent.eventType = ISSUE_LABEL_CHANGED; |
|
907 |
+ notiEvent.oldValue = deletedLabels; |
|
908 |
+ notiEvent.newValue = addedLabels; |
|
909 |
+ |
|
910 |
+ NotificationEvent.addWithoutSkipEvent(notiEvent); |
|
911 |
+ return notiEvent; |
|
912 |
+ } |
|
913 |
+ |
|
896 | 914 |
private static Set<User> getReceiversForIssueBodyChanged(String oldBody, Issue issue) { |
897 | 915 |
Set<User> receivers = issue.getWatchers(); |
898 | 916 |
receivers.addAll(getNewMentionedUsers(oldBody, issue.body)); |
--- app/models/enumeration/EventType.java
+++ app/models/enumeration/EventType.java
... | ... | @@ -35,7 +35,8 @@ |
35 | 35 |
ORGANIZATION_MEMBER_ENROLL_REQUEST("notification.organization.type.member.enroll",19), |
36 | 36 |
COMMENT_UPDATED("notification.type.comment.updated", 20), |
37 | 37 |
ISSUE_MOVED("notification.type.issue.is.moved", 21), |
38 |
- ISSUE_SHARER_CHANGED("notification.type.issue.sharer.changed", 22); |
|
38 |
+ ISSUE_SHARER_CHANGED("notification.type.issue.sharer.changed", 22), |
|
39 |
+ ISSUE_LABEL_CHANGED("notification.type.issue.label.changed", 23); |
|
39 | 40 |
|
40 | 41 |
private String descr; |
41 | 42 |
|
--- app/views/issue/partial_comments.scala.html
+++ app/views/issue/partial_comments.scala.html
... | ... | @@ -32,6 +32,23 @@ |
32 | 32 |
} |
33 | 33 |
} |
34 | 34 |
|
35 |
+@issueLabelBox(categoryAndName: String, project:Project ) = @{ |
|
36 |
+ val splitedCategoryAndName = categoryAndName.split(" - ") |
|
37 |
+ if(splitedCategoryAndName.length != 2) { |
|
38 |
+ categoryAndName |
|
39 |
+ } else { |
|
40 |
+ var categoryName = splitedCategoryAndName(0).trim |
|
41 |
+ var labelName = splitedCategoryAndName(1).trim |
|
42 |
+ val issueLabel = IssueLabel.findByName(labelName, categoryName, project) |
|
43 |
+ if( issueLabel != null) { |
|
44 |
+ val labelColor = issueLabel.color |
|
45 |
+ s"<div class='label issue-label' style='background-color: $labelColor'>$labelName</div>" |
|
46 |
+ } else { |
|
47 |
+ labelName |
|
48 |
+ } |
|
49 |
+ } |
|
50 |
+} |
|
51 |
+ |
|
35 | 52 |
@assginedMesssage(newValue: String, user:User) = @{ |
36 | 53 |
val LoginId = user.loginId |
37 | 54 |
newValue match { |
... | ... | @@ -187,6 +204,15 @@ |
187 | 204 |
@Html(Messages("issue.event.sharer.deleted", linkToUser(user.loginId, user.getPureNameOnly), linkToUser(event.oldValue, User.findByLoginId(event.oldValue).getPureNameOnly))) |
188 | 205 |
} |
189 | 206 |
} |
207 |
+ case EventType.ISSUE_LABEL_CHANGED => { |
|
208 |
+ @if(StringUtils.isBlank(event.oldValue) && StringUtils.isNotBlank(event.newValue)){ |
|
209 |
+ <span class="state label-added">@Messages("issue.event.label.added.title")</span> |
|
210 |
+ @Html(Messages("issue.event.label.added", linkToUser(user.loginId, user.getPureNameOnly), issueLabelBox(event.newValue, project))) |
|
211 |
+ } else { |
|
212 |
+ <span class="state label-deleted">@Messages("issue.event.label.deleted.title")</span> |
|
213 |
+ @Html(Messages("issue.event.label.deleted", linkToUser(user.loginId, user.getPureNameOnly), issueLabelBox(event.oldValue, project))) |
|
214 |
+ } |
|
215 |
+ } |
|
190 | 216 |
case _ => { |
191 | 217 |
@event.newValue by @linkToUser(user.loginId, user.getDisplayName) |
192 | 218 |
} |
--- app/views/issue/view.scala.html
+++ app/views/issue/view.scala.html
... | ... | @@ -567,6 +567,13 @@ |
567 | 567 |
} else { |
568 | 568 |
$yobi.notify('@Messages("site.features.error.clipboard")', 1500); |
569 | 569 |
} |
570 |
+ |
|
571 |
+ // timeline label text color adjusting |
|
572 |
+ $(".event > .label").each(function() { |
|
573 |
+ var $this = $(this); |
|
574 |
+ $this.removeClass("dimgray white") |
|
575 |
+ .addClass($yobi.getContrastColor($this.css('background-color'))) |
|
576 |
+ }); |
|
570 | 577 |
}); |
571 | 578 |
</script> |
572 | 579 |
} |
--- conf/messages
+++ conf/messages
... | ... | @@ -279,6 +279,10 @@ |
279 | 279 |
issue.event.assigned = {0} assigned this issue to {1} |
280 | 280 |
issue.event.assignedToMe = {0} assigned this issue to oneself |
281 | 281 |
issue.event.closed = {0} closed this issue |
282 |
+issue.event.label.added = {0} added {1} label |
|
283 |
+issue.event.label.added.title = Added |
|
284 |
+issue.event.label.deleted = {0} removed {1} label |
|
285 |
+issue.event.label.deleted.title = Removed |
|
282 | 286 |
issue.event.moved = {0} moved this issue from {1} |
283 | 287 |
issue.event.moved.title = moved |
284 | 288 |
issue.event.open = {0} reopened this issue |
... | ... | @@ -408,6 +412,8 @@ |
408 | 412 |
notification.help.update.pullrequest = when the status of pull request is changed. |
409 | 413 |
notification.issue.assigned = Issue has been assigned to {0} |
410 | 414 |
notification.issue.closed = Issue has been closed |
415 |
+notification.issue.label.added = Label {0} is added |
|
416 |
+notification.issue.label.deleted = Label {0} is deleted |
|
411 | 417 |
notification.issue.reopened = Issue has been reopened |
412 | 418 |
notification.issue.unassigned = Issue has been unassigned |
413 | 419 |
notification.issue.sharer.added = Issue is shared with {0} |
... | ... | @@ -450,6 +456,7 @@ |
450 | 456 |
notification.type.issue.assignee.changed = Issue assignee changed. |
451 | 457 |
notification.type.issue.body.changed = Issue body changed |
452 | 458 |
notification.type.issue.is.moved = Issue moved |
459 |
+notification.type.issue.label.changed = Issue label changed |
|
453 | 460 |
notification.type.issue.moved = Issue has been moved. From {0} To {1} |
454 | 461 |
notification.type.issue.referred.from.commit = Issue mentioned in commit |
455 | 462 |
notification.type.issue.referred.from.pullrequest = Issue mentioned in pull request |
--- conf/messages.ko-KR
+++ conf/messages.ko-KR
... | ... | @@ -279,6 +279,10 @@ |
279 | 279 |
issue.event.assigned = {0}님이 {1}님을 이 이슈의 담당자로 지정하였습니다. |
280 | 280 |
issue.event.assignedToMe = {0}님이 자신을 이슈의 담당자로 지정하였습니다. |
281 | 281 |
issue.event.closed = {0}님이 이 이슈를 닫았습니다. |
282 |
+issue.event.label.added = {0} 님이 {1} 라벨을 추가했습니다. |
|
283 |
+issue.event.label.added.title = 추가 |
|
284 |
+issue.event.label.deleted = {0} 님이 {1} 라벨을 제거했습니다. |
|
285 |
+issue.event.label.deleted.title = 삭제 |
|
282 | 286 |
issue.event.moved = {0}님이 {1}로부터 이슈를 이동했습니다. |
283 | 287 |
issue.event.moved.title = 이동함 |
284 | 288 |
issue.event.open = {0}님이 이 이슈를 다시 열었습니다. |
... | ... | @@ -408,6 +412,8 @@ |
408 | 412 |
notification.help.update.pullrequest = 보낸 코드의 상태가 변경 될 때 |
409 | 413 |
notification.issue.assigned = {0}에게 이슈 할당됨 |
410 | 414 |
notification.issue.closed = 이슈 닫힘 |
415 |
+notification.issue.label.added = {0} 라벨 추가되었습니다 |
|
416 |
+notification.issue.label.deleted = {0} 라벨 삭제되었습니다 |
|
411 | 417 |
notification.issue.reopened = 이슈 다시 열림 |
412 | 418 |
notification.issue.sharer.added = {0} 님에게 이슈가 공유되었습니다. |
413 | 419 |
notification.issue.sharer.deleted = 이슈 공유 상태가 변경되었습니다. |
... | ... | @@ -450,6 +456,7 @@ |
450 | 456 |
notification.type.issue.assignee.changed = 이슈 담당자 변경 |
451 | 457 |
notification.type.issue.body.changed = 이슈 본문 변경 |
452 | 458 |
notification.type.issue.is.moved = 이슈 이동 |
459 |
+notification.type.issue.label.changed = 이슈 라벨 변경 |
|
453 | 460 |
notification.type.issue.moved = 이슈가 {0}에서 {1}로 이동되었습니다 |
454 | 461 |
notification.type.issue.referred.from.commit = 커밋에서의 이슈 언급 |
455 | 462 |
notification.type.issue.referred.from.pullrequest = 코드 주고받기에서의 이슈 언급 |
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?