Suwon Chae 2015-04-18
notification: Add noti mail send option
User can choose to send modification mail or not
@5f643760bdf65d0145aa5ec6d7b14585e66bf39b
app/assets/stylesheets/less/_page.less
--- app/assets/stylesheets/less/_page.less
+++ app/assets/stylesheets/less/_page.less
@@ -6239,3 +6239,16 @@
   border-radius: 2px;
   color: #3592B5;
 }
+
+.send-notification-check {
+    vertical-align: middle;
+    padding: 9px;
+    border-radius: 3px;
+    strong {
+        margin-right: 5px;
+    }
+    .checkbox.inline {
+        padding-top: 0px;
+    }
+}
+
app/controllers/AbstractPostingApp.java
--- app/controllers/AbstractPostingApp.java
+++ app/controllers/AbstractPostingApp.java
@@ -33,6 +33,8 @@
 import play.mvc.*;
 import utils.*;
 
+import java.util.Map;
+
 @AnonymousCheck
 public class AbstractPostingApp extends Controller {
     public static final int ITEMS_PER_PAGE = 15;
@@ -156,4 +158,18 @@
         }
         return StringUtils.isNotBlank(files[0]);
     }
+
+    protected static boolean isSelectedToSendNotificationMail() {
+        Map<String,String[]> data;
+        if (isMultiPartFormData()) {
+            data = request().body().asMultipartFormData().asFormUrlEncoded();
+        } else {
+            data = request().body().asFormUrlEncoded();
+        }
+        return "yes".equalsIgnoreCase(HttpUtil.getFirstValueFromQuery(data, "notificationMail"));
+    }
+
+    private static boolean isMultiPartFormData() {
+        return request().body().asMultipartFormData() != null;
+    }
 }
app/controllers/BoardApp.java
--- app/controllers/BoardApp.java
+++ app/controllers/BoardApp.java
@@ -234,6 +234,9 @@
             @Override
             public void run() {
                 post.comments = original.comments;
+                if(isSelectedToSendNotificationMail() || !original.isAuthoredBy(UserApp.currentUser())){
+                    NotificationEvent.afterNewPost(post);
+                }
             }
         };
 
@@ -294,7 +297,9 @@
         if (existingComment != null) {
             existingComment.contents = comment.contents;
             savedComment = saveComment(existingComment, getContainerUpdater(posting, comment));
-            NotificationEvent.afterCommentUpdated(savedComment);
+            if(isSelectedToSendNotificationMail() || !existingComment.isAuthoredBy(UserApp.currentUser())){
+                NotificationEvent.afterCommentUpdated(savedComment);
+            }
         } else {
             savedComment = saveComment(comment, getContainerUpdater(posting, comment));
             NotificationEvent.afterNewComment(savedComment);
app/controllers/CommentApp.java
--- app/controllers/CommentApp.java
+++ app/controllers/CommentApp.java
@@ -21,6 +21,7 @@
 package controllers;
 
 import controllers.annotation.AnonymousCheck;
+import models.Comment;
 import models.enumeration.Operation;
 import models.resource.Resource;
 import play.db.ebean.Transactional;
@@ -54,5 +55,8 @@
         }
     }
 
+    public static boolean isCurrentUserTheAuthor(Comment comment){
+        return UserApp.currentUser().loginId.equals(comment.authorLoginId);
+    }
 
 }
app/controllers/IssueApp.java
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
@@ -524,9 +524,11 @@
                 issue.comments = originalIssue.comments;
                 addLabels(issue, request());
 
-                addAssigneeChangedNotification(issue, originalIssue);
-                addStateChangedNotification(issue, originalIssue);
-                addBodyChangedNotification(issue, originalIssue);
+                if(isSelectedToSendNotificationMail() || !originalIssue.isAuthoredBy(UserApp.currentUser())){
+                    addAssigneeChangedNotification(issue, originalIssue);
+                    addStateChangedNotification(issue, originalIssue);
+                    addBodyChangedNotification(issue, originalIssue);
+                }
             }
         };
 
