1 of 23

Blackboard Portlet - UW Madison

2 of 23

Welcome

  1. Tim Vertein - University of Wisconsin Madison

  • uPortal committer

  • 4th leading committer on the blackboard project

3 of 23

Outline

  1. Welcome
  2. What is the black board portlet
  3. Technologies
  4. Demo
  5. Questions

4 of 23

Blackboard Portlet - Overview

  • Portlet Interface to Blackboard service
  • Users can create/edit sessions and manage participants
  • Users can access past recordings
  • Users can set Telephony

5 of 23

Technologies

  • Spring Forms
  • Spring Security
  • Datatables
  • Session Storage
  • Soap Web Services

6 of 23

Spring Forms

  • Models a form on a jsp to an object
  • Allows the form inputs to be linked to object fields
  • consuming objects become easier

7 of 23

Spring Forms - Object

  • private long sessionId;

private LocalTime startHourMinute;

private LocalTime endHourMinute;

  • We’re going to tell the jsp to use this

8 of 23

Spring Forms - Jsp

<form action="${saveSessionActionUrl}" method="post">

<%-- Using nestedPath as form:form does not work for portlets see: https://jira.springsource.org/browse/SPR-10382 --%>

<spring:nestedPath path="sessionForm">

<form:hidden path="sessionId"/>

<form:hidden path="newSession" />

<form:hidden path="needToSendInitialEmail" />

<form:input id="${n}startdatepicker" class="date start" path="startDate" style="width: 82px;"/>&nbsp;

...

9 of 23

Spring Forms - Controller

BlackboardVCPortlet / blackboardvc-portlet-webapp / src / main / java / org / jasig / portlet / blackboardvcportlet /mvc / sessionmngr / SessionCreateEditController.java

Blackboard example:

model.put("serverConfiguration", serverConfiguration);

if (!model.containsKey("sessionForm"))

{

SessionForm sessionForm = new SessionForm(serverConfiguration);

model.addAttribute("sessionForm", sessionForm);

}

return "createEditSession";

10 of 23

Spring - Security

  • Define validating function
  • Apply with Annotations spring security to methods:
  • Use with jsp

11 of 23

Spring Security - Context

BlackboardVCPortlet / blackboardvc-portlet-webapp / src / main / webapp / WEB-INF / context /securityContext.xml

<!--

| Setup role hierarchy to simplify hasRole checks

+-->

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">

<constructor-arg ref="roleHierarchy" />

</bean>

<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">

<property name="hierarchy">

<value>

ROLE_ADMIN > ROLE_FULL_ACCESS

</value>

</property>

</bean>

12 of 23

Spring Security - Annotate

/**

* A user needs "edit" to view the set of session chairs but we don't want the call to fail

* if they only have "view" permission. So we pre-auth them with view and then filter all

* the results unless they have "edit"

*/

@Override

@PreAuthorize("hasRole('ROLE_ADMIN') ")

public Set<ConferenceUser> getSessionChairs(Session session) {

return new LinkedHashSet<ConferenceUser>(sessionDao.getSessionChairs(session));

}

13 of 23

Spring Security - JSP

  • include.jsp
    • <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
  • BlackboardVCPortlet / blackboardvc-portlet-webapp / src / main / webapp / WEB-INF / jsp / viewSession.jsp

<sec:authorize access="hasRole('ROLE_ADMIN')">

<tr>

<td class="label">

<span class="uportal-channel-strong">

<spring:message code="moderatorLink" text="moderatorLink"/>

</span>

<br/>

<span class="uportal-channel-table-caption"><spring:message code="moderatorLinkDesc" text="moderatorLinkDesc"/></span>

</td>

<td><a href="${session.launchUrl}" target="_blank">${session.launchUrl}</a></td></tr>

</sec:authorize>

14 of 23

Datatables

  • https://datatables.net/
  • DataTables is a plug-in for the jQuery Javascript library. It is a highly flexible tool, based upon the foundations of progressive enhancement, and will add advanced interaction controls to any HTML table. (source https://datatables.net)
  • Presentation of data
  • Paginated
  • Search enables
  • Hidden columns
  • Sortables
  • Bootstrap integration

15 of 23

Datatables - How to Add

BlackboardVCPortlet / blackboardvc-portlet-webapp / src / main / webapp / WEB-INF / jsp /viewSessionsMax.jsp

<table width="100%" id="sessionList">

...

</table>

var futureTable = $('#sessionList').dataTable( {

"aaData": upcomingSessions,

"aaSorting": [[3, "desc"]],

...

});

16 of 23

Datatables - markup

<table id="Pluto_1596_n237_1160_portletTable" class="display table dataTable" aria-describedby="Pluto_1596_n237_1160_portletTable_info">

<thead>

<tr role="row"><th class="essential sorting_asc" style="border:none;" role="columnheader" tabindex="0" aria-controls="Pluto_1596_n237_1160_portletTable" rowspan="1" colspan="1" aria-sort="ascending" aria-label="

...

</tr></tbody></table>

17 of 23

Datatables - Screenshot

18 of 23

Datatables - Screenshot

19 of 23

Session Storage

  • Store small information in the browser
  • No need to go to server
  • Last only for the life of the browser tab

20 of 23

Session Storage - Use

BlackboardVCPortlet/blackboardvc-portlet-webapp/src/main/webapp/WEB-INF/jsp/viewSessionsNormal.jsp

<c:set var="n"><portlet:namespace /></c:set>

var currentWCPTab = "${n}"+"webConferencePortletTab";

$("#${n}tabs").tabs(

{

create: function(event, ui){

if(!sessionStorage.getItem(currentWCPTab)){

sessionStorage.setItem(currentWCPTab, 0);

}

},

active: sessionStorage.getItem(currentWCPTab),

activate: function(event, ui){

var currentTab = $("#${n}tabs").tabs("option", "active");

sessionStorage.setItem(currentWCPTab, currentTab);

}

} );

21 of 23

Soap Web Services

BlackboardVCPortlet / blackboardvc-portlet-webapp / src / main / java / org / jasig / portlet / blackboardvcportlet /dao / ws / impl / SessionWSDaoImpl.java

@Override

public boolean removeSessionTelephony(long sessionId) {

BlackboardSessionTelephony bst = new ObjectFactory().createBlackboardSessionTelephony();

bst.setSessionId(sessionId);

JAXBElement<BlackboardSessionTelephony> removeSessionTelephony = new ObjectFactory().createRemoveSessionTelephony(bst);

return WSDaoUtils.isSuccessful (sasWebServiceOperations.marshalSendAndReceiveToSAS("http://sas.elluminate.com/RemoveSessionTelephony", removeSessionTelephony));

}

22 of 23

Demo Time

23 of 23

Questions