Skip to content

Commit 8224456

Browse files
committedJul 2, 2015
SAK-29637: add ability to User Membership to bulk change status
1 parent 32a378c commit 8224456

File tree

5 files changed

+322
-37
lines changed

5 files changed

+322
-37
lines changed
 

‎usermembership/tool/src/bundle/org/sakaiproject/umem/tool/bundle/Messages.properties

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ bar_input_search_title=Enter User Name, ID or Email Address to Search For.
99
bar_search=Search
1010
bar_clear_search=Clear search
1111
instructions_userlist=Select a user from the search results to get site and group membership.
12-
instructions_sitelist=Site and group membership for selected user.
12+
instructions_sitelist=Site and group membership for the selected user.
1313
unauthorized=You are not authorized to use this tool. This incident will be reported.
1414
processing=Processing user memberships...
1515
no_enrollments=No users to display
@@ -53,3 +53,13 @@ user_type_none=(no type)
5353
user_auth_all=All
5454
user_auth_internal=Internal
5555
user_auth_external=External
56+
57+
## SAK-29637
58+
set_to_inactive_button=Set Selected to Inactive
59+
set_to_active_button=Set Selected to Active
60+
invert_selection=Invert Selection
61+
select_all=Select All
62+
deselect_all=Deselect All
63+
export_selected_to_csv=Export Selected to CSV
64+
export_selected_to_excel=Export Selected to Excel
65+
actions_header=Actions

‎usermembership/tool/src/java/org/sakaiproject/umem/tool/ui/SiteListBean.java

+126-24
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@
4242
import javax.faces.context.ExternalContext;
4343
import javax.faces.context.FacesContext;
4444
import javax.faces.event.ActionEvent;
45+
import org.apache.commons.lang.StringUtils;
4546

4647
import org.apache.commons.logging.Log;
4748
import org.apache.commons.logging.LogFactory;
49+
import org.sakaiproject.authz.api.AuthzGroup;
50+
import org.sakaiproject.authz.api.AuthzGroupService;
51+
import org.sakaiproject.authz.api.AuthzPermissionException;
52+
import org.sakaiproject.authz.api.GroupNotDefinedException;
4853
import org.sakaiproject.authz.api.Role;
4954
import org.sakaiproject.component.api.ServerConfigurationService;
5055
import org.sakaiproject.component.cover.ComponentManager;
@@ -59,8 +64,8 @@
5964
import org.sakaiproject.tool.api.SessionManager;
6065
import org.sakaiproject.tool.api.ToolManager;
6166
import org.sakaiproject.umem.api.Authz;
67+
import org.sakaiproject.user.api.UserDirectoryService;
6268
import org.sakaiproject.user.api.UserNotDefinedException;
63-
import org.sakaiproject.user.cover.UserDirectoryService;
6469
import org.sakaiproject.util.ResourceLoader;
6570

6671