@@ -602,7 +604,9 @@
         if (existingComment != null) {
             existingComment.contents = comment.contents;
             savedComment = saveComment(existingComment, getContainerUpdater(issue, comment));
-            NotificationEvent.afterCommentUpdated(savedComment);
+            if(isSelectedToSendNotificationMail() || !existingComment.isAuthoredBy(UserApp.currentUser())){
+                NotificationEvent.afterCommentUpdated(savedComment);
+            }
         } else {
             savedComment = saveComment(comment, getContainerUpdater(issue, comment));
             NotificationEvent.afterNewComment(savedComment);
app/models/AbstractPosting.java
--- app/models/AbstractPosting.java
+++ app/models/AbstractPosting.java
@@ -23,6 +23,7 @@
 import models.enumeration.ResourceType;
 import models.resource.Resource;
 import models.resource.ResourceConvertible;
+import org.apache.commons.lang.StringUtils;
 import org.joda.time.Duration;
 import play.data.format.Formats;
 import play.data.validation.Constraints;
@@ -30,6 +31,7 @@
 import play.db.ebean.Transactional;
 import utils.JodaDateUtil;
 
+import javax.annotation.Nonnull;
 import javax.persistence.*;
 import javax.validation.constraints.Size;
 import java.util.Date;
@@ -257,4 +259,8 @@
     }
 
     public abstract void checkLabels() throws IssueLabel.IssueLabelException;
+
+    public boolean isAuthoredBy(@Nonnull User user){
+        return StringUtils.equalsIgnoreCase(this.authorLoginId, user.loginId);
+    }
 }
app/models/Comment.java
--- app/models/Comment.java
+++ app/models/Comment.java
@@ -23,6 +23,7 @@
 import com.avaje.ebean.annotation.Transactional;
 import models.resource.Resource;
 import models.resource.ResourceConvertible;
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.joda.time.Duration;
@@ -30,6 +31,7 @@
 import play.db.ebean.Model;
 import utils.JodaDateUtil;
 
+import javax.annotation.Nonnull;
 import javax.persistence.Id;
 import javax.persistence.Lob;
 import javax.persistence.MappedSuperclass;
@@ -153,4 +155,8 @@
                 .append(authorName)
                 .toHashCode();
     }
+
+    public boolean isAuthoredBy(@Nonnull User user){
+        return StringUtils.equalsIgnoreCase(this.authorLoginId, user.loginId);
+    }
 }
app/views/board/edit.scala.html
--- app/views/board/edit.scala.html
+++ app/views/board/edit.scala.html
@@ -78,6 +78,14 @@
         </div>
 
         <div class="actions">
+          @if(posting.getAuthor.equals(UserApp.currentUser()) && !posting.readme){
+            <span class="send-notification-check">
+              <label class="checkbox inline">
+                <input type="checkbox" name="notificationMail" id="notificationMail" value="yes" checked>
+                <strong>@Messages("notification.send.mail")</strong>
+              </label>
+            </span>
+          }
           <button class="ybtn ybtn-info" tabindex="3">@Messages("button.save")</button><!--
          --><a href="javascript:history.back();" class="ybtn" tabindex="4">@Messages("button.cancel")</a>
         </div>
app/views/board/partial_comments.scala.html
--- app/views/board/partial_comments.scala.html
+++ app/views/board/partial_comments.scala.html
@@ -63,7 +63,7 @@
                 </span>
             </div>
 
-            @common.commentUpdateForm(comment.id, routes.BoardApp.newComment(project.owner, project.name, post.getNumber).toString(), comment.contents)
+            @common.commentUpdateForm(comment, routes.BoardApp.newComment(project.owner, project.name, post.getNumber).toString(), comment.contents)
 
             <div id="comment-body-@comment.id">
                 <div class="comment-body markdown-wrap" data-via-email="@OriginalEmail.exists(comment.asResource)">@Html(Markdown.render(comment.contents, project))</div>
app/views/common/commentUpdateForm.scala.html
--- app/views/common/commentUpdateForm.scala.html
+++ app/views/common/commentUpdateForm.scala.html
@@ -18,18 +18,26 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **@
-@(commentId:Long, action:String, contents:String)
+@(comment:Comment, action:String, contents:String)
 
-<div id="comment-editform-@commentId" class="comment-update-form">
+<div id="comment-editform-@comment.id" class="comment-update-form">
     <form action="@action" method="post">
