Skip to content

Commit

Permalink
LSNBLDR-701 created Lessons component to show latest announcements. (s…
Browse files Browse the repository at this point in the history
…akaiproject#3106)

Added new dialog for Announcements in ShowPage.html ,related variables
and function are added in 'SimplePageBean.java' to create/edit
SimplePageItem of type ANNOUNCEMENTS for Announcements summary widget.
'messages.properties' is edited to add new texts.

For merged announcements, if user has no access to the site get public
messages from the site.Added method 'getMessagesPublic' to fetch all
public messages from the channel.
  • Loading branch information
ouit0408 authored and clhedrick committed Aug 1, 2016
1 parent f01cc60 commit 4cbc1a8
Show file tree
Hide file tree
Showing 10 changed files with 349 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public class AnnouncementEntityProviderImpl extends AbstractEntityProvider imple
private static final String MOTD_CHANNEL_SUFFIX = "motd";
public static int DEFAULT_NUM_ANNOUNCEMENTS = 3;
public static int DEFAULT_DAYS_IN_PAST = 10;
private static final long MILLISECONDS_IN_DAY = (24 * 60 * 60 * 1000);
private static final Logger log = LoggerFactory.getLogger(AnnouncementEntityProviderImpl.class);
private static ResourceLoader rb = new ResourceLoader("announcement");

Expand Down Expand Up @@ -224,6 +225,17 @@ private List<?> getAnnouncements(String siteId, Map<String,Object> params, boole
announcements.addAll(announcementService.getMessages(channel, t, numberOfAnnouncements, true, false, onlyPublic));
} catch (PermissionException e) {
log.warn("User: " + currentUserId + " does not have access to view the announcement channel: " + channel + ". Skipping...");
//user may not have access to view the channel but get all public messages in this channel
AnnouncementChannel announcementChannel = (AnnouncementChannel)announcementService.getChannelPublic(channel);
if(announcementChannel != null){
List<Message> publicMessages = announcementChannel.getMessagesPublic(null, true);
for(Message message : publicMessages){
//Add message only if it is within the time range
if(isMessageWithinPastNDays(message, numberOfDaysInThePast)){
announcements.add(message);
}
}
}
}
}

Expand Down Expand Up @@ -263,6 +275,18 @@ private List<?> getAnnouncements(String siteId, Map<String,Object> params, boole
return decoratedAnnouncements;
}

/**
* Checks if the given message was posted in the last N days, where N is the value of the maxDaysInPast
* @param message
* @param numberOfDaysInPast
* @return
*/
private boolean isMessageWithinPastNDays(Message message, int numberOfDaysInPast){
long timeDeltaMSeconds = timeService.newTime().getTime() - message.getHeader().getDate().getTime();
long numDays = timeDeltaMSeconds / MILLISECONDS_IN_DAY;
return (numDays <= numberOfDaysInPast);
}


