package org.sakaiproject.delegatedaccess.tool.pages;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import org.apache.log4j.Logger;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.extensions.markup.html.tree.table.ColumnLocation;
import org.apache.wicket.extensions.markup.html.tree.table.ColumnLocation.Alignment;
import org.apache.wicket.extensions.markup.html.tree.table.ColumnLocation.Unit;
import org.apache.wicket.extensions.markup.html.tree.table.IColumn;
import org.apache.wicket.extensions.markup.html.tree.table.PropertyTreeColumn;
import org.apache.wicket.extensions.markup.html.tree.table.TreeTable;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.tree.AbstractTree;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;
import org.sakaiproject.delegatedaccess.model.HierarchyNodeSerialized;
import org.sakaiproject.delegatedaccess.model.ListOptionSerialized;
import org.sakaiproject.delegatedaccess.model.NodeModel;
import org.sakaiproject.delegatedaccess.model.SearchResult;
import org.sakaiproject.delegatedaccess.util.DelegatedAccessConstants;
import org.sakaiproject.delegatedaccess.utils.PropertyEditableColumnAdvancedUserOptions;
import org.sakaiproject.delegatedaccess.utils.PropertyEditableColumnCheckbox;
import org.sakaiproject.delegatedaccess.utils.PropertyEditableColumnDropdown;
import org.sakaiproject.delegatedaccess.utils.PropertyEditableColumnList;
/**
* Creates the UserEdit page to edit a user's access
*
* @author Bryan Holladay (holladay@longsight.com)
*
*/
public class UserEditPage extends BaseTreePage{
private TreeTable tree;
private static final Logger log = Logger.getLogger(UserEditPage.class);
private String[] defaultRole = null;
List<String> accessAdminNodeIds = null;
@Override
protected AbstractTree getTree() {
return tree;
}
public UserEditPage(final String userId, final String displayName){
//Form Feedback (Saved/Error)
final Label formFeedback = new Label("formFeedback");
formFeedback.setOutputMarkupPlaceholderTag(true);
final String formFeedbackId = formFeedback.getMarkupId();
add(formFeedback);
//Form Feedback2 (Saved/Error)
final Label formFeedback2 = new Label("formFeedback2");
formFeedback2.setOutputMarkupPlaceholderTag(true);
final String formFeedback2Id = formFeedback2.getMarkupId();
add(formFeedback2);
//USER NAME & IMAGE:
add(new Label("userName", displayName));
//FORM:
Form form = new Form("form");
add(form);
//Expand Collapse Link:
form.add(getExpandCollapseLink());
//tree:
//create a map of the realms and their roles for the Role column
final Map<String, String> roleMap = projectLogic.getRealmRoleDisplay(false);
String largestRole = "";
for(String role : roleMap.values()){
if(role.length() > largestRole.length()){
largestRole = role;
}
}
//set the size of the role Column (shopper becomes)
int roleColumnSize = 40 + largestRole.length() * 6;
if(roleColumnSize < 115){
//for "Choose One" default option
roleColumnSize = 115;
}
boolean singleRoleOptions = false;
if(roleMap.size() == 1){
String[] split = null;
for(String key : roleMap.keySet()){
split = key.split(":");
}
if(split != null && split.length == 2){
//only one option for role, so don't bother showing it in the table
singleRoleOptions = true;
defaultRole = split;
}
}
List<IColumn> columnsList = new ArrayList<IColumn>();
columnsList.add(new PropertyTreeColumn(new ColumnLocation(Alignment.MIDDLE, 100, Unit.PROPORTIONAL), "", "userObject.node.description"));
if(sakaiProxy.isSuperUser()){
columnsList.add(new PropertyEditableColumnCheckbox(new ColumnLocation(Alignment.RIGHT, 70, Unit.PX), new StringResourceModel("accessAdmin", null).getString(), "userObject.accessAdmin", DelegatedAccessConstants.TYPE_ACCESS_ADMIN));
columnsList.add(new PropertyEditableColumnCheckbox(new ColumnLocation(Alignment.RIGHT, 70, Unit.PX), new StringResourceModel("shoppingPeriodAdmin", null).getString(), "userObject.shoppingPeriodAdmin", DelegatedAccessConstants.TYPE_SHOPPING_PERIOD_ADMIN));
}
columnsList.add(new PropertyEditableColumnCheckbox(new ColumnLocation(Alignment.RIGHT, 55, Unit.PX), new StringResourceModel("siteAccess", null).getString(), "userObject.directAccess", DelegatedAccessConstants.TYPE_ACCESS));
if(!singleRoleOptions){
columnsList.add(new PropertyEditableColumnDropdown(new ColumnLocation(Alignment.RIGHT, roleColumnSize, Unit.PX), new StringResourceModel("userBecomes", null).getString(),
"userObject.roleOption", roleMap, DelegatedAccessConstants.TYPE_ACCESS, sakaiProxy.isSuperUser() ? null : sakaiProxy.getSubAdminOrderedRealmRoles()));
}
columnsList.add(new PropertyEditableColumnList(new ColumnLocation(Alignment.RIGHT, 96, Unit.PX), new StringResourceModel("restrictedToolsHeader", null).getString(),
"userObject.restrictedAuthTools", DelegatedAccessConstants.TYPE_ACCESS, DelegatedAccessConstants.TYPE_LISTFIELD_TOOLS));
//setup advanced options settings:
Map<String, Object> advSettings = new HashMap<String, Object>();
advSettings.put(PropertyEditableColumnAdvancedUserOptions.SETTINGS_ALLOW_SET_BECOME_USER, sakaiProxy.isSuperUser() || sakaiProxy.allowAccessAdminsSetBecomeUserPerm());
columnsList.add(new PropertyEditableColumnAdvancedUserOptions(new ColumnLocation(Alignment.RIGHT, 75, Unit.PX), new StringResourceModel("advanced", null).getString(), "", advSettings));
IColumn columns[] = columnsList.toArray(new IColumn[columnsList.size()]);
//if the user isn't a super user, they should only be able to edit the nodes they
//have been granted accessAdmin privileges
if(!sakaiProxy.isSuperUser()){
Set<HierarchyNodeSerialized> accessAdminNodes = projectLogic.getAccessAdminNodesForUser(sakaiProxy.getCurrentUserId());
accessAdminNodeIds = new ArrayList<String>();
if(accessAdminNodes != null){
for(HierarchyNodeSerialized node : accessAdminNodes){
accessAdminNodeIds.add(node.id);
}
}
}
final TreeModel treeModel = projectLogic.createEntireTreeModelForUser(userId, true, false);
final List<ListOptionSerialized> blankRestrictedTools = projectLogic.getEntireToolsList();
//a null model means the tree is empty
tree = new TreeTable("treeTable", treeModel, columns){
@Override
public boolean isVisible() {
return treeModel != null;
}
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) {
//the nodes are generated on the fly with ajax. This will add any child nodes that
//are missing in the tree. Expanding and collapsing will refresh the tree node
tree.getTreeState().selectNode(node, false);
boolean anyAdded = false;
if(!tree.getTreeState().isNodeExpanded(node) && !((NodeModel) ((DefaultMutableTreeNode) node).getUserObject()).isAddedDirectChildrenFlag()){
anyAdded = projectLogic.addChildrenNodes(node, userId, blankRestrictedTools, false, accessAdminNodeIds, false, false);
((NodeModel) ((DefaultMutableTreeNode) node).getUserObject()).setAddedDirectChildrenFlag(true);
}
if(anyAdded){
collapseEmptyFoldersHelper((DefaultMutableTreeNode) node);
}
if(!tree.getTreeState().isNodeExpanded(node) || anyAdded){
tree.getTreeState().expandNode(node);
}else{
tree.getTreeState().collapseNode(node);
}
}
protected void onJunctionLinkClicked(AjaxRequestTarget target, TreeNode node) {
//the nodes are generated on the fly with ajax. This will add any child nodes that
//are missing in the tree. Expanding and collapsing will refresh the tree node
if(tree.getTreeState().isNodeExpanded(node) && !((NodeModel) ((DefaultMutableTreeNode) node).getUserObject()).isAddedDirectChildrenFlag()){
boolean anyAdded = projectLogic.addChildrenNodes(node, userId, blankRestrictedTools, false, accessAdminNodeIds, false, false);
((NodeModel) ((DefaultMutableTreeNode) node).getUserObject()).setAddedDirectChildrenFlag(true);
if(anyAdded){
collapseEmptyFoldersHelper((DefaultMutableTreeNode) node);
}
}
}
@Override
protected boolean isForceRebuildOnSelectionChange() {
return true;
};
};
if(singleRoleOptions){
tree.add(new AttributeAppender("class", new Model("noRoles"), " "));
}
form.add(tree);
//updateButton button:
AjaxButton updateButton = new AjaxButton("update", form) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form arg1) {
try{
//save node access and roll information:
updateNodeAccess(userId, defaultRole);
//display a "saved" message
formFeedback.setDefaultModel(new ResourceModel("success.save"));
formFeedback.add(new AttributeModifier("class", true, new Model("success")));
target.addComponent(formFeedback);
formFeedback2.setDefaultModel(new ResourceModel("success.save"));
formFeedback2.add(new AttributeModifier("class", true, new Model("success")));
target.addComponent(formFeedback2);
}catch (Exception e) {
log.error(e.getMessage(), e);
formFeedback.setDefaultModel(new ResourceModel("failed.save"));
formFeedback.add(new AttributeModifier("class", true, new Model("alertMessage")));
target.addComponent(formFeedback);
formFeedback2.setDefaultModel(new ResourceModel("failed.save"));
formFeedback2.add(new AttributeModifier("class", true, new Model("alertMessage")));
target.addComponent(formFeedback2);
}
//call a js function to hide the message in 5 seconds
target.appendJavascript("hideFeedbackTimer('" + formFeedbackId + "');");
target.appendJavascript("hideFeedbackTimer('" + formFeedback2Id + "');");
}
};
form.add(updateButton);
//cancelButton button:
Button cancelButton = new Button("cancel") {
@Override
public void onSubmit() {
setResponsePage(new SearchUsersPage());
}
};
form.add(cancelButton);
}
}