-        <input type="hidden" name="id" value="@commentId">
+        <input type="hidden" name="id" value="@comment.id">
 
         <div class="write-comment-box">
             <div class="write-comment-wrap">
                 @common.editor("contents", contents,"", "update-comment-body")
 
                 <div class="right-txt comment-update-button">
-                    <button type="button" class="ybtn ybtn-cancel" data-comment-id="@commentId">@Messages("button.cancel")</button>
+                    @if(comment.isAuthoredBy(UserApp.currentUser())){
+                    <span class="send-notification-check" data-toggle='popover' data-trigger="hover" data-placement="top" data-content="@Messages("notification.send.mail.warning")">
+                        <label class="checkbox inline">
+                            <input type="checkbox" name="notificationMail" id="notificationMail" value="yes" checked>
+                            <strong>@Messages("notification.send.mail")</strong>
+                        </label>
+                    </span>
+                    }
+                    <button type="button" class="ybtn ybtn-cancel" data-comment-id="@comment.id">@Messages("button.cancel")</button>
                     <button type="submit" class="ybtn ybtn-info">@Messages("button.save")</button>
                 </div>
             </div>
app/views/issue/edit.scala.html
--- app/views/issue/edit.scala.html
+++ app/views/issue/edit.scala.html
@@ -71,6 +71,14 @@
                     @** end of fileUploader **@
 
                     <div class=" actrow right-txt">
+                        @if(issue.isAuthoredBy(UserApp.currentUser())){
+                        <span class="send-notification-check">
+                            <label class="checkbox inline">
+                                <input type="checkbox" name="notificationMail" id="notificationMail" value="yes" checked>
+                                <strong>@Messages("notification.send.mail")</strong>
+                            </label>
+                        </span>
+                        }
                         <button type="submit" class="ybtn ybtn-info">@Messages("button.save")</button><!--
                      --><a href="javascript:history.back();" class="ybtn">@Messages("button.cancel")</a>
                     </div>
app/views/issue/partial_comments.scala.html
--- app/views/issue/partial_comments.scala.html
+++ app/views/issue/partial_comments.scala.html
@@ -144,7 +144,7 @@
                 </span>
             </div>
 
-            @common.commentUpdateForm(comment.id, routes.IssueApp.newComment(project.owner, project.name, issue.getNumber).toString(), comment.contents)
+            @common.commentUpdateForm(comment, routes.IssueApp.newComment(project.owner, project.name, issue.getNumber).toString(), comment.contents)
 
             <div id="comment-body-@comment.id">
                 <div class="comment-body markdown-wrap" data-via-email="@OriginalEmail.exists(comment.asResource)">@Html(Markdown.render(comment.contents, project))</div>
conf/messages
--- conf/messages
+++ conf/messages
@@ -394,6 +394,8 @@
 notification.reviewthread.reopened = Review thread reopened
 notification.reviewthread.inTheFile = In {0}:
 notification.type.comment.updated = Comment updated
+notification.send.mail = Send notification mail
+notification.send.mail.warning = If you are not original author, this option will be ignored. Noti mail will be sent.
 notification.type.issue.assignee.changed = Issue assignee changed.
 notification.type.issue.body.changed = Issue body changed
 notification.type.issue.referred.from.commit = Issue mentioned in commit
conf/messages.ko-KR
--- conf/messages.ko-KR
+++ conf/messages.ko-KR
@@ -393,6 +393,8 @@
 notification.reviewthread.reopened = 리뷰 스레드 다시 열림
 notification.reviewthread.inTheFile = {0} 에서:
 notification.type.comment.updated = 댓글 수정
+notification.send.mail = 수정에 대한 알림 메일 발송
+notification.send.mail.warning = 만약 해당글의 원 작성자가 아니라면 이 옵션은 무시되고 알림 메일이 발송됩니다.
 notification.type.issue.assignee.changed = 이슈 담당자 변경
 notification.type.issue.body.changed = 이슈 본문 변경
 notification.type.issue.referred.from.commit = 커밋에서의 이슈 언급
public/javascripts/common/yobi.Comment.js
--- public/javascripts/common/yobi.Comment.js
+++ public/javascripts/common/yobi.Comment.js
@@ -53,6 +53,7 @@
 
         $('#comment-editform-' + commentId).toggle();
         $('#comment-body-' + commentId).toggle();
+        $("[data-toggle='popover']").popover();
     }
 
     /**
Add a comment
List