private DecoratedAnnouncement createDecoratedAnnouncement(AnnouncementMessage a, String siteTitle) {
String reference = a.getReference();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public interface SimplePageItem {
public static final int QUESTION = 11;
public static final int BLTI = 12;
public static final int PEEREVAL = 13;
//new SimplePageItem type added to display latest announcements in Lessons
public static final int ANNOUNCEMENTS = 17;
public static final int BREAK = 14;
public static final int CHECKLIST = 15;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ public enum Status {
public static final String LESSONBUILDER_PATH = "lessonbuilder.path";
public static final String LESSONBUILDER_BACKPATH = "lessonbuilder.backpath";
public static final String LESSONBUILDER_ID = "sakai.lessonbuildertool";
public static final String ANNOUNCEMENTS_TOOL_ID = "sakai.announcements";


private static String PAGE = "simplepage.page";
Expand Down Expand Up @@ -292,6 +293,9 @@ public enum Status {
private Date peerEvalDueDate;
private Date peerEvalOpenDate;
private boolean peerEvalAllowSelfGrade;
//variables used for announcements widget
private String announcementsHeight;
private String announcementsDropdown;

// almost ISO format. real thing can't be done until Java 7. uses -0400 rather than -04:00
// SimpleDateFormat isoDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Expand Down Expand Up @@ -934,6 +938,12 @@ public void setWebsite(boolean isWebsite) {
public void setCaption(boolean isCaption) {
this.isCaption = isCaption;
}
public void setAnnouncementsHeight(String announcementsHeight) {
this.announcementsHeight = announcementsHeight;
}
public void setAnnouncementsDropdown(String announcementsDropdown) {
this.announcementsDropdown = announcementsDropdown;
}

// hibernate interposes something between us and saveItem, and that proxy gets an
// error after saveItem does. Thus we never see any value that saveItem might
Expand Down Expand Up @@ -7782,6 +7792,36 @@ public String addPeerEval() {
return "success";
}

/**
* To add latest announcements in a div in Lessons page
* @return status
*/
public String addAnnouncements(){
if (!itemOk(itemId))
return "permission-failed";
if (!checkCsrf())
return "permission-failed";
String status = "success";
if (canEditPage()) {
SimplePageItem item;
if (itemId != null && itemId != -1) {
//existing item, need to update
item = findItem(itemId);
}else{
//new item ,add it
item = appendItem("", "", SimplePageItem.ANNOUNCEMENTS);
}
//setting height in the item attribute
item.setAttribute("height", announcementsHeight);
item.setAttribute("numberOfAnnouncements", announcementsDropdown);
item.setPrerequisite(this.prerequisite);
setItemGroups(item, selectedGroups);
update(item);
}else{
status = "cancel";
}
return status;
}
public String savePeerEvalResult() {

String userId = getCurrentUserId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,7 @@ public int compare(SimpleStudentPage o1, SimpleStudentPage o2) {
|| i.getType() == SimplePageItem.COMMENTS || i.getType() == SimplePageItem.STUDENT_CONTENT
|| i.getType() == SimplePageItem.QUESTION || i.getType() == SimplePageItem.PEEREVAL
|| i.getType() == SimplePageItem.CHECKLIST
|| i.getType() == SimplePageItem.BREAK);
|| i.getType() == SimplePageItem.BREAK || i.getType() == SimplePageItem.ANNOUNCEMENTS );
// (i.getType() == SimplePageItem.PAGE &&
// "button".equals(i.getFormat())))

Expand Down Expand Up @@ -1273,6 +1273,7 @@ public int compare(SimpleStudentPage o1, SimpleStudentPage o2) {
case SimplePageItem.QUESTION: itemClassName = "question"; break;
case SimplePageItem.BLTI: itemClassName = "bltiType"; break;
case SimplePageItem.PEEREVAL: itemClassName = "peereval"; break;
case SimplePageItem.ANNOUNCEMENTS: itemClassName = "announcementsType"; break;
case SimplePageItem.CHECKLIST: itemClassName = "checklistType"; break;
}

Expand Down Expand Up @@ -2783,6 +2784,46 @@ public int compare(SimpleStudentPage o1, SimpleStudentPage o2) {
UIOutput.make(tableRow, "student-group-owned-see-only-own", (i.getAttribute("see-only-own")));
}
}
}else if(i.getType() == SimplePageItem.ANNOUNCEMENTS){
UIOutput.make(tableRow, "announcementsSpan");
String itemGroupString = null;
String itemGroupTitles = null;
if (canSeeAll) {
itemGroupString = simplePageBean.getItemGroupString(i, null, true);
if (itemGroupString != null)
itemGroupTitles = simplePageBean.getItemGroupTitles(itemGroupString, i);
if (itemGroupTitles != null) {
itemGroupTitles = "[" + itemGroupTitles + "]";
}
if (canEditPage)
UIOutput.make(tableRow, "item-groups", itemGroupString);
if (itemGroupTitles != null)
UIOutput.make(tableRow, "announcements-groups-titles", itemGroupTitles);
}
if(canSeeAll || simplePageBean.isItemAvailable(i)) {
//get widget height from the item attribute
String height = i.getAttribute("height") != null ? i.getAttribute("height") : "" ;
//create html for announcements widget
String divHeight = "height:" + height +"px;";
String html = "<div align=\"left\" style='"+divHeight+"' class=\"announcements-div\"></div>";
UIVerbatim.make(tableRow, "content", html);
UIOutput.make(tableRow, "announcements-id", String.valueOf(i.getId()));
UIOutput.make(tableRow, "announcements-widget-height", height);
//setting announcements url to get all announcements for the site
UIOutput.make(tableRow, "announcements-site-url", myUrl() + "/direct/announcement/site/" + simplePageBean.getCurrentSiteId());
//setting this variable to redirect user to the particular announcement
UIOutput.make(tableRow, "announcements-view-url", myUrl() + "/portal/directtool/" + simplePageBean.getCurrentTool(simplePageBean.ANNOUNCEMENTS_TOOL_ID) + "?itemReference=/announcement/msg/" + simplePageBean.getCurrentSiteId() + "/main/");
//get numberOfAnnouncements for the widget
String numberOfAnnouncements = i.getAttribute("numberOfAnnouncements") != null ? i.getAttribute("numberOfAnnouncements") : "";
UIOutput.make(tableRow, "numberOfAnnouncements", numberOfAnnouncements);
}else{
UIComponent unavailableText = UIOutput.make(tableRow, "content", messageLocator.getMessage("simplepage.textItemUnavailable"));
unavailableText.decorate(new UIFreeAttributeDecorator("class", "disabled-text-item"));
}
if (canEditPage) {
UIOutput.make(tableRow, "announcements-td");
UILink.make(tableRow, "edit-announcements", (String) null, "");
}
}else if(i.getType() == SimplePageItem.QUESTION) {
String itemGroupString = null;
String itemGroupTitles = null;
Expand Down Expand Up @@ -3181,6 +3222,7 @@ public void createDialogs(UIContainer tofill, SimplePage currentPage, SimplePage
createStudentContentDialog(tofill, currentPage);
createQuestionDialog(tofill, currentPage);
createDeleteItemDialog(tofill, currentPage);
createAnnouncementsDialog(tofill, currentPage);
createColumnDialog(tofill, currentPage);
}

Expand Down Expand Up @@ -3685,7 +3727,10 @@ private void createToolBar(UIContainer tofill, SimplePage currentPage, boolean i
// A: Not sure
log.warn("SecurityException thrown by expandZippedResource method lookup", e);
}

//Adding 'Embed Announcements' component
UIOutput.make(tofill, "announcements-li");
UILink announcementsLink = UIInternalLink.makeURL(tofill, "announcements-link", "#");
announcementsLink.decorate(new UITooltipDecorator(messageLocator.getMessage("simplepage.announcements-descrip")));
UIOutput.make(tofill, "assignment-li");
createToolBarLink(AssignmentPickerProducer.VIEW_ID, tofill, "add-assignment", "simplepage.assignment-descrip", currentPage, "simplepage.assignment");

Expand Down Expand Up @@ -3965,7 +4010,30 @@ public void createGroupList(UIContainer tofill, Collection<String> groupsSet, St
}

}

//To display dialog to add Announcements widget in Lessons
private void createAnnouncementsDialog(UIContainer tofill, SimplePage currentPage){
UIOutput.make(tofill, "add-announcements-dialog").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.announcementsLinkText")));
UIForm form = UIForm.make(tofill, "add-announcements-form");
makeCsrf(form, "csrf23");
//check if site has announcements tool added?if not then display info and return
if(simplePageBean.getCurrentTool(simplePageBean.ANNOUNCEMENTS_TOOL_ID) == null){
UIOutput.make(tofill, "announcements-error-div");
UIOutput.make(tofill, "announcements-error-span", messageLocator.getMessage("simplepage.no_announcements_tool"));
UICommand.make(form, "announcements-cancel", messageLocator.getMessage("simplepage.cancel"), null);
UICommand.make(form, "delete-announcements-item", messageLocator.getMessage("simplepage.delete"), "#{simplePageBean.deleteItem}");
return;
}
UIInput.make(form, "announcementsEditId", "#{simplePageBean.itemId}");
UIInput.make(form, "announcements-height", "#{simplePageBean.announcementsHeight}");
UIOutput.make(form, "announcements-height-label", messageLocator.getMessage("simplepage.announcements.height_label"));
String[] options = {"5","10","15","20","30","50"};
String[] labels = {"5","10","15","20","30","50"};
UIOutput.make(form, "announcementsNumberDropdownLabel", messageLocator.getMessage("simplepage.announcements-number-dropdown-label"));
UISelect.make(form, "announcementsNumberDropdown", options, labels, "#{simplePageBean.announcementsDropdown}","5");
UICommand.make(form, "announcements-add-item", messageLocator.getMessage("simplepage.save_message"), "#{simplePageBean.addAnnouncements}");
UICommand.make(form, "announcements-cancel", messageLocator.getMessage("simplepage.cancel"), null);
UICommand.make(form, "delete-announcements-item", messageLocator.getMessage("simplepage.delete"), "#{simplePageBean.deleteItem}");
}
// for both add multimedia and add resource, as well as updating resources
// in the edit dialogs
private void createAddMultimediaDialog(UIContainer tofill, SimplePage currentPage) {
Expand Down
9 changes: 9 additions & 0 deletions lessonbuilder/tool/src/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -712,5 +712,14 @@ simplepage.defaultTitle=Lessons

simplepage.indent.level = Indent level
simplepage.custom.css.class = Custom CSS class
simplepage.announcementsLinkText=Embed Announcements
simplepage.announcements-descrip=Display latest announcements
simplepage.no_announcements_tool=There is no Announcements tool in the site.
simplepage.announcements.height_label=Height of display box (in pixels)
simplepage.announcements-number-dropdown-label=Specify number of announcements
simplepage.edit-title.announcements=Edit Announcements
simplepage.announcements-no-message=There are currently no announcements
simplepage.announcements-error-message=Error in adding announcements:
simplepage.announcements-header-title=Announcements


3 changes: 3 additions & 0 deletions lessonbuilder/tool/src/webapp/WEB-INF/applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ simplePageBean.width,
simplePageBean.youtubeId,
simplePageBean.youtubeURL,
simplePageBean.selectPage,
simplePageBean.announcementsHeight,
simplePageBean.announcementsDropdown,
simplePageBean.addAnnouncements,
simplePageBean.peerEval,
simplePageBean.peerEvalDueDate,
simplePageBean.peerEvalOpenDate,
Expand Down
34 changes: 34 additions & 0 deletions lessonbuilder/tool/src/webapp/css/Simplepagetool.css
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,36 @@ div[role="dialog"] {
.right-col3 {
left:10px;
}
.announcements-div{
border: 1px solid #ccc;
float: left;
margin: 30px 10px 30px 0;
overflow-y: scroll;
text-align: left;
background-color: #fff;
width: 550px;
}
.announcementsHeaderDiv{
position: relative;
width: 100.0%;
max-height: 240.0px;
vertical-align: top;
overflow: hidden;
background-color: #eee;
}
.announcementSummaryHeader{
font-family: 'Segoe UI', Segoe, Tahoma, Helvetica, Arial, sans-serif;
border-bottom:1px solid #ccc;
padding: 10px 0px 10px 15px;
font-size: 1.2em;
letter-spacing: normal
}
.announcementLink{
margin-left: 5px;
}
.itemDiv {
padding: 10px 15px 0 15px
}
.returnwarning, .returnheader, .xMrphs-toolTitleNav__addLeft .usebutton span {
font-size: .75em;
}
Expand Down Expand Up @@ -1515,6 +1545,10 @@ font-size: 90%;
}

/* for ShowItem */
.itemDate {
font-family: 'Segoe UI', Segoe, Tahoma, Helvetica, Arial, sans-serif;
font-size: 12px;
}
.itemHeader {
}
.itemHeader-resource {
Expand Down
57 changes: 57 additions & 0 deletions lessonbuilder/tool/src/webapp/js/announcements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
$(function(){
//get all divs with class announcementType
$(".announcements-div").each(function(){
var rightColDiv = $(this).parent().parent();
//Get parameters for each announcements div
var number = rightColDiv.find('.numberOfAnnouncements').text().replace(/'/g,"");
var url = rightColDiv.find(".announcements-site-url").text().replace(/'/g,"");
var tool_href = rightColDiv.find(".announcements-view-url").text().replace(/'/g,"");
showAnnouncements(url, tool_href, number, $(this));
});
});

function showAnnouncements(url, tool_href, number, announcementsDiv){
//only make ajax request if announcement widget is added
if(url.length){
var announcementsUrl = url + ".json?n=" + number;
//get the announcement tool url
var link_to_tool = tool_href.split("?", 1);
var title = msg("simplepage.announcements-header-title");
var text_for_announcements = '<div class="announcementsHeaderDiv"><h3 class="announcementSummaryHeader"><span aria-hidden="true" class="fa-item-text icon-sakai-announcements"></span><a href="'+link_to_tool+'" target="_top" class="announcementLink" title ="'+title+'">'+title+'</a></h3></div>';
//Get announcements
$.ajax({
url: announcementsUrl,
dataType: 'json',
cache: false,
success: function(data) {
if($(data["announcement_collection"]).size() === 0) {
//ie no announcements
text_for_announcements += '<p>'+msg("simplepage.announcements-no-message")+'</p>';
}
else {
$(data["announcement_collection"]).each(function(){
//create a new javascript Date object based on the timestamp
date = new Date(this["createdOn"]);
var hour = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
var min = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
//using javascript's toLocaleDateString() to include user's locale and local time zone
date_time = hour +":"+min+ " " + date.toLocaleDateString();
text_for_announcements += '<div class="itemDiv">';
var href = tool_href + this["announcementId"]+"&sakai_action=doShowmetadata";
var entityTitle = this["entityTitle"].replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
var createdByDisplayName = this["createdByDisplayName"].replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
text_for_announcements += '<div class="itemTitle"><a href="'+href+'" target="_top">'+ entityTitle +'</a> by '+ createdByDisplayName +'</div>';
text_for_announcements += '<div class="itemDate">'+date_time+'</div>';
text_for_announcements += '</div>';
});
}
announcementsDiv.html(text_for_announcements);
},
error: function(xhr, textStatus, errorThrown){
var err = textStatus + ", " + errorThrown;
text_for_announcements += '<p>'+ msg("simplepage.announcements-error-message") + err +'</p>';
announcementsDiv.html(text_for_announcements);
}
});
}
}
Loading

0 comments on commit 4cbc1a8

Please sign in to comment.