@@ -82,7 +87,7 @@ public class SiteListBean {
8287
/** Resource bundle */
8388
private transient ResourceLoader msgs = new ResourceLoader("org.sakaiproject.umem.tool.bundle.Messages");
8489
/** Controller fields */
85-
private List userSitesRows;
90+
private List<UserSitesRow> userSitesRows;
8691
/** Getter vars */
8792
private boolean refreshQuery = false;
8893
private boolean allowed = false;
@@ -98,13 +103,21 @@ public class SiteListBean {
98103
private SiteService M_site = (SiteService) ComponentManager.get(SiteService.class.getName());
99104
private ToolManager M_tm = (ToolManager) ComponentManager.get(ToolManager.class.getName());
100105
private Authz authz = (Authz) ComponentManager.get(Authz.class.getName());
106+
private AuthzGroupService authzGroupService = (AuthzGroupService) ComponentManager.get( AuthzGroupService.class.getName() );
107+
private UserDirectoryService userDirectoryService= (UserDirectoryService) ComponentManager.get( UserDirectoryService.class.getName() );
101108
private ServerConfigurationService M_scf = (ServerConfigurationService) ComponentManager.get(ServerConfigurationService.class.getName());
102109
/** Private vars */
103110
private RuleBasedCollator collator;
104111
private long timeSpentInGroups = 0;
105112
private String portalURL = M_scf.getPortalUrl();
106113
private String message = "";
107114

115+
private final static String frameID = "Main" + org.sakaiproject.tool.cover.ToolManager.getCurrentPlacement().getId().replaceAll( "[-!~]", "x" );
116+
public static String getFrameID()
117+
{
118+
return frameID;
119+
}
120+
108121
// ######################################################################################
109122
// UserSitesRow CLASS
110123
// ######################################################################################
@@ -121,6 +134,7 @@ public class UserSitesRow implements Serializable {
121134
private String pubView;
122135
private String userStatus;
123136
private String siteTerm;
137+
private boolean selected;
124138

125139
{
126140
try{
@@ -130,6 +144,7 @@ public class UserSitesRow implements Serializable {
130144
}
131145
}
132146
public UserSitesRow() {
147+
this.selected = false;
133148
}
134149

135150
public UserSitesRow(String siteId, String siteTitle, String siteType, String groups, String roleName, String pubView, String userStatus, String term) {
@@ -141,6 +156,7 @@ public UserSitesRow(String siteId, String siteTitle, String siteType, String gro
141156
this.pubView = pubView;
142157
this.userStatus = userStatus;
143158
this.siteTerm = term;
159+
this.selected = false;
144160
}
145161

146162
public UserSitesRow(Site site, String groups, String roleName) {
@@ -152,6 +168,7 @@ public UserSitesRow(Site site, String groups, String roleName) {
152168
this.pubView = site.isPublished() ? msgs.getString("status_published") : msgs.getString("status_unpublished");
153169
this.userStatus = site.getMember(userId).isActive() ? msgs.getString("site_user_status_active") : msgs.getString("site_user_status_inactive");
154170
this.siteTerm = site.getProperties().getProperty(PROP_SITE_TERM);
171+
this.selected = false;
155172
}
156173

157174
public String getSiteId() {
@@ -193,7 +210,14 @@ public String getUserStatus(){
193210
public String getSiteTerm() {
194211
return siteTerm;
195212
}
196-
213+
214+
public boolean isSelected() {
215+
return selected;
216+
}
217+
218+
public void setSelected( boolean selected ) {
219+
this.selected = selected;
220+
}
197221
}
198222

199223
public static final Comparator getUserSitesRowComparator(final String fieldName, final boolean sortAscending, final Collator collator) {
@@ -283,7 +307,7 @@ public String getInitValues() {
283307
* @throws SQLException
284308
*/
285309
private void doSearch() throws SQLException {
286-
userSitesRows = new ArrayList();
310+
userSitesRows = new ArrayList<>();
287311
Connection c = null;
288312
PreparedStatement pst = null;
289313
ResultSet rs = null;
@@ -346,7 +370,7 @@ private void doSearch() throws SQLException {
346370
*/
347371
private void doSearch2() throws SQLException {
348372
long start = (new Date()).getTime();
349-
userSitesRows = new ArrayList();
373+
userSitesRows = new ArrayList<>();
350374
thisUserId = M_session.getCurrentSessionUserId();
351375
setSakaiSessionUser(userId);
352376
LOG.debug("Switched CurrentSessionUserId: " + M_session.getCurrentSessionUserId());
@@ -371,7 +395,7 @@ private void doSearch2() throws SQLException {
371395
* @deprecated
372396
*/
373397
private void doSearch3() throws SQLException {
374-
userSitesRows = new ArrayList();
398+
userSitesRows = new ArrayList<>();
375399
timeSpentInGroups = 0;
376400
Connection c = null;
377401
PreparedStatement pst = null;
@@ -538,7 +562,7 @@ public List getUserSitesRows() {
538562
return userSitesRows;
539563
}
540564

541-
public void setUserSitesRows(List userRows) {
565+
public void setUserSitesRows(List<UserSitesRow> userRows) {
542566
this.userSitesRows = userRows;
543567
}
544568

@@ -551,9 +575,9 @@ public boolean isRenderTable() {
551575
}
552576

553577
public String getUserDisplayId() {
554-
String displayId = null;
578+
String displayId;
555579
try{
556-
displayId = UserDirectoryService.getUser(userId).getDisplayId();
580+
displayId = userDirectoryService.getUser(userId).getDisplayId();
557581
}catch(UserNotDefinedException e){
558582
displayId = userId;
559583
}
@@ -580,6 +604,80 @@ public void setSitesSortColumn(String sitesSortColumn) {
580604
this.sitesSortColumn = sitesSortColumn;
581605
}
582606

607+
/**
608+
* SAK-29637 - Action listener for the 'Set to Active' button.
609+
*
610+
* @param event
611+
*/
612+
public void setToInactive( ActionEvent event )
613+
{
614+
toggleUserStatusInSites( false );
615+
}
616+
617+
/**
618+
* SAK-29637 - Action listener for the 'Set to Inactive' button.
619+
*
620+
* @param event
621+
*/
622+
public void setToActive( ActionEvent event )
623+
{
624+
toggleUserStatusInSites( true );
625+
}
626+
627+
/**
628+
* SAK-29637 - Utility method to toggle the user's status in the selected sites.
629+
*
630+
* @param active true = toggle to active, false = toggle to inactive
631+
*/
632+
private void toggleUserStatusInSites( boolean active )
633+
{
634+
// Loop through all user rows (user's sites)
635+
for( UserSitesRow row : userSitesRows )
636+
{
637+
if( row.isSelected() )
638+
{
639+
// Get the site
640+
Site site = row.site;
641+
if( site == null )
642+
{
643+
try
644+
{
645+
site = M_site.getSite( row.getSiteId() );
646+
}
647+
catch( IdUnusedException ex )
648+
{
649+
LOG.warn( "site not found, id=" + row.getSiteId(), ex );
650+
}
651+
}
652+
653+
if( site != null )
654+
{
655+
String realmID = site.getReference();
656+
try
657+
{
658+
String roleID = site.getMember( userId ).getRole().getId();
659+
AuthzGroup realm = authzGroupService.getAuthzGroup( realmID );
660+
boolean isProvided = StringUtils.isNotBlank( realm.getProviderGroupId() );
661+
realm.addMember( userId, roleID, active, isProvided );
662+
authzGroupService.save( realm );
663+
}
664+
catch( GroupNotDefinedException ex )
665+
{
666+
LOG.warn( "realm not found, id=" + realmID, ex );
667+
}
668+
catch( AuthzPermissionException ex )
669+
{
670+
LOG.warn( "permission exception updating realm, id=" + realmID, ex );
671+
}
672+
}
673+
}
674+
}
675+
676+
// Refresh the list
677+
this.refreshQuery = true;
678+
getInitValues();
679+
}
680+
583681
// ######################################################################################
584682
// CSV export
585683
// ######################################################################################
@@ -597,15 +695,16 @@ private String getFileNamePrefix() {
597695

598696
/**
599697
* Build a generic tabular representation of the user site membership data export.
698+
* SAK-29637 - modified to obey user's selection
600699
*
601700
* @param userSites The content of the table
602701
* @return
603702
* A table of data suitable to be exported
604703
*/
605704
private List<List<Object>> buildDataTable(List<UserSitesRow> userSites) {
606-
List<List<Object>> table = new LinkedList<List<Object>>();
705+
List<List<Object>> table = new LinkedList<>();
607706

608-
List<Object> header = new ArrayList<Object>();
707+
List<Object> header = new ArrayList<>();
609708
header.add(msgs.getString("site_name"));
610709
header.add(msgs.getString("site_id"));
611710
header.add(msgs.getString("groups"));
@@ -615,20 +714,23 @@ private List<List<Object>> buildDataTable(List<UserSitesRow> userSites) {
615714
header.add(msgs.getString("status"));
616715
header.add(msgs.getString("site_user_status"));
617716
table.add(header);
618-
717+
619718
for (UserSitesRow userSiteRow : userSites) {
620-
List<Object> currentRow = new ArrayList<Object>();
621-
currentRow.add(userSiteRow.getSiteTitle());
622-
currentRow.add(userSiteRow.getSiteId());
623-
currentRow.add(userSiteRow.getGroups());
624-
currentRow.add(userSiteRow.getSiteType());
625-
currentRow.add(userSiteRow.getSiteTerm());
626-
currentRow.add(userSiteRow.getRoleName());
627-
currentRow.add(userSiteRow.getPubView());
628-
currentRow.add(userSiteRow.getUserStatus());
629-
table.add(currentRow);
719+
if( userSiteRow.isSelected() )
720+
{
721+
List<Object> currentRow = new ArrayList<>();
722+
currentRow.add(userSiteRow.getSiteTitle());
723+
currentRow.add(userSiteRow.getSiteId());
724+
currentRow.add(userSiteRow.getGroups());
725+
currentRow.add(userSiteRow.getSiteType());
726+
currentRow.add(userSiteRow.getSiteTerm());
727+
currentRow.add(userSiteRow.getRoleName());
728+
currentRow.add(userSiteRow.getPubView());
729+
currentRow.add(userSiteRow.getUserStatus());
730+
table.add(currentRow);
731+
}
630732
}
631-
733+
632734
return table;
633-
}
735+
}
634736
}

‎usermembership/tool/src/webapp/usermembership/css/usermembership.css

+68-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,75 @@
33
text-align: left;
44
padding: 0px;
55
}
6+
67
.right {
78
vertical-align: bottom;
89
text-align: right;
910
padding: 0px;
10-
}
11+
}
12+
13+
/* SAK-29637 */
14+
div#sitelistform\:headerContainer1, div#sitelistform\:headerContainer2 {
15+
margin-top: 1em;
16+
}
17+
18+
div.headerWrapper {
19+
display: inline-block;
20+
background-color: #EEE !important;
21+
padding: 1em 1em 1em 0.5em;
22+
}
23+
24+
div#sitelistform\:headerContainer1 span.collapsed, div#sitelistform\:headerContainer1 span.expanded,
25+
div#sitelistform\:headerContainer2 span.collapsed, div#sitelistform\:headerContainer2 span.expanded {
26+
cursor: pointer;
27+
padding-left: 13px;
28+
}
29+
30+
div#sitelistform\:headerContainer1 span.collapsed, div#sitelistform\:headerContainer2 span.collapsed {
31+
background: url('/library/image/sakai/expand.gif') no-repeat left !important;
32+
}
33+
34+
div#sitelistform\:headerContainer1 span.expanded, div#sitelistform\:headerContainer2 span.expanded {
35+
background: url('/library/image/sakai/collapse.gif') no-repeat left !important;
36+
}
37+
38+
div#sitelistform\:actionContainer1, div#sitelistform\:actionContainer2 {
39+
display: none;
40+
background-color: #EEE;
41+
padding: 1em;
42+
}
43+
44+
div#sitelistform\:actionContainer1 div, div#sitelistform\:actionContainer2 div {
45+
display: inline-block;
46+
}
47+
48+
div#sitelistform\:actionContainer1 input, div#sitelistform\:actionContainer2 input {
49+
display: block;
50+
margin: 0.25em 0;
51+
border: 0 !important;
52+
background: 0 !important;
53+
background-color: #EEE !important;
54+
width: 100%;
55+
text-align: left;
56+
text-shadow: none !important;
57+
}
58+
59+
div#sitelistform\:actionContainer1 input:hover:enabled, div#sitelistform\:actionContainer2 input:hover:enabled {
60+
background-color: #CCC !important;
61+
}
62+
63+
div#sitelistform\:actionContainer1 input:active:enabled, div#sitelistform\:actionContainer2 input:active:enabled {
64+
background-color: #75B9C2 !important;
65+
color: #FFF !important;
66+
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.15) inset !important;
67+
text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.3) !important;
68+
}
69+
70+
div#sitelistform\:actionContainer1 div.column2, div#sitelistform\:actionContainer1 div.column3,
71+
div#sitelistform\:actionContainer2 div.column2, div#sitelistform\:actionContainer2 div.column3 {
72+
border-left: 2px solid #C8C8C8;
73+
padding-left: 1em;
74+
margin-left: 1em;
75+
vertical-align: top;
76+
}
77+
/* end SAK-29637 */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
var USR_MEMBRSHP = {};
2+
3+
USR_MEMBRSHP.applyStateToCheckboxes = function( state )
4+
{
5+
$( ".chkStatus" ).prop( "checked", state );
6+
$( ".chkStatus" ).attr( "value", state );
7+
USR_MEMBRSHP.checkEnableButtons();
8+
};
9+
10+
USR_MEMBRSHP.checkEnableButtons = function()
11+
{
12+
// Enable the buttons if any of the checkboxes are checked
13+
var disabled = $( ".chkStatus:checked" ).length > 0 ? false : true;
14+
$( "#sitelistform\\:setToInactive1" ).prop( "disabled", disabled );
15+
$( "#sitelistform\\:setToActive1" ).prop( "disabled", disabled );
16+
$( "#sitelistform\\:exportCsv1" ).prop( "disabled", disabled );
17+
$( "#sitelistform\\:exportXls1" ).prop( "disabled", disabled );
18+
$( "#sitelistform\\:setToInactive2" ).prop( "disabled", disabled );
19+
$( "#sitelistform\\:setToActive2" ).prop( "disabled", disabled );
20+
$( "#sitelistform\\:exportCsv2" ).prop( "disabled", disabled );
21+
$( "#sitelistform\\:exportXls2" ).prop( "disabled", disabled );
22+
};
23+
24+
USR_MEMBRSHP.invertSelection = function()
25+
{
26+
// For each checkbox...
27+
$( ".chkStatus" ).each( function()
28+
{
29+
// Invert it's selected state and value
30+
var checked = $( this ).prop( "checked" );
31+
$( this ).prop( "checked", !checked );
32+
$( this ).attr( "value", !checked );
33+
});
34+
35+
USR_MEMBRSHP.checkEnableButtons();
36+
};
37+
38+
USR_MEMBRSHP.toggleActions = function( clickedElement )
39+
{
40+
var specifier = clickedElement.parentElement.id === "sitelistform:headerContainer1" ? "1" : "2";
41+
var span = $( "#sitelistform\\:actionHeader" + specifier );
42+
if( span.attr( "class" ) === "collapsed" )
43+
{
44+
span.attr( "class", "expanded" );
45+
$( "#sitelistform\\:actionContainer" + specifier ).show();
46+
$( "#sitelistform\\:actionContainer" + specifier ).css( "display", "inline-flex" );
47+
}
48+
else
49+
{
50+
span.attr( "class", "collapsed" );
51+
$( "#sitelistform\\:actionContainer" + specifier ).hide();
52+
$( "#sitelistform\\:actionContainer" + specifier ).css( "display", "none" );
53+
}
54+
55+
setMainFrameHeight( USR_MEMBRSHP.frameID );
56+
};

‎usermembership/tool/src/webapp/usermembership/sitelist.jsp

+61-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<%@ page import="org.sakaiproject.umem.tool.ui.SiteListBean"%>
12
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
23
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
34
<%@ taglib uri="http://sakaiproject.org/jsf/sakai" prefix="sakai" %>
@@ -17,6 +18,14 @@
1718

1819
<f:view>
1920
<sakai:view title="#{msgs.tool_title}">
21+
<script type="text/javascript" src="/library/js/jquery/jquery-1.9.1.min.js"></script>
22+
<script type="text/javascript" src="/sakai-usermembership-tool/usermembership/js/usermembership.js"></script>
23+
<link href="/sakai-usermembership-tool/usermembership/css/usermembership.css" rel="stylesheet" type="text/css" media="all"></link>
24+
25+
<script>
26+
USR_MEMBRSHP.frameID = "<%= SiteListBean.getFrameID() %>";
27+
</script>
28+
2029
<%/*<sakai:flowState bean="#{SiteListBean}"/>*/%>
2130
<h:outputText value="#{SiteListBean.initValues}"/>
2231

@@ -28,13 +37,37 @@
2837
<h3><h:outputText value="#{msgs.title_sitelist} (#{SiteListBean.userDisplayId})"/></h3>
2938
<sakai:instruction_message value="#{msgs.instructions_sitelist}" />
3039

40+
<t:div id="headerContainer1" rendered="#{SiteListBean.renderTable && !SiteListBean.emptySiteList}">
41+
<t:div styleClass="headerWrapper" onclick="USR_MEMBRSHP.toggleActions( this );">
42+
<h:outputText id="actionHeader1" styleClass="collapsed" value="#{msgs.actions_header}" />
43+
</t:div>
44+
</t:div>
45+
<t:div id="actionContainer1" rendered="#{SiteListBean.renderTable && !SiteListBean.emptySiteList}">
46+
<t:div styleClass="column1">
47+
<h:commandButton type="button" title="#{msgs.select_all}" value="#{msgs.select_all}" onclick="USR_MEMBRSHP.applyStateToCheckboxes( true );" />
48+
<h:commandButton type="button" title="#{msgs.deselect_all}" value="#{msgs.deselect_all}" onclick="USR_MEMBRSHP.applyStateToCheckboxes( false );" />
49+
<h:commandButton type="button" title="#{msgs.invert_selection}" value="#{msgs.invert_selection}" onclick="USR_MEMBRSHP.invertSelection();" />
50+
</t:div>
51+
<t:div styleClass="column2">
52+
<h:commandButton id="setToInactive1" actionListener="#{SiteListBean.setToInactive}" value="#{msgs.set_to_inactive_button}" disabled="true"/>
53+
<h:commandButton id="setToActive1" actionListener="#{SiteListBean.setToActive}" value="#{msgs.set_to_active_button}" disabled="true" />
54+
</t:div>
55+
<t:div styleClass="column3">
56+
<h:commandButton id="exportCsv1" actionListener="#{SiteListBean.exportAsCsv}" value="#{msgs.export_selected_to_csv}" disabled="true" />
57+
<h:commandButton id="exportXls1" actionListener="#{SiteListBean.exportAsXls}" value="#{msgs.export_selected_to_excel}" disabled="true" />
58+
</t:div>
59+
</t:div>
60+
3161
<t:dataTable
3262
value="#{SiteListBean.userSitesRows}"
3363
var="row1"
3464
styleClass="listHier narrowTable"
3565
sortColumn="#{SiteListBean.sitesSortColumn}"
3666
sortAscending="#{SiteListBean.sitesSortAscending}"
3767
rendered="#{SiteListBean.renderTable}" >
68+
<h:column id="statusToggle">
69+
<h:selectBooleanCheckbox value="#{row1.selected}" styleClass="chkStatus" onclick="USR_MEMBRSHP.checkEnableButtons();" />
70+
</h:column>
3871
<h:column id="siteName">
3972
<f:facet name="header">
4073
<t:commandSortHeader columnName="siteName" immediate="true" arrow="true">
@@ -93,19 +126,36 @@
93126
</h:column>
94127
</t:dataTable>
95128

96-
<p class="instruction" style="margin-top: 40px;">
97-
<h:outputText value="#{msgs.no_sitelist}" rendered="#{SiteListBean.emptySiteList}" />
98-
</p>
99-
100-
<br>
101-
<t:div styleClass="act" rendered="#{SiteListBean.allowed}">
102-
<h:commandButton id="userlist" action="#{SiteListBean.processActionBack}" value="#{msgs.back_button}" styleClass="active"/>
103-
<h:commandButton id="exportCsv" actionListener="#{SiteListBean.exportAsCsv}" value="#{msgs.export_csv_button}" rendered="#{!SiteListBean.emptySiteList}" />
104-
<h:commandButton id="exportXls" actionListener="#{SiteListBean.exportAsXls}" value="#{msgs.export_excel_button}" rendered="#{!SiteListBean.emptySiteList}" />
129+
<h:panelGroup rendered="#{SiteListBean.emptySiteList}">
130+
<p class="instruction" style="margin-top: 40px;">
131+
<h:outputText value="#{msgs.no_sitelist}" />
132+
</p>
133+
</h:panelGroup>
134+
135+
<t:div id="headerContainer2" rendered="#{SiteListBean.renderTable && !SiteListBean.emptySiteList}" onclick="USR_MEMBRSHP.toggleActions( this );">
136+
<t:div styleClass="headerWrapper">
137+
<h:outputText id="actionHeader2" styleClass="collapsed" value="#{msgs.actions_header}" />
138+
</t:div>
139+
</t:div>
140+
<t:div id="actionContainer2" rendered="#{SiteListBean.renderTable && !SiteListBean.emptySiteList}">
141+
<t:div styleClass="column1">
142+
<h:commandButton type="button" title="#{msgs.select_all}" value="#{msgs.select_all}" onclick="USR_MEMBRSHP.applyStateToCheckboxes( true );" />
143+
<h:commandButton type="button" title="#{msgs.deselect_all}" value="#{msgs.deselect_all}" onclick="USR_MEMBRSHP.applyStateToCheckboxes( false );" />
144+
<h:commandButton type="button" title="#{msgs.invert_selection}" value="#{msgs.invert_selection}" onclick="USR_MEMBRSHP.invertSelection();" />
145+
</t:div>
146+
<t:div styleClass="column2">
147+
<h:commandButton id="setToInactive2" actionListener="#{SiteListBean.setToInactive}" value="#{msgs.set_to_inactive_button}" disabled="true"/>
148+
<h:commandButton id="setToActive2" actionListener="#{SiteListBean.setToActive}" value="#{msgs.set_to_active_button}" disabled="true" />
149+
</t:div>
150+
<t:div styleClass="column3">
151+
<h:commandButton id="exportCsv2" actionListener="#{SiteListBean.exportAsCsv}" value="#{msgs.export_selected_to_csv}" disabled="true" />
152+
<h:commandButton id="exportXls2" actionListener="#{SiteListBean.exportAsXls}" value="#{msgs.export_selected_to_excel}" disabled="true" />
153+
</t:div>
105154
</t:div>
106-
107155

156+
<t:div styleClass="act">
157+
<h:commandButton id="userlist" action="#{SiteListBean.processActionBack}" value="#{msgs.back_button}" styleClass="active"/>
158+
</t:div>
108159
</h:form>
109-
110160
</sakai:view>
111161
</f:view>

0 commit comments

Comments
 (0)
Please sign in to comment.