Skip to content

Commit

Permalink
SAK-46022 Add High-Priority option to Commons posts (sakaiproject#9638)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkozar2 authored Aug 31, 2021
1 parent 50983ae commit e295237
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 11 deletions.
7 changes: 7 additions & 0 deletions commons/api/src/bundle/commons.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ like = Like
people = people liked this
person = person liked this
reply = Reply
priority = Make this post High-Priority
priorityHelp = When a post is marked as High Priority, an email notification is sent to participants that contains the text of the post and will be flagged as High Priority within the Commons tool.
priority_icon = High-Priority Post
post_comment = Post Comment
delete_post_message = Are you sure you want to delete this post?
delete_comment_message = Are you sure you want to delete this comment?
Expand Down Expand Up @@ -68,3 +71,7 @@ Example URL: /direct/commons/rss/SITEID.json
# Menu
menu_main = Posts
permissions = Permissions

priority_email_subject = [{0} - Commons] New high-priority post
priority_email_added = A high-priority post was added to the Commons tool in the {0} site.
priority_email_forwarded = This forwarded message was sent by Isidore (<a href="https://isidore.udayton.edu/portal" >https://isidore.udayton.edu/portal</a>) via the Commons tool in the {0} site.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class Post implements Entity {
private String siteId;
private String commonsId;
private String url = "";
private boolean priority;

public Post() {

Expand All @@ -73,7 +74,7 @@ public Post(ResultSet rs) throws SQLException {
this.setSiteId(rs.getString("SITE_ID"));
this.setContent(rs.getString("CONTENT"));
this.setCreatorId(rs.getString("CREATOR_ID"));

this.setPriority(rs.getBoolean("PRIORITY"));
// retrieve time's in UTC since that's how it's stored
this.setCreatedDate(rs.getTimestamp("CREATED_DATE", Calendar.getInstance(TimeZone.getTimeZone(ZoneId.of("UTC")))).getTime());
this.setModifiedDate(rs.getTimestamp("MODIFIED_DATE", Calendar.getInstance(TimeZone.getTimeZone(ZoneId.of("UTC")))).getTime());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class PersistenceManagerImpl implements PersistenceManager {
private static final String COMMENT_UPDATE = "UPDATE COMMONS_COMMENT SET CONTENT = ?, MODIFIED_DATE = ? WHERE ID = ?";
private static final String COMMENT_DELETE = "DELETE FROM COMMONS_COMMENT WHERE ID = ?";
private static final String POST_UPDATE = "UPDATE COMMONS_POST SET CONTENT = ?, MODIFIED_DATE = ?, RELEASE_DATE = ? WHERE ID = ?";
private static final String POST_INSERT = "INSERT INTO COMMONS_POST VALUES (?,?,?,?,?,?)";
private static final String POST_INSERT = "INSERT INTO COMMONS_POST VALUES (?,?,?,?,?,?,?)";
private static final String POST_DELETE = "DELETE FROM COMMONS_POST WHERE ID = ?";
private static final String POST_LIKE = "INSERT INTO COMMONS_LIKE VALUES (?,?,?,?)";
private static final String LIKE_GET = "SELECT * FROM COMMONS_LIKE WHERE POST_ID = ? AND USER_ID=?";
Expand Down Expand Up @@ -229,7 +229,8 @@ public void run() {
, post.getCreatorId()
, new Timestamp(post.getCreatedDate())
, new Timestamp(post.getModifiedDate())
, new Timestamp(post.getReleaseDate())});
, new Timestamp(post.getReleaseDate())
, post.isPriority()});
sqlService.dbWrite(COMMONS_POST_INSERT
, new Object [] { post.getCommonsId(), post.getId() });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand All @@ -50,6 +51,7 @@
import org.sakaiproject.commons.api.datamodel.Post;
import org.sakaiproject.commons.api.datamodel.PostLike;
import org.sakaiproject.commons.api.datamodel.PostsData;
import org.sakaiproject.email.api.EmailService;
import org.sakaiproject.entitybroker.EntityReference;
import org.sakaiproject.entitybroker.EntityView;
import org.sakaiproject.entitybroker.entityprovider.annotations.EntityCustomAction;
Expand All @@ -64,6 +66,12 @@
import org.sakaiproject.entitybroker.entityprovider.extension.RequestGetter;
import org.sakaiproject.entitybroker.exception.EntityException;
import org.sakaiproject.entitybroker.util.AbstractEntityProvider;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.util.ResourceLoader;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -83,6 +91,10 @@ public class CommonsEntityProvider extends AbstractEntityProvider implements Req
private CommonsSecurityManager commonsSecurityManager;
private RequestGetter requestGetter;
private SakaiProxy sakaiProxy;
private EmailService emailService;
private SiteService siteService;
private UserDirectoryService userDirectoryService;
private static final ResourceLoader rl = new ResourceLoader("commons");

private final static List<String> contentTypes
= Arrays.asList("image/png", "image/jpg", "image/jpeg", "image/gif");
Expand Down Expand Up @@ -204,6 +216,7 @@ public ActionReturn handleSavePost(Map<String, Object> params) {
String siteId = (String) params.get("siteId");
String commonsId = (String) params.get("commonsId");
String embedder = (String) params.get("embedder");
boolean priority = Boolean.valueOf((String) params.get("priority"));

if (StringUtils.isBlank(content) || StringUtils.isBlank(siteId)
|| StringUtils.isBlank(commonsId) || StringUtils.isBlank(embedder)) {
Expand All @@ -226,6 +239,7 @@ public ActionReturn handleSavePost(Map<String, Object> params) {
post.setCommonsId(commonsId);
post.setEmbedder(embedder);
post.setContent(content);
post.setPriority(priority);
}

Post createdOrUpdatedPost = commonsManager.savePost(post);
Expand All @@ -234,6 +248,9 @@ public ActionReturn handleSavePost(Map<String, Object> params) {
sakaiProxy.postEvent(CommonsEvents.POST_CREATED,
createdOrUpdatedPost.getReference(),
createdOrUpdatedPost.getSiteId());
if(priority){ //send an email for a new priority post.
sendPriorityEmail(siteId, content);
}
} else {
sakaiProxy.postEvent(CommonsEvents.POST_UPDATED,
createdOrUpdatedPost.getReference(),
Expand Down Expand Up @@ -541,4 +558,32 @@ private String getCheckedUser() throws EntityException {
private String escape(String unescaped) {
return StringEscapeUtils.escapeJava(unescaped);
}

private void sendPriorityEmail(String siteId, String postContent){
try{
Set<String> siteUserIds = siteService.getSite(siteId).getUsers();
Set<User> siteUsers = new HashSet<>(); //will be list of users to email
for(String id: siteUserIds){
try{
siteUsers.add(userDirectoryService.getUser(id));
} catch (UserNotDefinedException u){
log.error("No user found with ID {} while sending Commons Priority email.", id);
}
}
List<String> headers = new ArrayList<>();
headers.add("Subject: " + rl.getFormattedMessage("priority_email_subject", siteService.getSite(siteId).getTitle()));
headers.add("From: " + "\"" + userDirectoryService.getCurrentUser().getDisplayName() + "\" <" + userDirectoryService.getCurrentUser().getEmail() + ">");
headers.add("Reply-To: " + userDirectoryService.getCurrentUser().getEmail());
headers.add("Content-Type: text/html");
StringBuilder messageText = new StringBuilder(); //make message body
messageText.append(rl.getFormattedMessage("priority_email_added", "<a href=\"" + siteService.getSite(siteId).getUrl() + "\" >" + siteService.getSite(siteId).getTitle() + "</a> "));
messageText.append("<br><br>" + postContent);
messageText.append("<br><br><hr><em>");
messageText.append(rl.getFormattedMessage("priority_email_forwarded", "<a href=\"" + siteService.getSite(siteId).getUrl() + "\" >" + siteService.getSite(siteId).getTitle() + "</a> "));
messageText.append("</em>");
emailService.sendToUsers(siteUsers, headers, messageText.toString());
} catch (IdUnusedException e){
log.error("Cannot send email; no site with ID {}", siteId);
}
}
}
3 changes: 3 additions & 0 deletions commons/tool/src/webapp/WEB-INF/applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
<property name="commonsManager"><ref bean="org.sakaiproject.commons.api.CommonsManager"/></property>
<property name="commonsSecurityManager"><ref bean="org.sakaiproject.commons.api.CommonsSecurityManager"/></property>
<property name="sakaiProxy"><ref bean="org.sakaiproject.commons.api.SakaiProxy"/></property>
<property name="emailService"><ref bean="org.sakaiproject.email.api.EmailService"/></property>
<property name="siteService"><ref bean="org.sakaiproject.site.api.SiteService"/></property>
<property name="userDirectoryService"><ref bean="org.sakaiproject.user.api.UserDirectoryService"/></property>
</bean>

</beans>
8 changes: 6 additions & 2 deletions commons/tool/src/webapp/WEB-INF/templates/post.hbs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<div id="commons-post-outer-container-{{id}}" class="commons-post-outer-container">

<div class="commons-post-inner-container">
<div class="commons-post-inner-container" id="commons-post-inner-container-{{id}}">

<div class="commons-photo" style="background-image:url(/direct/profile/{{creatorId}}/image/thumb)"></div>
<div class="commons-post-text-container">
<div class="commons-post-body">
<div class="commons-post-content"><a id="commons-author-name-{{id}}" class="commons-post-author-name profile-popup-trigger" data-user-id="{{creatorId}}" href="javascript:;">{{creatorDisplayName}}</a><span id="commons-post-content-{{id}}">{{{content}}}<span></div>
<div class="commons-post-content">
<span id="commons-high-priority-{{id}}" class="fa fa-flag commons-high-priority" title={{tr 'priority_icon'}} style="display:none;"></span>
<a id="commons-author-name-{{id}}" class="commons-post-author-name profile-popup-trigger" data-user-id="{{creatorId}}" href="javascript:;">{{creatorDisplayName}}</a>
<span id="commons-post-content-{{id}}">{{{content}}}<span>
</div>
<div id="commons-post-options-{{id}}" class="commons-post-options">
<span id="commons-like-section" >
<a href="javascript:;" id="commons-like-link-{{id}}" class="commons-like-link" data-post-id="{{id}}" >
Expand Down
6 changes: 6 additions & 0 deletions commons/tool/src/webapp/WEB-INF/templates/posts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
<button id="commons-editor-cancel-button" disabled="true">{{tr 'cancel'}}</button>
<button id="commons-editor-link-button" class="commons-editor-special-button" title="{{tr 'link_button_tooltip'}}"><span class="fa fa-link"></span></button>
<button id="commons-editor-image-button" class="commons-editor-special-button" title="{{tr 'image_button_tooltip'}}"><span class="fa fa-picture-o"></span></button>
<span id="commons-editor-priority-container" style="display:none;">
<input type="checkbox" id="commons-editor-priority" class="commons-editor-priority"></input>
<label for="commons-editor-priority" class="commons-editor-priority-label">{{tr 'priority'}}</label>
<a href="javascript://" data-toggle="popover" data-placement="top" data-trigger="focus" data-html="true" data-content="{{tr 'priorityHelp'}}" id="commons-editor-priority-help" class="fa fa-question-circle" ></a>
<br>
</span>
</div>
</div>

Expand Down
5 changes: 4 additions & 1 deletion commons/tool/src/webapp/js/commons.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@ commons.switchState = function (state, arg) {
commons.selectedText = (document.selection) ? sel.createRange().htmlText : sel.toString();
commons.currentRange = sel.getRangeAt(0);
});

if(commons.currentUserPermissions.postDeleteAny){ //if the user can delete any post, we will give them access to Hi-Priority posting too.
document.getElementById('commons-editor-priority-container').removeAttribute('style');
$('[data-toggle="popover"]').popover(); //we need the popover to work only when Hi-Priority is exposed.
}
editorPostButton.click(function (e) {

commons.utils.savePost('', editor.html(), function (post) {
Expand Down
11 changes: 8 additions & 3 deletions commons/tool/src/webapp/js/commons_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ commons.utils = {
savePost: function (postId, content, callback) {

var success = false;

var priority = document.getElementById('commons-editor-priority').checked;
document.getElementById('commons-editor-priority').checked = false; //uncheck the box by default, we have what we need from it already.
if (!postId) postId = '';

if ('' == content) {
Expand All @@ -296,7 +297,8 @@ commons.utils = {
'content': content,
'commonsId': commons.commonsId,
'siteId': commons.siteId,
'embedder': commons.embedder
'embedder': commons.embedder,
'priority': priority
};

$.ajax({
Expand Down Expand Up @@ -499,7 +501,10 @@ commons.utils = {
if (post.comments.length <= 3) {
showCommentsLink.hide();
}

if(post.priority === true){
document.getElementById('commons-post-inner-container-' + post.id).classList.add('alert-info');
document.getElementById('commons-high-priority-' + post.id).removeAttribute('style');
}
post.comments.forEach(function (c) { self.addHandlersToComment(c); });
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@

.commons-post-outer-container {
border-bottom: 1px solid var(--sakai-border-color);
margin-bottom: 20px;
margin-bottom: 10px;
}
.commons-post-inner-container{
margin: 5px;
padding: 5px;
overflow: auto;
}
.commons-post-body {
Expand Down Expand Up @@ -254,3 +254,15 @@
#commons-like-section {
margin-right: 1em;
}

.commons-editor-priority-label {
margin-top: 7px;
}

#commons-editor-priority-help {
text-decoration: none;
}

span.commons-high-priority {
float: right;
}

0 comments on commit e295237

Please sign in to comment.