Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r53be6f88884b380ccb963eb05c985a57f580b5d4 -r16eafe54d28edddfe0bdb558a18c68e1962cb536 Binary files differ Index: lams_central/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r5f4bc2d10944b6f6fffcfa066fbdb9497e1cbf0c -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 5f4bc2d10944b6f6fffcfa066fbdb9497e1cbf0c) +++ lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -679,4 +679,6 @@ label.no.comments=No Comments label.newest.first=Newest First label.top.comments=Top Comments +label.add.sticky=Stick To Top +label.remove.sticky=Remove Sticky #======= End labels: Exported 439 labels for en AU ===== Index: lams_central/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== diff -u -r5f4bc2d10944b6f6fffcfa066fbdb9497e1cbf0c -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 5f4bc2d10944b6f6fffcfa066fbdb9497e1cbf0c) +++ lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -669,4 +669,6 @@ label.no.comments=No Comments label.newest.first=Newest First label.top.comments=Top Comments +label.add.sticky=Stick To Top +label.remove.sticky=Remove Sticky #======= End labels: Exported 439 labels for en AU ===== Index: lams_central/conf/xdoclet/struts-actions.xml =================================================================== diff -u -rae9d620300d1143e326d68c80f84359252fa64fd -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/conf/xdoclet/struts-actions.xml (.../struts-actions.xml) (revision ae9d620300d1143e326d68c80f84359252fa64fd) +++ lams_central/conf/xdoclet/struts-actions.xml (.../struts-actions.xml) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -20,6 +20,7 @@ scope="request" > + + + + + \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/comments/CommentConstants.java =================================================================== diff -u -r30969026bd35b912bde264a9b16e49848a6d9463 -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/src/java/org/lamsfoundation/lams/comments/CommentConstants.java (.../CommentConstants.java) (revision 30969026bd35b912bde264a9b16e49848a6d9463) +++ lams_central/src/java/org/lamsfoundation/lams/comments/CommentConstants.java (.../CommentConstants.java) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -43,6 +43,7 @@ public static final String ATTR_LIKE_AND_DISLIKE = "likeAndDislike"; public static final String ATTR_READ_ONLY = "readOnly"; public static final String ATTR_SORT_BY = "sortBy"; // 0 date, 1 likes + public static final String ATTR_STICKY = "sticky"; // 0 date, 1 likes // for paging long topics & inlining reply public static final String PAGE_LAST_ID = "pageLastId"; Index: lams_central/src/java/org/lamsfoundation/lams/comments/web/CommentAction.java =================================================================== diff -u -r1c6cd416ca3946f49e0bb6cb2cecc7107887d7f5 -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/src/java/org/lamsfoundation/lams/comments/web/CommentAction.java (.../CommentAction.java) (revision 1c6cd416ca3946f49e0bb6cb2cecc7107887d7f5) +++ lams_central/src/java/org/lamsfoundation/lams/comments/web/CommentAction.java (.../CommentAction.java) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -112,6 +112,9 @@ if (param.equals("hide")) { return hideComment(mapping, form, request, response, false); } + if (param.equals("makeSticky")) { + return makeSticky(mapping, form, request, response); + } return mapping.findForward("error"); } @@ -188,23 +191,34 @@ Comment rootComment = getCommentService().createOrGetRoot(externalId, externalType, externalSignature, user); sessionMap.put(CommentConstants.ATTR_ROOT_COMMENT_UID, rootComment.getUid()); - return viewTopicImpl(mapping, form, request, response, sessionMap, pageSize, sortBy); + return viewTopicImpl(mapping, form, request, response, sessionMap, pageSize, sortBy, true); } private void throwException(String msg, String loginName, Long externalId, Integer externalType, String externalSignature) throws ServletException { String error = msg+" User "+loginName+" "+externalId+":"+externalType+":"+externalSignature; log.error(error); throw new ServletException(error); } - + + private void throwException(String msg, String loginName) throws ServletException { + String error = msg+" User "+loginName; + log.error(error); + throw new ServletException(error); + } + private boolean learnerInToolSession(Long toolSessionId, User user) { GroupedToolSession toolSession = (GroupedToolSession) getCoreToolService().getToolSessionById(toolSessionId); return toolSession.getSessionGroup().getUsers().contains(user); } - private boolean monitorInToolSession(Long toolSessionId, User user) { - GroupedToolSession toolSession = (GroupedToolSession) getCoreToolService().getToolSessionById(toolSessionId); - return getSecurityService().isLessonMonitor(toolSession.getLesson().getLessonId(), user.getUserId(), "Comment Monitoring Tasks", false); + private boolean monitorInToolSession(Long toolSessionId, User user, SessionMap sessionMap) { + + if ( ToolAccessMode.TEACHER.equals(WebUtil.getToolAccessMode((String)sessionMap.get(AttributeNames.ATTR_MODE))) ) { + GroupedToolSession toolSession = (GroupedToolSession) getCoreToolService().getToolSessionById(toolSessionId); + return getSecurityService().isLessonMonitor(toolSession.getLesson().getLessonId(), user.getUserId(), "Comment Monitoring Tasks", false); + } else { + return false; + } } /** @@ -226,14 +240,15 @@ SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); Integer pageSize = WebUtil.readIntParam(request, CommentConstants.PAGE_SIZE, true); Integer sortBy = WebUtil.readIntParam(request, CommentConstants.ATTR_SORT_BY, true); + Boolean sticky = WebUtil.readBooleanParam(request, CommentConstants.ATTR_STICKY, false); if ( sortBy != null ) sessionMap.put( CommentConstants.ATTR_SORT_BY, sortBy); - return viewTopicImpl(mapping, form, request, response, sessionMap, pageSize, sortBy); + return viewTopicImpl(mapping, form, request, response, sessionMap, pageSize, sortBy, sticky); } private ActionForward viewTopicImpl(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response, SessionMap sessionMap, Integer pageSize, Integer sortBy) { + HttpServletResponse response, SessionMap sessionMap, Integer pageSize, Integer sortBy, boolean includeSticky) { Long externalId = (Long) sessionMap.get(CommentConstants.ATTR_EXTERNAL_ID); Integer externalType = (Integer) sessionMap.get(CommentConstants.ATTR_EXTERNAL_TYPE); @@ -256,11 +271,17 @@ List msgDtoList = commentService.getTopicThread(externalId, externalType, externalSignature, lastMsgSeqId, pageSize, sortBy, currentLikeCount, user.getUserID()); updateMessageFlag(msgDtoList, user.getUserID()); request.setAttribute(CommentConstants.ATTR_COMMENT_THREAD, msgDtoList); + + if ( includeSticky ) { + List stickyList = commentService.getTopicStickyThread(externalId, externalType, externalSignature,sortBy, currentLikeCount, user.getUserID()); + updateMessageFlag(stickyList, user.getUserID()); + request.setAttribute(CommentConstants.ATTR_STICKY, stickyList); + } // transfer SessionMapID as well request.setAttribute(CommentConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); - return mapping.findForward("success"); + return mapping.findForward(includeSticky ? "successAll" : "success"); } @SuppressWarnings("unchecked") @@ -363,7 +384,8 @@ commentService = getCommentService(); User user = getCurrentUser(request); - if ( ! learnerInToolSession(externalId, user) ) + boolean monitoringMode = ToolAccessMode.TEACHER.equals(WebUtil.getToolAccessMode((String)sessionMap.get(AttributeNames.ATTR_MODE))); + if ( ! learnerInToolSession(externalId, user) && ! monitorInToolSession(externalId, user, sessionMap) ) throwException("New comment: User does not have the rights to access the comments. ", user.getLogin(), externalId, externalType, externalSignature ); Comment rootSeq = commentService.getRoot(externalId, externalType, externalSignature); @@ -435,7 +457,7 @@ commentService = getCommentService(); User user = getCurrentUser(request); - if ( ! learnerInToolSession(externalId, user) ) + if ( ! learnerInToolSession(externalId, user) && ! monitorInToolSession(externalId, user, sessionMap) ) throwException("New comment: User does not have the rights to access the comments. ", user.getLogin(), externalId, externalType, externalSignature ); // save message into database @@ -517,12 +539,12 @@ CommentDTO originalComment = commentService.getComment(commentId); - boolean monitoringMode = ToolAccessMode.TEACHER.equals(WebUtil.getToolAccessMode((String)sessionMap.get(AttributeNames.ATTR_MODE))); User user = getCurrentUser(request); - if ( ! originalComment.getComment().getCreatedBy().equals(user) && ! ( monitoringMode && monitorInToolSession(externalId, user) ) ) + if ( ! originalComment.getComment().getCreatedBy().equals(user) && ! monitorInToolSession(externalId, user, sessionMap) ) throwException("Update comment: User does not have the rights to update the comment "+commentId+". ", user.getLogin(), externalId, externalType, externalSignature ); - Comment updatedComment = commentService.updateComment(commentId, commentText, user, monitoringMode); + Comment updatedComment = commentService.updateComment(commentId, commentText, user, + ToolAccessMode.TEACHER.equals(WebUtil.getToolAccessMode((String)sessionMap.get(AttributeNames.ATTR_MODE)))); JSONObject = new JSONObject(); JSONObject.put(CommentConstants.ATTR_COMMENT_ID, commentId); @@ -579,9 +601,8 @@ commentService = getCommentService(); - boolean monitoringMode = ToolAccessMode.TEACHER.equals(WebUtil.getToolAccessMode((String)sessionMap.get(AttributeNames.ATTR_MODE))); User user = getCurrentUser(request); - if ( ! monitoringMode || ! monitorInToolSession(externalId, user) ) + if ( ! monitorInToolSession(externalId, user, sessionMap) ) throwException("Update comment: User does not have the rights to hide the comment "+commentId+". ", user.getLogin(), externalId, (Integer) sessionMap.get(CommentConstants.ATTR_EXTERNAL_TYPE), (String) sessionMap.get(CommentConstants.ATTR_EXTERNAL_SIG) ); @@ -599,6 +620,39 @@ } /** + * Make a topic sticky - the topic should be level 1 only. + * @throws ServletException + */ + public ActionForward makeSticky(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException, ServletException { + + commentService = getCommentService(); + SessionMap sessionMap = getSessionMap(request); + Long commentId = WebUtil.readLongParam(request, CommentConstants.ATTR_COMMENT_ID); + Boolean sticky = WebUtil.readBooleanParam(request, CommentConstants.ATTR_STICKY); + Long externalId = (Long) sessionMap.get(CommentConstants.ATTR_EXTERNAL_ID); + + CommentDTO originalComment = commentService.getComment(commentId); + User user = getCurrentUser(request); + + if ( ! monitorInToolSession(externalId, user, sessionMap)) + throwException("Make comment sticky: User does not have the rights to make the comment stick to the top of the list "+commentId+". ", user.getLogin()); + if ( originalComment.getComment().getCommentLevel() != 1) + throwException("Make comment sticky: Comment much be level 1 to stick to the top of the list "+commentId+" level "+originalComment.getLevel()+". ", user.getLogin()); + + Comment updatedComment = commentService.updateSticky(commentId, sticky); + + JSONObject JSONObject = new JSONObject(); + JSONObject.put(CommentConstants.ATTR_COMMENT_ID, commentId); + JSONObject.put(CommentConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); + JSONObject.put(CommentConstants.ATTR_THREAD_ID, updatedComment.getThreadComment().getUid()); + JSONObject.put(CommentConstants.ATTR_PARENT_COMMENT_ID, updatedComment.getParent().getUid()); + + response.setContentType("application/json;charset=utf-8"); + response.getWriter().print(JSONObject); + return null; + } + /** * Get login user information from system level session. */ private User getCurrentUser(HttpServletRequest request) { Index: lams_central/web/comments/allview.jsp =================================================================== diff -u --- lams_central/web/comments/allview.jsp (revision 0) +++ lams_central/web/comments/allview.jsp (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -0,0 +1,27 @@ + + + + + + +
+ <%@ include file="topicview.jsp"%> +
+ + + +
+ + + + + +
+ + <%@ include file="topicview.jsp"%> + +
+ \ No newline at end of file Index: lams_central/web/comments/allviewwrapper.jsp =================================================================== diff -u --- lams_central/web/comments/allviewwrapper.jsp (revision 0) +++ lams_central/web/comments/allviewwrapper.jsp (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -0,0 +1,19 @@ + + + + +<%@ taglib uri="tags-lams" prefix="lams"%> +<%@ taglib uri="tags-core" prefix="c"%> +<%@ taglib uri="tags-html" prefix="html"%> +<%@ taglib uri="tags-fmt" prefix="fmt"%> + + + + + + + + +<%@ include file="allview.jsp"%> + + Index: lams_central/web/comments/comments.jsp =================================================================== diff -u -r4df9f0edfb3b0b15dd52743caf6c655a461b531c -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/web/comments/comments.jsp (.../comments.jsp) (revision 4df9f0edfb3b0b15dd52743caf6c655a461b531c) +++ lams_central/web/comments/comments.jsp (.../comments.jsp) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -42,22 +42,20 @@ scrollDoneCallback(); $('#sortMenu').change(function(){ - var url = "comments/viewTopic.do?sessionMapID=${sessionMapID}&sortBy="+$(this).find("option:selected").attr('value'); - reloadScroll(url); + var url = "comments/viewTopic.do?sessionMapID=${sessionMapID}&sticky=true&sortBy="+$(this).find("option:selected").attr('value'); + reloadDivs(url); }); }); function refreshComments(){ var reqIDVar = new Date(); - reloadScroll('comments/viewTopic.do?sessionMapID=${sessionMapID}&reqUid='+reqIDVar.getTime()); + reloadDivs('comments/viewTopic.do?sessionMapID=${sessionMapID}&sticky=true&reqUid='+reqIDVar.getTime()); } - function reloadScroll(url) { + function reloadDivs(url) { $('#newcomments').children().remove(); - $('.scroll').load(url, function() { - $('.scroll').data('jscroll', null); - $('.scroll').jscroll({loadingHtml: '${loading_words}${loading_words}',padding:30,autoTrigger:false,callback:scrollDoneCallback}); - }); + $('.scroll').data('jscroll', null); + $('#commentDiv').load(url); } function scrollDoneCallback() { @@ -68,7 +66,7 @@

- + <%@ include file="new.jsp"%> @@ -80,20 +78,9 @@
- - - - -
-
- - <%@ include file="topicview.jsp"%> - -
-
- - +
+ <%@ include file="allview.jsp"%> +
+ Index: lams_central/web/comments/msgview.jsp =================================================================== diff -u -r3074a9a950b01b5d024ca73e9ac0cc15c5d6f921 -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/web/comments/msgview.jsp (.../msgview.jsp) (revision 3074a9a950b01b5d024ca73e9ac0cc15c5d6f921) +++ lams_central/web/comments/msgview.jsp (.../msgview.jsp) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -30,11 +30,24 @@   - - - + + + + + + + + + + + + + + + () - + + @@ -53,7 +66,7 @@ - + comments/newReplyTopic.do?sessionMapID=${sessionMapID}&parentUid=${commentDto.comment.uid} Reply · @@ -82,6 +95,13 @@ · + + comments/makeSticky.do?sessionMapID=${sessionMapID}&commentUid=${commentDto.comment.uid}&create=${commentDto.comment.created.time}&sticky=${!commentDto.comment.sticky} + + + · + + ${commentDto.comment.likeCount} Index: lams_central/web/comments/msgviewwrapper.jsp =================================================================== diff -u -r46bcb6ea758a272250071d1a571d008c6745e593 -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/web/comments/msgviewwrapper.jsp (.../msgviewwrapper.jsp) (revision 46bcb6ea758a272250071d1a571d008c6745e593) +++ lams_central/web/comments/msgviewwrapper.jsp (.../msgviewwrapper.jsp) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -16,6 +16,8 @@ + + Index: lams_central/web/comments/topicview.jsp =================================================================== diff -u -r4df9f0edfb3b0b15dd52743caf6c655a461b531c -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/web/comments/topicview.jsp (.../topicview.jsp) (revision 4df9f0edfb3b0b15dd52743caf6c655a461b531c) +++ lams_central/web/comments/topicview.jsp (.../topicview.jsp) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -3,13 +3,13 @@ - + expandable:true,initialState:'expanded', - expanderTemplate:'    ${prompt}', + expanderTemplate:'     ${prompt}', stringCollapse:'${hide}',stringExpand:'${show}', clickableNodeNames:true,indent:${indent}, onNodeInitialized:function() { @@ -18,6 +18,16 @@ } } +expandable:true,initialState:'collapsed', + expanderTemplate:'     ${prompt}', + stringCollapse:'${hide}',stringExpand:'${show}', + clickableNodeNames:true,indent:${indent}, + onNodeInitialized:function() { + if (this.level() >= 2) { + this.collapse(); + } + } + + + @@ -133,12 +157,13 @@
+
@@ -158,13 +183,13 @@
-
+
/comments/viewTopic.do?pageLastId=${maxThreadUid}&likeCount=${minThreadLike}&pageSize=${sessionMap.pageSize}&sessionMapID=${sessionMapID} " class="button">
Index: lams_central/web/css/defaultHTML_learner.css =================================================================== diff -u -rd8be0fc2c13bfb38ac7239cf7185895a31845e2b -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_central/web/css/defaultHTML_learner.css (.../defaultHTML_learner.css) (revision d8be0fc2c13bfb38ac7239cf7185895a31845e2b) +++ lams_central/web/css/defaultHTML_learner.css (.../defaultHTML_learner.css) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -626,10 +626,13 @@ overflow: hidden; } +.comment-sticky { + color:#0087e5; +} .comment-author { - color:#0087e5; font-size:11px; + font-weight: bold; margin-bottom:2px; } Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/comments/Comment.hbm.xml =================================================================== diff -u -r46bcb6ea758a272250071d1a571d008c6745e593 -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/comments/Comment.hbm.xml (.../Comment.hbm.xml) (revision 46bcb6ea758a272250071d1a571d008c6745e593) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/comments/Comment.hbm.xml (.../Comment.hbm.xml) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -137,6 +137,13 @@ column="comment_level" /> + Index: lams_common/src/java/org/lamsfoundation/lams/comments/Comment.java =================================================================== diff -u -r46bcb6ea758a272250071d1a571d008c6745e593 -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_common/src/java/org/lamsfoundation/lams/comments/Comment.java (.../Comment.java) (revision 46bcb6ea758a272250071d1a571d008c6745e593) +++ lams_common/src/java/org/lamsfoundation/lams/comments/Comment.java (.../Comment.java) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -52,7 +52,8 @@ private Date lastReplyDate; private int replyNumber; private boolean hideFlag; - + private boolean sticky; + private Comment rootComment; private Comment threadComment; private short commentLevel; @@ -177,6 +178,13 @@ this.hideFlag = hideFlag; } + public boolean isSticky() { + return sticky; + } + + public void setSticky(boolean sticky) { + this.sticky = sticky; + } public Comment getParent() { return parent; } Index: lams_common/src/java/org/lamsfoundation/lams/comments/dao/ICommentDAO.java =================================================================== diff -u -r54921c2609f8b6eed36ab972d246bc9094489ebf -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_common/src/java/org/lamsfoundation/lams/comments/dao/ICommentDAO.java (.../ICommentDAO.java) (revision 54921c2609f8b6eed36ab972d246bc9094489ebf) +++ lams_common/src/java/org/lamsfoundation/lams/comments/dao/ICommentDAO.java (.../ICommentDAO.java) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -7,11 +7,8 @@ public interface ICommentDAO { - /* Standard DAO call */ public abstract void saveOrUpdate(Comment comment); - public abstract void update(Comment comment); - public abstract Comment getById(Long commentId); /** @@ -26,5 +23,7 @@ public abstract SortedSet getNextThreadByThreadId(final Long rootTopicId, final Long previousThreadMessageId, Integer numberOfThreads, Integer sortBy, String extraSortParam, Integer userId); + + public abstract SortedSet getStickyThreads(final Long rootTopicId, Integer sortBy, String extraSortParam, Integer userId); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/comments/dao/hibernate/CommentDAO.java =================================================================== diff -u -r54921c2609f8b6eed36ab972d246bc9094489ebf -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_common/src/java/org/lamsfoundation/lams/comments/dao/hibernate/CommentDAO.java (.../CommentDAO.java) (revision 54921c2609f8b6eed36ab972d246bc9094489ebf) +++ lams_common/src/java/org/lamsfoundation/lams/comments/dao/hibernate/CommentDAO.java (.../CommentDAO.java) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -53,11 +53,6 @@ } @Override - public void update(Comment comment) { - this.getHibernateTemplate().saveOrUpdate(comment); - } - - @Override public Comment getById(Long commentId) { return (Comment) getHibernateTemplate().get(Comment.class, commentId); } @@ -128,10 +123,9 @@ } private static final String SQL_QUERY_FIND_FIRST_THREAD_TOP_BY_UID = "SELECT uid FROM lams_comment" - + " WHERE root_comment_uid = :rootUid AND comment_level = 1 ORDER BY uid DESC"; - + + " WHERE root_comment_uid = :rootUid AND comment_level = 1 AND sticky = 0 ORDER BY uid DESC"; private static final String SQL_QUERY_FIND_NEXT_THREAD_TOP = "SELECT uid FROM lams_comment" - + " WHERE root_comment_uid = :rootUid AND uid < :lastUid AND comment_level = 1 ORDER BY uid DESC"; + + " WHERE root_comment_uid = :rootUid AND uid < :lastUid AND comment_level = 1 AND sticky = 0 ORDER BY uid DESC"; private static final String SQL_QUERY_FIND_NEXT_THREAD_MESSAGES = "SELECT c.*, SUM(l.vote) likes_total, l2.vote user_vote FROM lams_comment c " @@ -180,7 +174,7 @@ + " FROM lams_comment c " + " LEFT JOIN lams_comment_likes l ON c.uid = l.comment_uid " + " LEFT JOIN lams_comment_likes l2 ON c.uid = l2.comment_uid AND l2.user_id=:userId " - + " WHERE root_comment_uid = :rootUid AND comment_level = 1 " + + " WHERE root_comment_uid = :rootUid AND comment_level = 1 AND sticky = 0 " + " GROUP BY c.uid " + " ORDER BY likes_total DESC, c.uid DESC"; @@ -189,7 +183,7 @@ + " FROM lams_comment c " + " LEFT JOIN lams_comment_likes l ON c.uid = l.comment_uid " + " LEFT JOIN lams_comment_likes l2 ON c.uid = l2.comment_uid AND l2.user_id=:userId " - + " WHERE root_comment_uid = :rootUid AND comment_level = 1 " + + " WHERE root_comment_uid = :rootUid AND comment_level = 1 AND sticky = 0 " + " GROUP BY c.uid " + " ORDER BY likes_total DESC, c.uid DESC) cl " + " WHERE (cl.likes_total = :like AND cl.uid < :lastUid ) " @@ -250,4 +244,81 @@ } return new TreeSet(); } + + @Override + public SortedSet getStickyThreads(final Long rootTopicId, Integer sortBy, String extraSortParam, Integer userId) { + + if (ICommentService.SORT_BY_LIKE.equals(sortBy)) { + return getStickyByThreadIdLikes(rootTopicId, sortBy, extraSortParam, userId); + } else { + return getStickyByThreadIdNewestFirst(rootTopicId, sortBy, userId); + } + + } + + private static final String SQL_QUERY_FIND_STICKY_BY_UID = "SELECT uid FROM lams_comment" + + " WHERE root_comment_uid = :rootUid AND comment_level = 1 AND sticky = 1 ORDER BY uid DESC"; + + @SuppressWarnings({"unchecked" }) + private SortedSet getStickyByThreadIdNewestFirst(final Long rootTopicId, Integer sortBy, Integer userId) { + + // the search to get to the top level is quite light, so get just the uids + // then build a complete set. + List threadUidList = (List) getSession(). + createSQLQuery(SQL_QUERY_FIND_STICKY_BY_UID) + .setLong("rootUid", rootTopicId) + .list(); + + if (threadUidList != null && threadUidList.size() > 0) { + SQLQuery query = getSession().createSQLQuery(SQL_QUERY_FIND_NEXT_THREAD_MESSAGES); + query.addEntity("comment", Comment.class) + .addScalar("likes_total", Hibernate.INTEGER) + .addScalar("user_vote", Hibernate.INTEGER) + .setLong("userId", userId != null ? userId : 0) + .setParameterList("threadIds", threadUidList); + List results = query.list(); + return upgradeComments(results, sortBy); + } + return new TreeSet(); + } + + private static final String SQL_QUERY_FIND_STICKY_BY_LIKES = "SELECT c.*, COALESCE(SUM(l.vote),0) likes_total, l2.vote user_vote" + + " FROM lams_comment c " + + " LEFT JOIN lams_comment_likes l ON c.uid = l.comment_uid " + + " LEFT JOIN lams_comment_likes l2 ON c.uid = l2.comment_uid AND l2.user_id=:userId " + + " WHERE root_comment_uid = :rootUid AND comment_level = 1 AND c.sticky = 1 " + + " GROUP BY c.uid " + + " ORDER BY likes_total DESC, c.uid DESC"; + + @SuppressWarnings({ "unchecked" }) + private SortedSet getStickyByThreadIdLikes(final Long rootTopicId, Integer sortBy, String extraSortParam, Integer userId) { + + List topThreadObjects = (List) getSession().createSQLQuery(SQL_QUERY_FIND_STICKY_BY_LIKES) + .addEntity("comment", Comment.class) + .addScalar("likes_total", Hibernate.INTEGER) + .addScalar("user_vote", Hibernate.INTEGER) + .setLong("rootUid", rootTopicId) + .setLong("userId", userId != null ? userId : 0) + .list(); + + if (topThreadObjects != null && topThreadObjects.size() > 0) { + // build the list of uids + List threadUidList = new ArrayList(); + for ( Object[] rawObject : topThreadObjects ) { + Comment comment = (Comment) rawObject[0]; + threadUidList.add(comment.getUid()); + } + SQLQuery query = getSession().createSQLQuery(SQL_QUERY_FIND_NEXT_THREAD_MESSAGES_REPLIES_ONLY); + query.addEntity("comment", Comment.class) + .addScalar("likes_total", Hibernate.INTEGER) + .addScalar("user_vote", Hibernate.INTEGER) + .setLong("userId", userId != null ? userId : 0) + .setParameterList("threadIds", threadUidList); + List results = query.list(); + topThreadObjects.addAll(results); + return upgradeComments(topThreadObjects, sortBy); + } + return new TreeSet(); + } + } Index: lams_common/src/java/org/lamsfoundation/lams/comments/service/CommentService.java =================================================================== diff -u -r54921c2609f8b6eed36ab972d246bc9094489ebf -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_common/src/java/org/lamsfoundation/lams/comments/service/CommentService.java (.../CommentService.java) (revision 54921c2609f8b6eed36ab972d246bc9094489ebf) +++ lams_common/src/java/org/lamsfoundation/lams/comments/service/CommentService.java (.../CommentService.java) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -78,7 +78,23 @@ SortedSet comments = commentDAO.getNextThreadByThreadId(rootTopic.getUid(), lastThreadMessageUid, pageSize, sortBy, extraSortParam, userId); return getSortedCommentDTO(comments); } - + + @Override + public List getTopicStickyThread(Long externalId, Integer externalType, String externalSignature, + Integer sortBy, String extraSortParam, Integer userId) { + + // hidden root of all the threads! + Comment rootTopic = commentDAO.getRootTopic(externalId, externalType, externalSignature); + + // first time through - no root topic. + if ( rootTopic == null ) { + return new ArrayList(); + } + + SortedSet comments = commentDAO.getStickyThreads(rootTopic.getUid(), sortBy, extraSortParam, userId); + return getSortedCommentDTO(comments); + } + private List getSortedCommentDTO(SortedSet comments) { List msgDtoList = new ArrayList(); @@ -215,6 +231,19 @@ } } + public Comment updateSticky(Long commentUid, Boolean newSticky) { + + Comment comment = commentDAO.getById(commentUid); + if ( comment != null ) { + comment.setSticky(newSticky); + commentDAO.saveOrUpdate(comment); + return comment; + } else { + log.error("Unable to update comment as comment not found. Comment uid "+commentUid + +" new sticky "+newSticky); + return null; + } + } public CommentDTO getComment(Long commentUid){ Comment comment = commentDAO.getById(commentUid); return comment != null ? CommentDTO.getCommentDTO(comment) : null; Index: lams_common/src/java/org/lamsfoundation/lams/comments/service/ICommentService.java =================================================================== diff -u -r54921c2609f8b6eed36ab972d246bc9094489ebf -r16eafe54d28edddfe0bdb558a18c68e1962cb536 --- lams_common/src/java/org/lamsfoundation/lams/comments/service/ICommentService.java (.../ICommentService.java) (revision 54921c2609f8b6eed36ab972d246bc9094489ebf) +++ lams_common/src/java/org/lamsfoundation/lams/comments/service/ICommentService.java (.../ICommentService.java) (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -37,10 +37,15 @@ public static final Integer SORT_BY_LIKE = 1; - /** Gets the comments for a tool, based on the tool session and the tool's id. Allows for paging */ + /** Gets the comments for a tool, based on the tool session and the tool's id. Allows for paging. + * Will not include the sticky - get them using getTopicStickyThread() */ List getTopicThread(Long externalId, Integer externalType, String externalSignature, Long lastMsgSeqId, Integer pageSize, Integer sortBy, String extraSortParam, Integer userId); + /** Gets all the sticky comments for a tool, based on the tool session and the tool's id */ + List getTopicStickyThread(Long externalId, Integer externalType, String externalSignature, + Integer sortBy, String extraSortParam, Integer userId); + /** Saves a comment - either creating a whole tree one if there is no parent or saving under the given parent. */ Comment createReply(Long parentId, String replyText, User user); Comment createReply(Comment parent, String replyText, User user); @@ -62,6 +67,9 @@ /** Update the body in a comment, and update the modified time, who by, etc, etc */ Comment updateComment(Long commentUid, String newBody, User user, boolean makeAuditEntry); + /** Update the sticky flag for a comment */ + Comment updateSticky(Long commentUid, Boolean newSticky); + /** Update the like list for Comment commentUid by likeVote. Returns true if like/dislike added. */ boolean addLike(Long commentUid, User user, Integer likeVote); Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040061.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040061.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040061.sql (revision 16eafe54d28edddfe0bdb558a18c68e1962cb536) @@ -0,0 +1,10 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; + +-- LDEV-3756 Noticeboard comments: set thread to top +ALTER TABLE lams_comment +ADD COLUMN sticky SMALLINT(6) NULL DEFAULT 0, +ADD INDEX IX_comment_level_sticky (comment_level ASC, sticky ASC); + +COMMIT; +SET AUTOCOMMIT = 1; \ No newline at end of file