[Notice] Announcing the End of Demo Server [Read me]
noti: Polish notification features
- Refactor methods - Change messages - Reduce notification scope of new commit codes
@ff95d5e5ec15dc9091e8a8d3fd1bd238afa50350
--- app/actors/CommitsNotificationActor.java
+++ app/actors/CommitsNotificationActor.java
... | ... | @@ -1,23 +1,10 @@ |
1 | 1 |
/** |
2 |
- * Yobi, Project Hosting SW |
|
3 |
- * |
|
4 |
- * Copyright 2013 NAVER Corp. |
|
5 |
- * http://yobi.io |
|
6 |
- * |
|
7 |
- * @author Keesun Baik |
|
8 |
- * |
|
9 |
- * Licensed under the Apache License, Version 2.0 (the "License"); |
|
10 |
- * you may not use this file except in compliance with the License. |
|
11 |
- * You may obtain a copy of the License at |
|
12 |
- * |
|
13 |
- * http://www.apache.org/licenses/LICENSE-2.0 |
|
14 |
- * |
|
15 |
- * Unless required by applicable law or agreed to in writing, software |
|
16 |
- * distributed under the License is distributed on an "AS IS" BASIS, |
|
17 |
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
18 |
- * See the License for the specific language governing permissions and |
|
19 |
- * limitations under the License. |
|
20 |
- */ |
|
2 |
+ * Yona, 21st Century Project Hosting SW |
|
3 |
+ * <p> |
|
4 |
+ * Copyright Yona & Yobi Authors & NAVER Corp. & NAVER LABS Corp. |
|
5 |
+ * https://yona.io |
|
6 |
+ **/ |
|
7 |
+ |
|
21 | 8 |
package actors; |
22 | 9 |
|
23 | 10 |
import models.*; |
... | ... | @@ -29,8 +16,6 @@ |
29 | 16 |
|
30 | 17 |
/** |
31 | 18 |
* Creates new commit notifications. |
32 |
- * |
|
33 |
- * @author Keesun Baik |
|
34 | 19 |
*/ |
35 | 20 |
public class CommitsNotificationActor extends PostReceiveActor { |
36 | 21 |
|
... | ... | @@ -50,10 +35,7 @@ |
50 | 35 |
title = Messages.get("notification.pushed.commits", project.name, commits.size()); |
51 | 36 |
} |
52 | 37 |
|
53 |
- Set<User> watchers = Watch.findWatchers(project.asResource()); |
|
54 |
- watchers.remove(sender); |
|
55 |
- |
|
56 |
- NotificationEvent.afterNewCommits(commits, refNames, project, sender, title, watchers); |
|
38 |
+ NotificationEvent.afterNewCommits(commits, refNames, project, sender, title); |
|
57 | 39 |
} |
58 | 40 |
|
59 | 41 |
} |
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
... | ... | @@ -900,16 +900,16 @@ |
900 | 900 |
private static Comment saveComment(Project project, Issue issue, IssueComment comment) { |
901 | 901 |
Comment savedComment; |
902 | 902 |
IssueComment existingComment = IssueComment.find.where().eq("id", comment.id).findUnique(); |
903 |
- if (existingComment != null) { |
|
903 |
+ if (existingComment == null) { |
|
904 |
+ comment.projectId = project.id; |
|
905 |
+ savedComment = saveComment(comment, getContainerUpdater(issue, comment)); |
|
906 |
+ NotificationEvent.afterNewComment(savedComment); |
|
907 |
+ } else { |
|
904 | 908 |
existingComment.contents = comment.contents; |
905 | 909 |
savedComment = saveComment(existingComment, getContainerUpdater(issue, comment)); |
906 | 910 |
if(isSelectedToSendNotificationMail() || !existingComment.isAuthoredBy(UserApp.currentUser())){ |
907 | 911 |
NotificationEvent.afterCommentUpdated(savedComment); |
908 | 912 |
} |
909 |
- } else { |
|
910 |
- comment.projectId = project.id; |
|
911 |
- savedComment = saveComment(comment, getContainerUpdater(issue, comment)); |
|
912 |
- NotificationEvent.afterNewComment(savedComment); |
|
913 | 913 |
} |
914 | 914 |
return savedComment; |
915 | 915 |
} |
--- app/controllers/WatchProjectApp.java
+++ app/controllers/WatchProjectApp.java
... | ... | @@ -60,12 +60,12 @@ |
60 | 60 |
UserProjectNotification userProjectNotification = findOne(user, project, notiType); |
61 | 61 |
if(userProjectNotification == null) { // not specified yet |
62 | 62 |
if (isNotifiedByDefault(notiType)) { |
63 |
- watchExplictly(user, project, notiType); |
|
64 |
- } else { |
|
65 | 63 |
unwatchExplictly(user, project, notiType); |
64 |
+ } else { |
|
65 |
+ watchExplictly(user, project, notiType); |
|
66 | 66 |
} |
67 | 67 |
} else { |
68 |
- userProjectNotification.toggle(); |
|
68 |
+ userProjectNotification.toggle(notiType); |
|
69 | 69 |
} |
70 | 70 |
|
71 | 71 |
return ok(); |
--- app/models/NotificationEvent.java
+++ app/models/NotificationEvent.java
... | ... | @@ -39,15 +39,14 @@ |
39 | 39 |
import java.io.IOException; |
40 | 40 |
import java.io.UnsupportedEncodingException; |
41 | 41 |
import java.net.URLEncoder; |
42 |
-import java.util.Date; |
|
43 |
-import java.util.HashSet; |
|
44 |
-import java.util.List; |
|
45 |
-import java.util.Set; |
|
42 |
+import java.util.*; |
|
46 | 43 |
import java.util.concurrent.TimeUnit; |
47 | 44 |
import java.util.regex.Matcher; |
48 | 45 |
import java.util.regex.Pattern; |
49 | 46 |
|
47 |
+import static models.UserProjectNotification.findEventUnwatchersByEventType; |
|
50 | 48 |
import static models.UserProjectNotification.findEventWatchersByEventType; |
49 |
+import static models.Watch.findUnwatchers; |
|
51 | 50 |
import static models.Watch.findWatchers; |
52 | 51 |
import static models.enumeration.EventType.*; |
53 | 52 |
|
... | ... | @@ -733,11 +732,7 @@ |
733 | 732 |
NotificationEvent notiEvent = createFrom(author, comment); |
734 | 733 |
notiEvent.title = formatReplyTitle(post); |
735 | 734 |
notiEvent.eventType = eventType; |
736 |
- Set<User> receivers = getCommentReceivers(comment, author); |
|
737 |
- receivers.addAll(findEventWatchersByEventType(comment.projectId, eventType)); |
|
738 |
- receivers.addAll(getMentionedUsers(comment.contents)); |
|
739 |
- receivers.remove(author); |
|
740 |
- notiEvent.receivers = receivers; |
|
735 |
+ notiEvent.receivers = getMandatoryReceivers(comment, eventType); |
|
741 | 736 |
notiEvent.oldValue = null; |
742 | 737 |
notiEvent.newValue = comment.contents; |
743 | 738 |
notiEvent.resourceType = comment.asResource().getType(); |
... | ... | @@ -776,7 +771,7 @@ |
776 | 771 |
|
777 | 772 |
NotificationEvent notiEvent = createFromCurrentUser(issue); |
778 | 773 |
notiEvent.title = formatReplyTitle(issue); |
779 |
- notiEvent.receivers = getMandatoryReceivers(issue); |
|
774 |
+ notiEvent.receivers = getMandatoryReceivers(issue, EventType.ISSUE_STATE_CHANGED); |
|
780 | 775 |
notiEvent.eventType = ISSUE_STATE_CHANGED; |
781 | 776 |
notiEvent.oldValue = oldState != null ? oldState.state() : null; |
782 | 777 |
notiEvent.newValue = issue.state.state(); |
... | ... | @@ -842,7 +837,7 @@ |
842 | 837 |
} |
843 | 838 |
|
844 | 839 |
private static Set<User> getReceiversWhenAssigneeChanged(User oldAssignee, Issue issue) { |
845 |
- Set<User> receivers = getMandatoryReceivers(issue); |
|
840 |
+ Set<User> receivers = getMandatoryReceivers(issue, ISSUE_ASSIGNEE_CHANGED); |
|
846 | 841 |
|
847 | 842 |
if (oldAssignee != null && !oldAssignee.isAnonymous() |
848 | 843 |
&& !oldAssignee.loginId.equals(UserApp.currentUser().loginId)) { |
... | ... | @@ -953,7 +948,7 @@ |
953 | 948 |
|
954 | 949 |
NotificationEvent notiEvent = createFromCurrentUser(issue); |
955 | 950 |
|
956 |
- Set<User> receivers = getMandatoryReceivers(issue); |
|
951 |
+ Set<User> receivers = getMandatoryReceivers(issue, ISSUE_MILESTONE_CHANGED); |
|
957 | 952 |
|
958 | 953 |
notiEvent.title = formatReplyTitle(issue); |
959 | 954 |
notiEvent.receivers = receivers; |
... | ... | @@ -966,7 +961,7 @@ |
966 | 961 |
return notiEvent; |
967 | 962 |
} |
968 | 963 |
|
969 |
- private static Set<User> getMandatoryReceivers(Issue issue) { |
|
964 |
+ private static Set<User> getMandatoryReceivers(Issue issue, EventType eventType) { |
|
970 | 965 |
Set<User> receivers = findWatchers(issue.asResource()); |
971 | 966 |
receivers.add(issue.getAuthor()); |
972 | 967 |
|
... | ... | @@ -978,22 +973,74 @@ |
978 | 973 |
receivers.add(issue.assignee.user); |
979 | 974 |
} |
980 | 975 |
|
976 |
+ receivers.addAll(findWatchers(issue.asResource())); |
|
977 |
+ receivers.addAll(findEventWatchersByEventType(issue.project.id, eventType)); |
|
978 |
+ |
|
979 |
+ receivers.removeAll(findUnwatchers(issue.asResource())); |
|
980 |
+ receivers.removeAll(findEventUnwatchersByEventType(issue.project.id, eventType)); |
|
981 | 981 |
receivers.remove(UserApp.currentUser()); |
982 | 982 |
|
983 | 983 |
return receivers; |
984 | 984 |
} |
985 | 985 |
|
986 |
- private static Set<User> getMandatoryReceivers(Posting posting) { |
|
986 |
+ private static Set<User> getMandatoryReceivers(Posting posting, EventType eventType) { |
|
987 | 987 |
Set<User> receivers = findWatchers(posting.asResource()); |
988 | 988 |
receivers.add(posting.getAuthor()); |
989 |
+ receivers.addAll(findWatchers(posting.asResource())); |
|
990 |
+ receivers.addAll(findEventWatchersByEventType(posting.project.id, eventType)); |
|
989 | 991 |
|
992 |
+ receivers.removeAll(findUnwatchers(posting.asResource())); |
|
993 |
+ receivers.removeAll(findEventUnwatchersByEventType(posting.project.id, eventType)); |
|
990 | 994 |
receivers.remove(UserApp.currentUser()); |
991 | 995 |
|
992 | 996 |
return receivers; |
997 |
+ } |
|
998 |
+ |
|
999 |
+ private static Set<User> getMandatoryReceivers(Comment comment, EventType eventType) { |
|
1000 |
+ AbstractPosting parent = comment.getParent(); |
|
1001 |
+ Set<User> receivers = findWatchers(parent.asResource()); |
|
1002 |
+ receivers.add(parent.getAuthor()); |
|
1003 |
+ receivers.addAll(findEventWatchersByEventType(comment.projectId, eventType)); |
|
1004 |
+ receivers.addAll(getMentionedUsers(comment.contents)); |
|
1005 |
+ includeAssigneeIfExist(comment, receivers); |
|
1006 |
+ |
|
1007 |
+ receivers.removeAll(findUnwatchers(parent.asResource())); |
|
1008 |
+ receivers.removeAll(findEventUnwatchersByEventType(comment.projectId, eventType)); |
|
1009 |
+ receivers.remove(UserApp.currentUser()); |
|
1010 |
+ |
|
1011 |
+ return receivers; |
|
1012 |
+ } |
|
1013 |
+ |
|
1014 |
+ private static Set<User> getProjectCommitReceivers(Project project, EventType eventType) { |
|
1015 |
+ Set<User> receivers = findMembersOnlyFromWatchers(project); |
|
1016 |
+ receivers.removeAll(findUnwatchers(project.asResource())); |
|
1017 |
+ receivers.removeAll(findEventUnwatchersByEventType(project.id, eventType)); |
|
1018 |
+ receivers.remove(UserApp.currentUser()); |
|
1019 |
+ |
|
1020 |
+ return receivers; |
|
1021 |
+ } |
|
1022 |
+ |
|
1023 |
+ private static Set<User> findMembersOnlyFromWatchers(Project project) { |
|
1024 |
+ Set<User> receivers = new HashSet<>(); |
|
1025 |
+ Set<User> projectMembers = extractMembers(project); |
|
1026 |
+ for (User watcher : findWatchers(project.asResource())) { |
|
1027 |
+ if (projectMembers.contains(watcher)) { |
|
1028 |
+ receivers.add(watcher); |
|
1029 |
+ } |
|
1030 |
+ } |
|
1031 |
+ return receivers; |
|
1032 |
+ } |
|
1033 |
+ |
|
1034 |
+ private static Set<User> extractMembers(Project project) { |
|
1035 |
+ Set<User> projectMembers = new HashSet<>(); |
|
1036 |
+ for (ProjectUser projectUser : project.members()) { |
|
1037 |
+ projectMembers.add(projectUser.user); |
|
1038 |
+ } |
|
1039 |
+ return projectMembers; |
|
993 | 1040 |
} |
994 | 1041 |
|
995 | 1042 |
private static Set<User> getReceiversForIssueBodyChanged(String oldBody, Issue issue) { |
996 |
- Set<User> receivers = getMandatoryReceivers(issue); |
|
1043 |
+ Set<User> receivers = getMandatoryReceivers(issue, ISSUE_BODY_CHANGED); |
|
997 | 1044 |
receivers.addAll(getNewMentionedUsers(oldBody, issue.body)); |
998 | 1045 |
receivers.remove(UserApp.currentUser()); |
999 | 1046 |
return receivers; |
... | ... | @@ -1020,7 +1067,7 @@ |
1020 | 1067 |
public static NotificationEvent forUpdatePosting(String oldValue, Posting post, User author) { |
1021 | 1068 |
NotificationEvent notiEvent = createFrom(author, post); |
1022 | 1069 |
notiEvent.title = formatNewTitle(post); |
1023 |
- notiEvent.receivers = getMandatoryReceivers(post); |
|
1070 |
+ notiEvent.receivers = getMandatoryReceivers(post, EventType.POSTING_BODY_CHANGED); |
|
1024 | 1071 |
notiEvent.eventType = POSTING_BODY_CHANGED; |
1025 | 1072 |
notiEvent.oldValue = oldValue; |
1026 | 1073 |
notiEvent.newValue = post.body; |
... | ... | @@ -1133,10 +1180,10 @@ |
1133 | 1180 |
NotificationEvent.add(notiEvent); |
1134 | 1181 |
} |
1135 | 1182 |
|
1136 |
- public static void afterNewCommits(List<RevCommit> commits, List<String> refNames, Project project, User sender, String title, Set<User> watchers) { |
|
1183 |
+ public static void afterNewCommits(List<RevCommit> commits, List<String> refNames, Project project, User sender, String title) { |
|
1137 | 1184 |
NotificationEvent notiEvent = createFrom(sender, project); |
1138 | 1185 |
notiEvent.title = title; |
1139 |
- notiEvent.receivers = watchers; |
|
1186 |
+ notiEvent.receivers = getProjectCommitReceivers(project, NEW_COMMIT); |
|
1140 | 1187 |
notiEvent.eventType = NEW_COMMIT; |
1141 | 1188 |
notiEvent.oldValue = null; |
1142 | 1189 |
notiEvent.newValue = newCommitsMessage(commits, refNames, project); |
... | ... | @@ -1230,17 +1277,6 @@ |
1230 | 1277 |
Set<User> receivers = abstractPosting.getWatchers(); |
1231 | 1278 |
receivers.addAll(getMentionedUsers(abstractPosting.body)); |
1232 | 1279 |
receivers.remove(except); |
1233 |
- return receivers; |
|
1234 |
- } |
|
1235 |
- |
|
1236 |
- private static Set<User> getCommentReceivers(Comment comment, User except) { |
|
1237 |
- AbstractPosting parent = comment.getParent(); |
|
1238 |
- |
|
1239 |
- Set<User> receivers = new HashSet<>(findWatchers(parent.asResource())); |
|
1240 |
- receivers.add(comment.getParent().getAuthor()); |
|
1241 |
- includeAssigneeIfExist(comment, receivers); |
|
1242 |
- receivers.remove(except); |
|
1243 |
- |
|
1244 | 1280 |
return receivers; |
1245 | 1281 |
} |
1246 | 1282 |
|
--- app/models/UserProjectNotification.java
+++ app/models/UserProjectNotification.java
... | ... | @@ -13,9 +13,7 @@ |
13 | 13 |
import java.util.*; |
14 | 14 |
|
15 | 15 |
/** |
16 |
- * User this class when someone want to know whether a user is receiving notification alarm from the project or not |
|
17 |
- * |
|
18 |
- * @author Keesun Baik |
|
16 |
+ * Project notification subscribing settings with events which are customized by user |
|
19 | 17 |
*/ |
20 | 18 |
@Entity |
21 | 19 |
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"project_id", "user_id", "notification_type"})) |
... | ... | @@ -96,9 +94,13 @@ |
96 | 94 |
.findUnique(); |
97 | 95 |
} |
98 | 96 |
|
99 |
- public void toggle() { |
|
97 |
+ public void toggle(EventType notificationType) { |
|
100 | 98 |
this.allowed = !this.allowed; |
101 |
- update(); |
|
99 |
+ if (allowed == isNotifiedByDefault(notificationType)) { |
|
100 |
+ delete(); |
|
101 |
+ } else { |
|
102 |
+ update(); |
|
103 |
+ } |
|
102 | 104 |
} |
103 | 105 |
|
104 | 106 |
public static void unwatchExplictly(User user, Project project, EventType notiType) { |
... | ... | @@ -144,10 +146,18 @@ |
144 | 146 |
} |
145 | 147 |
|
146 | 148 |
public static Set<User> findEventWatchersByEventType(Long projectId, EventType eventType) { |
149 |
+ return findByEventTypeAndOption(projectId, eventType, true); |
|
150 |
+ } |
|
151 |
+ |
|
152 |
+ public static Set<User> findEventUnwatchersByEventType(Long projectId, EventType eventType) { |
|
153 |
+ return findByEventTypeAndOption(projectId, eventType, false); |
|
154 |
+ } |
|
155 |
+ |
|
156 |
+ private static Set<User> findByEventTypeAndOption(Long projectId, EventType eventType, boolean isAllowd) { |
|
147 | 157 |
List<UserProjectNotification> userProjectNotifications = find.where() |
148 | 158 |
.eq("project.id", projectId) |
149 | 159 |
.eq("notificationType", eventType) |
150 |
- .eq("allowed", true) |
|
160 |
+ .eq("allowed", isAllowd) |
|
151 | 161 |
.findList(); |
152 | 162 |
Set<User> users = new LinkedHashSet<>(); |
153 | 163 |
for (UserProjectNotification notification : userProjectNotifications) { |
--- conf/messages
+++ conf/messages
... | ... | @@ -483,7 +483,7 @@ |
483 | 483 |
notification.type.pullrequest.reviewed = Pull request review completed. |
484 | 484 |
notification.type.pullrequest.state.changed = Pull request Status changed. |
485 | 485 |
notification.type.pullrequest.unreviewed = Pull request review is canceled. |
486 |
-notification.type.resource.deleted = Deleted |
|
486 |
+notification.type.resource.deleted = Issue/Posting deletion |
|
487 | 487 |
notification.type.review.state.changed = Review Thread State Change |
488 | 488 |
notification.unwatch = Unwatch |
489 | 489 |
notification.watch = Watch |
--- conf/messages.ko-KR
+++ conf/messages.ko-KR
... | ... | @@ -484,7 +484,7 @@ |
484 | 484 |
notification.type.pullrequest.reviewed = 코드보내기 리뷰가 완료되었습니다. |
485 | 485 |
notification.type.pullrequest.state.changed = 코드보내기 상태 변경 |
486 | 486 |
notification.type.pullrequest.unreviewed = 코드보내기 리뷰가 취소되었습니다. |
487 |
-notification.type.resource.deleted = 삭제되었습니다 |
|
487 |
+notification.type.resource.deleted = 이슈/게시글 삭제 |
|
488 | 488 |
notification.type.review.state.changed = 리뷰 스레드 상태 변경 |
489 | 489 |
notification.unwatch = 그만 지켜보기 |
490 | 490 |
notification.watch = 지켜보기 |
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?