Skip to content

Commit

Permalink
SAK-30461 Add bullhorns to portal (sakaiproject#3822)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianfish authored Feb 20, 2017
1 parent cbc895a commit eabdea2
Show file tree
Hide file tree
Showing 28 changed files with 1,430 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4674,3 +4674,22 @@
# Run the seed sites automatically on startup, this is mainly for the demo setup
# DEFAULT: false
#quartz.seedsites.autorun=true

# ###############################################################
# SAK-30461 Add academic and social alerts icons to portal topbar
#
# Set this to false to hide the bullhorn icons in the topbar and
# disable bullhorn event harvesting.
#
# true/false Defaults to true (on)
# ###############################################################
#portal.bullhorns.enabled=false

# ###############################################################
# SAK-30461 Add academic and social alerts icons to portal topbar
#
# Set this to the number of milliseconds between polls
#
# Defaults to 10000
# ###############################################################
#portal.bullhorns.poll.interval=5000
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**********************************************************************************
* $URL$
* $Id$
***********************************************************************************
*
* Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/

package org.sakaiproject.portal.api;

import java.util.List;

import org.sakaiproject.portal.beans.BullhornAlert;
import org.sakaiproject.tool.api.Placement;

/**
* Service for the bullhorn alerts at the top of the portal
*
* @author Adrian Fish <[email protected]>
*/
public interface BullhornService {

/**
* Used by the bullhorn alerts code
*/
public static final String ACADEMIC = "ACADEMIC";

/**
* Used by the bullhorn alerts code
*/
public static final String SOCIAL = "SOCIAL";

/**
* @param userId The user to retrieve the alert count for
* @return the number of current social alerts for the specified user
*/
public int getSocialAlertCount(String userId);

/**
* @param userId The user to retrieve alerts for
* @return the list of current social alerts for the specified user
*/
public List<BullhornAlert> getSocialAlerts(String userId);

/**
* @param userId The user to clear the alerts for
* @return boolean to indicate success
*/
public boolean clearAllSocialAlerts(String userId);

/**
* @param userId The user to retrieve the alert count for
* @return the number of current academic alerts for the specified user
*/
public int getAcademicAlertCount(String userId);

/**
* @param userId The user to retrieve alerts for
* @return the list of current academic alerts for the specified user
*/
public List<BullhornAlert> getAcademicAlerts(String userId);

/**
* @param userId The user to clear the alert for
* @param alertId The alert to clear
* @return boolean to indicate success
*/
public boolean clearBullhornAlert(String userId, long alertId);

/**
* @param userId The user to clear the alerts for
* @return boolean to indicate success
*/
public boolean clearAllAcademicAlerts(String userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.sakaiproject.portal.beans;

import java.sql.ResultSet;
import java.sql.SQLException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class BullhornAlert {

public long id = 0L;
public String from = "";
public String fromDisplayName = "";
public String to = "";
public String event = "";
public String ref = "";
public String title = "";
public String siteId = "";
public String siteTitle = "";
public String url = "";
public long eventDate = 0L;

public BullhornAlert() { }

public BullhornAlert(ResultSet rs) {

try {
id = rs.getLong("ID");
from = rs.getString("FROM_USER");
to = rs.getString("TO_USER");
event = rs.getString("EVENT");
ref = rs.getString("REF");
title = rs.getString("TITLE");
siteId = rs.getString("SITE_ID");
url = rs.getString("URL");
eventDate = rs.getTimestamp("EVENT_DATE").getTime();
} catch (SQLException sqle) {
log.error("Failed to build BullhornAlert from db record", sqle);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
class="org.sakaiproject.portal.entityprovider.PortalEntityProvider" init-method="init">
<property name="serverConfigurationService" ref="org.sakaiproject.component.api.ServerConfigurationService" />
<property name="sessionManager" ref="org.sakaiproject.tool.api.SessionManager" />
<property name="bullhornService" ref="org.sakaiproject.portal.api.BullhornService" />
<property name="profileConnectionsLogic" ref="org.sakaiproject.profile2.logic.ProfileConnectionsLogic" />
<property name="profileLogic" ref="org.sakaiproject.profile2.logic.ProfileLogic" />
<property name="profileLinkLogic" ref="org.sakaiproject.profile2.logic.ProfileLinkLogic" />
Expand Down
18 changes: 18 additions & 0 deletions portal/portal-impl/impl/src/bundle/bullhorns.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
wallPost = \u0020posted on your wall
statusUpdate = \u0020updated their status
postComment = \u0020commented on your post
friendRequest = \u0020sent you a friend request
friendConfirm = \u0020confirmed your friend request
commentCreated = \u0020commented on your post
message = \u0020sent you a message
accept = Accept
ignore = Ignore
view = View
clear = Clear
noAlerts = No alerts
announcement = \u0020added a new announcement "{0}" in "{1}"
assignmentCreated = \u0020created a new assignment "{0}" in "{1}"
assignmentSubmissionGraded = \u0020graded your submission for assignment "{0}" in "{1}"
clearAll = Clear All
unrecognisedAlert = Unrecognised alert
academicCommentCreated = \u0020commented on your post in "{0}"
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,13 @@ public void includeBottom(PortalRenderContext rcontext)
rcontext.put("bottomNavSakaiVersion", sakaiVersion);
rcontext.put("bottomNavServer", server);

boolean useBullhornAlerts = ServerConfigurationService.getBoolean("portal.bullhorns.enabled", true);
rcontext.put("useBullhornAlerts", useBullhornAlerts);
if (useBullhornAlerts) {
int bullhornAlertInterval = ServerConfigurationService.getInt("portal.bullhorns.poll.interval", 10000);
rcontext.put("bullhornsPollInterval", bullhornAlertInterval);
}

// SAK-25931 - Do not remove this from session here - removal is done by /direct
Session s = SessionManager.getCurrentSession();
String userWarning = (String) s.getAttribute("userWarning");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;
import java.util.HashMap;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.Template;
Expand Down Expand Up @@ -40,6 +39,8 @@
import org.sakaiproject.tool.api.SessionManager;
import org.sakaiproject.util.ResourceLoader;

import org.sakaiproject.portal.api.BullhornService;
import org.sakaiproject.portal.beans.BullhornAlert;
import org.sakaiproject.portal.beans.PortalNotifications;

import lombok.Setter;
Expand All @@ -56,6 +57,12 @@ public class PortalEntityProvider extends AbstractEntityProvider implements Auto
public final static String PREFIX = "portal";
public final static String TOOL_ID = "sakai.portal";

@Setter
private BullhornService bullhornService;

@Setter
private SessionManager sessionManager;

@Setter
private ProfileConnectionsLogic profileConnectionsLogic;

Expand All @@ -68,9 +75,6 @@ public class PortalEntityProvider extends AbstractEntityProvider implements Auto
@Setter
private ServerConfigurationService serverConfigurationService;

@Setter
private SessionManager sessionManager;

private Template formattedProfileTemplate = null;

public void init() {
Expand Down Expand Up @@ -123,6 +127,104 @@ public PortalNotifications handleNotify(EntityView view) {
return noti;
}

private ActionReturn getBullhornAlerts(List<BullhornAlert> alerts) {

ResourceLoader rl = new ResourceLoader("bullhorns");

if (alerts.size() > 0) {
Map<String, Object> data = new HashMap();
data.put("alerts", alerts);
data.put("i18n", rl);

return new ActionReturn(data);
} else {
Map<String, String> i18n = new HashMap();
i18n.put("noAlerts", rl.getString("noAlerts"));

Map<String, Object> data = new HashMap();
data.put("message", "NO_ALERTS");
data.put("i18n", i18n);

return new ActionReturn(data);
}
}

@EntityCustomAction(action = "socialAlerts", viewKey = EntityView.VIEW_LIST)
public ActionReturn getSocialAlerts(EntityView view) {
return getBullhornAlerts(bullhornService.getSocialAlerts(getCheckedCurrentUser()));
}

@EntityCustomAction(action = "clearBullhornAlert", viewKey = EntityView.VIEW_LIST)
public boolean clearBullhornAlert(Map<String, Object> params) {

String currentUserId = getCheckedCurrentUser();

try {
long alertId = Long.parseLong((String) params.get("id"));
return bullhornService.clearBullhornAlert(currentUserId, alertId);
} catch (Exception e) {
log.error("Failed to clear social alert", e);
}

return false;
}

@EntityCustomAction(action = "clearAllSocialAlerts", viewKey = EntityView.VIEW_LIST)
public boolean clearAllSocialAlerts(Map<String, Object> params) {

String currentUserId = getCheckedCurrentUser();

try {
return bullhornService.clearAllSocialAlerts(currentUserId);
} catch (Exception e) {
log.error("Failed to clear all social alerts", e);
}

return false;
}

@EntityCustomAction(action = "academicAlerts", viewKey = EntityView.VIEW_LIST)
public ActionReturn getAcademicAlerts(EntityView view) {
return getBullhornAlerts(bullhornService.getAcademicAlerts(getCheckedCurrentUser()));
}

@EntityCustomAction(action = "clearAllAcademicAlerts", viewKey = EntityView.VIEW_LIST)
public boolean clearAllAcademicAlerts(Map<String, Object> params) {

String currentUserId = getCheckedCurrentUser();

try {
return bullhornService.clearAllAcademicAlerts(currentUserId);
} catch (Exception e) {
log.error("Failed to clear all academic alerts", e);
}

return false;
}

@EntityCustomAction(action = "bullhornCounts", viewKey = EntityView.VIEW_LIST)
public ActionReturn getBullhornCounts(EntityView view) {

String currentUserId = getCheckedCurrentUser();

Map<String, Integer> counts = new HashMap();
counts.put("academic", bullhornService.getAcademicAlertCount(currentUserId));
counts.put("social", bullhornService.getSocialAlertCount(currentUserId));

return new ActionReturn(counts);
}

private String getCheckedCurrentUser() throws SecurityException {

String currentUserId = developerHelperService.getCurrentUserId();

if (StringUtils.isBlank(currentUserId)) {
throw new SecurityException("You must be logged in to use this service");
} else {
return currentUserId;
}
}

@EntityCustomAction(action="formatted",viewKey=EntityView.VIEW_SHOW)
public ActionReturn getFormattedProfile(EntityReference ref) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@

</div> ## END: Mrphs-container Mrphs-container--extras
<div id="tutorial" class="Mrphs-tutorial Mrphs-modal"></div>
<div id="social-alerts" class="Mrphs-tutorial Mrphs-modal"></div>

#else

<!-- dont compact -->

#end ## END of IF (!$pagepopup)

</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
#end

#if (${userIsLoggedIn})
#if (${useBullhornAlerts})
<div class="Mrphs-sitesNav__menuitem portal-bullhorns-buttons">
<a id="Mrphs-academic-bullhorn" href="javascript:void(0);"><span class="icon-sakai--academic-bullhorn"></span></a>
<a id="Mrphs-social-bullhorn" href="javascript:void(0);"><span class="icon-sakai--social-bullhorn"></span></a>
</div>
#end
<div class="Mrphs-sitesNav__menuitem view-all-sites-btn">
<a href="javascript:void(0);" title="${rloader.sit_allsites}" role="menuitem" aria-haspopup="true">
<i class="fa fa-th all-sites-icon"></i> <span class="all-sites-label">${rloader.sit_worksites}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@
<link href="${pageScriptPath}jquery/qtip/jquery.qtip-latest.min.css$!{portalCDNQuery}" rel="stylesheet">
<link href="${pageWebjarsPath}pnotify/2.1.0/pnotify.core.min.css$!{portalCDNQuery}" rel="stylesheet">
<script src="${pageSkinRepo}/${pageSkin}/js/lib/modernizr.js$!{portalCDNQuery}"></script>
#if ($useBullhornAlerts)
<script src="/profile2-tool/javascript/profile2-eb.js$!{portalCDNQuery}"></script>
<script src="${pageWebjarsPath}momentjs/2.11.1/min/moment-with-locales.min.js$!{portalCDNQuery}"></script>
#end

<script> ## Include this at the top so tool markup and headscripts.js can use it
## SAK-16484 Allow Javascript to easily get at user details.
## SAK-13987, SAK-16162, SAK-19132 - Portal Logout Timer
var portal = {
"bullhorns": {
"enabled": $!{useBullhornAlerts},
"pollInterval": $!{bullhornsPollInterval}
},
"chat": {
"enabled": $!{neoChat},
"pollInterval": $!{portalChatPollInterval},
"video" : {
"enabled": $!{neoChatVideo}
}
"video" : {
"enabled": $!{neoChatVideo}
}
},
"loggedIn": $!{loggedIn},
"portalPath": "$!{portalPath}",
Expand Down
Loading

0 comments on commit eabdea2

Please sign in to comment.