Index: pom.xml =================================================================== --- pom.xml (revision 100780) +++ pom.xml (working copy) @@ -148,6 +148,18 @@ ${sakai.jsf.version} pom + + org.projectlombok + lombok + 0.9.3 + provided + + + net.sf.opencsv + opencsv + 2.3 + compile + Index: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/impl/SiteManageGroupSectionRoleHandler.java =================================================================== --- site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/impl/SiteManageGroupSectionRoleHandler.java (revision 100780) +++ site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/impl/SiteManageGroupSectionRoleHandler.java (working copy) @@ -1,5 +1,7 @@ package org.sakaiproject.site.tool.helper.managegroupsectionrole.impl; +import java.io.IOException; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -12,6 +14,12 @@ import java.util.Set; import java.util.Vector; +import javax.servlet.http.HttpServletRequest; + +import lombok.Getter; +import lombok.Setter; + +import org.apache.commons.fileupload.FileItem; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -35,9 +43,14 @@ import org.sakaiproject.tool.api.Tool; import org.sakaiproject.tool.api.ToolManager; import org.sakaiproject.tool.api.ToolSession; +import org.sakaiproject.user.api.User; +import org.sakaiproject.user.api.UserDirectoryService; +import org.sakaiproject.user.api.UserNotDefinedException; +import org.sakaiproject.util.RequestFilter; import uk.org.ponder.messageutil.TargettedMessage; import uk.org.ponder.messageutil.TargettedMessageList; +import au.com.bytecode.opencsv.CSVReader; /** * * @author @@ -89,6 +102,8 @@ // Tool session attribute name used to schedule a whole page refresh. public static final String ATTR_TOP_REFRESH = "sakai.vppa.top.refresh"; + + private static final String CSV_MIME_TYPE="text/csv"; public TargettedMessageList messages; public void setMessages(TargettedMessageList messages) { @@ -152,6 +167,8 @@ selectedSiteMembers = new String[]{}; selectedRosters = new HashMap(); selectedRoles = new HashMap(); + + importedGroups = null; } /** @@ -1011,6 +1028,250 @@ return ((Group)o1).getTitle().compareToIgnoreCase( ((Group)o2).getTitle() ); } } + + /** + * Grabs the uploaded file from the groupfile request attribute and extracts the group details + * from it, adding them to the importedGroups list as it goes. Expects at least three columns, + * the first three being first name, last name and email respectively. + */ + public String processUploadAndCheck() { + String uploadsDone = (String) httpServletRequest.getAttribute(RequestFilter.ATTR_UPLOADS_DONE); + + FileItem usersFileItem; + + if (uploadsDone != null && uploadsDone.equals(RequestFilter.ATTR_UPLOADS_DONE)) { + + try { + usersFileItem = (FileItem) httpServletRequest.getAttribute("groupfile"); + + if(usersFileItem != null && usersFileItem.getSize() > 0) { + + String mimetype = usersFileItem.getContentType(); + + if(StringUtils.equals(mimetype, CSV_MIME_TYPE)) { + if(processCsvFile(usersFileItem)) { + return "success"; + } + } else { + M_log.error("Invalid file type: " + mimetype); + return "error"; + } + } + } + catch (Exception e){ + M_log.error(e.getClass() + " : " + e.getMessage()); + return "error"; + } + } + + return "error"; + } + + /** + * Helper to process the uploaded CSV file + * + * @param fileItem + * @return + */ + private boolean processCsvFile(FileItem fileItem){ + + M_log.debug("CSV file uploaded"); + + importedGroups = new ArrayList(); + + CSVReader reader; + try { + reader = new CSVReader(new InputStreamReader(fileItem.getInputStream())); + List lines = reader.readAll(); + + //maintain a map of the groups and their titles in case the CSV file is unordered + //this way we can still lookup the group and add members to it + Map groupMap = new HashMap(); + + for(String[] line: lines){ + + String groupTitle = StringUtils.trim(line[0]); + String userId = StringUtils.trim(line[1]); + + //if we already have an occurrence of this group, get the group and update the user list within it + if(groupMap.containsKey(groupTitle)){ + ImportedGroup group = groupMap.get(groupTitle); + group.addUser(userId); + } else { + ImportedGroup group = new ImportedGroup(groupTitle, userId); + groupMap.put(groupTitle, group); + } + } + + //extract all of the imported groups from the map + importedGroups.addAll(groupMap.values()); + + } catch (IOException ioe) { + M_log.error(ioe.getClass() + " : " + ioe.getMessage()); + return false; + } catch (ArrayIndexOutOfBoundsException ae){ + M_log.error(ae.getClass() + " : " + ae.getMessage()); + return false; + } + + return true; + } + + /** + * Helper to check for a valid user in a site, given an eid + * @param eid eid of user,v eg jsmith26 + * @return + */ + public boolean isValidSiteUser(String eid) { + try { + User u = userDirectoryService.getUserByEid(eid); + if(u != null){ + + Member m = site.getMember(u.getId()); + if(m != null) { + return true; + } + } + } catch (UserNotDefinedException e) { + //not a valid user + return false; + } + return false; + } + + /** + * Helper to get a userId given an eid + * @param eid eid of user,v eg jsmith26 + * @return + */ + public String getUserId(String eid) { + try { + return userDirectoryService.getUserId(eid); + } catch (UserNotDefinedException e) { + M_log.error("The eid: " + eid + "is invalid."); + return null; + } + } + + /** + * Does the actual import of the groups into the site. + * @return + */ + public String processImportedGroups() { + + //get current groups in this site + List existingGroups = getGroups(); + + //for each imported group... + for(ImportedGroup importedGroup: importedGroups) { + + Group group = null; + + //check if the groups already exists + for(Group g : existingGroups) { + if(StringUtils.equals(g.getTitle(), importedGroup.getGroupTitle())) { + //use existing group + group = g; + } + } + + if(group == null){ + //create new group + group= site.addGroup(); + group.getProperties().addProperty(SiteConstants.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString()); + group.setTitle(importedGroup.getGroupTitle()); + } + + //add all of the imported members to the group + for(String eid: importedGroup.getUserIds()){ + this.addUserToGroup(eid, group); + } + + try { + siteService.save(site); + // post event about the participant update + EventTrackingService.post(EventTrackingService.newEvent(SiteService.SECURE_UPDATE_GROUP_MEMBERSHIP, group.getId(),true)); + + } catch (Exception e) { + M_log.error("processImportedGroups failed for site: " + site.getId(), e); + return "error"; + } + } + + return "success"; + } + + /** + * Helper to get a list of user eids in a group + * @param g the group + * @return + */ + public List getGroupUserIds(Group g) { + + List userIds = new ArrayList(); + + if(g == null) { + return userIds; + } + + Set members= g.getMembers(); + for(Member m: members) { + userIds.add(m.getUserEid()); + } + return userIds; + } + + + /** + * Helper to add a user to a group. Takes care of the role selection. + * @param eid eid of the user eg jsmith26 + * @param g the group + */ + private void addUserToGroup(String eid, Group g) { + + //is this a valid site user? + if(!isValidSiteUser(eid)){ + return; + } + + //get userId + String userId = getUserId(eid); + if(StringUtils.isBlank(userId)) { + return; + } + + //is user already in the group? + if(g.getUserRole(userId) != null) { + return; + } + + //add user to group with correct role. This is the same logic as above + Role r = site.getUserRole(userId); + Member m = site.getMember(userId); + Role memberRole = m != null ? m.getRole() : null; + g.addMember(userId, r != null ? r.getId() : memberRole != null? memberRole.getId() : "", m != null ? m.isActive() : true, false); + + } + + + + @Setter + private UserDirectoryService userDirectoryService; + + /** + * We need this to get the uploaded file as snaffled by the request filter. + */ + @Setter + private HttpServletRequest httpServletRequest; + + /** + * As we import groups we store the details here for use in further stages + * of the import sequence. + */ + @Getter + private List importedGroups; + + } Index: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/impl/ImportedGroup.java =================================================================== --- site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/impl/ImportedGroup.java (revision 0) +++ site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/impl/ImportedGroup.java (revision 0) @@ -0,0 +1,32 @@ +package org.sakaiproject.site.tool.helper.managegroupsectionrole.impl; + +import java.util.SortedSet; +import java.util.TreeSet; + +import lombok.Data; + +/** + * Model for a group that is imported. Has a title and list of members. + * + */ +@Data +public class ImportedGroup { + + private String groupTitle; + private SortedSet userIds; + + // special constructor to take the title and a single user, then add that user to the internal set + public ImportedGroup(String groupTitle, String userId){ + this.groupTitle = groupTitle; + + userIds = new TreeSet(); + + addUser(userId); + } + + + //helper method to update the internal list + public void addUser(String userId) { + userIds.add(userId); + } +} Property changes on: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/impl/ImportedGroup.java ___________________________________________________________________ Added: svn:keywords + Date Revision Author HeadURL Id Added: svn:eol-style + native Index: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportViewParameters.java =================================================================== --- site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportViewParameters.java (revision 0) +++ site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportViewParameters.java (revision 0) @@ -0,0 +1,33 @@ +package org.sakaiproject.site.tool.helper.managegroupsectionrole.rsf; + +import uk.org.ponder.rsf.viewstate.SimpleViewParameters; + +/** + * + * Params for the group import process + * + */ +public class GroupImportViewParameters extends SimpleViewParameters { + + public String status; + + + public GroupImportViewParameters(String viewID, String status) { + this.status= status; + this.viewID = viewID; + } + + + public GroupImportViewParameters(String status) { + super(); + this.status = status; + } + + + public GroupImportViewParameters() { + super(); + } + + + +} Property changes on: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportViewParameters.java ___________________________________________________________________ Added: svn:keywords + Date Revision Author HeadURL Id Added: svn:eol-style + native Index: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep1Producer.java =================================================================== --- site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep1Producer.java (revision 0) +++ site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep1Producer.java (revision 0) @@ -0,0 +1,91 @@ +package org.sakaiproject.site.tool.helper.managegroupsectionrole.rsf; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.site.tool.helper.managegroupsectionrole.impl.SiteManageGroupSectionRoleHandler; +import org.sakaiproject.tool.api.SessionManager; +import org.sakaiproject.tool.api.Tool; + +import uk.ac.cam.caret.sakai.rsf.producers.FrameAdjustingProducer; +import uk.ac.cam.caret.sakai.rsf.util.SakaiURLUtil; +import uk.org.ponder.messageutil.MessageLocator; +import uk.org.ponder.rsf.components.UIBranchContainer; +import uk.org.ponder.rsf.components.UICommand; +import uk.org.ponder.rsf.components.UIContainer; +import uk.org.ponder.rsf.components.UIForm; +import uk.org.ponder.rsf.components.UIMessage; +import uk.org.ponder.rsf.components.UIVerbatim; +import uk.org.ponder.rsf.flow.ARIResult; +import uk.org.ponder.rsf.flow.ActionResultInterceptor; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCase; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReporter; +import uk.org.ponder.rsf.view.ComponentChecker; +import uk.org.ponder.rsf.view.ViewComponentProducer; +import uk.org.ponder.rsf.viewstate.RawViewParameters; +import uk.org.ponder.rsf.viewstate.SimpleViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParamsReporter; + +/** + * Producer for page 1 of the group import + */ +public class GroupImportStep1Producer implements ViewComponentProducer, NavigationCaseReporter, ViewParamsReporter, ActionResultInterceptor { + + private static Log M_log = LogFactory.getLog(GroupImportStep1Producer.class); + public SiteManageGroupSectionRoleHandler handler; + public static final String VIEW_ID = "GroupImportStep1"; + public MessageLocator messageLocator; + public FrameAdjustingProducer frameAdjustingProducer; + public SessionManager sessionManager; + + public String getViewID() { + return VIEW_ID; + } + + public void fillComponents(UIContainer tofill, ViewParameters viewParams, ComponentChecker checker) { + + GroupImportViewParameters params = (GroupImportViewParameters) viewParams; + + UIBranchContainer content = UIBranchContainer.make(tofill, "content:"); + UIVerbatim.make(content, "import1.instr.req.1", messageLocator.getMessage("import1.instr.req.1")); + UIVerbatim.make(content, "import1.instr.req.2", messageLocator.getMessage("import1.instr.req.2")); + UIVerbatim.make(content, "import1.instr.req.3", messageLocator.getMessage("import1.instr.req.3")); + UIForm uploadForm = UIForm.make(content, "uploadform"); + UICommand.make(uploadForm, "continue", messageLocator.getMessage("import1.continue"), "#{SiteManageGroupSectionRoleHandler.processUploadAndCheck}"); + UICommand.make(uploadForm, "cancel", messageLocator.getMessage("cancel"), "#{SiteManageGroupSectionRoleHandler.processCancel}"); + + if(StringUtils.equals(params.status, "error")){ + UIMessage.make(content, "import1.error", "import1.error"); + handler.resetParams(); + } + + frameAdjustingProducer.fillComponents(tofill, "resize", "resetFrame"); + + } + + public List reportNavigationCases() { + List togo = new ArrayList(); + togo.add(new NavigationCase("success", new SimpleViewParameters(GroupImportStep2Producer.VIEW_ID))); + togo.add(new NavigationCase("error", new GroupImportViewParameters(GroupImportStep1Producer.VIEW_ID, "error"))); + return togo; + } + + + public void interceptActionResult(ARIResult result, ViewParameters incoming, Object actionReturn) { + //from processCancel + if ("done".equals(actionReturn)) { + handler.resetParams(); + Tool tool = handler.getCurrentTool(); + result.resultingView = new RawViewParameters(SakaiURLUtil.getHelperDoneURL(tool, sessionManager)); + } + } + + + public ViewParameters getViewParameters() { + return new GroupImportViewParameters(); + } +} Property changes on: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep1Producer.java ___________________________________________________________________ Added: svn:keywords + Date Revision Author HeadURL Id Added: svn:eol-style + native Index: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep2Producer.java =================================================================== --- site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep2Producer.java (revision 0) +++ site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep2Producer.java (revision 0) @@ -0,0 +1,163 @@ +package org.sakaiproject.site.tool.helper.managegroupsectionrole.rsf; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.site.api.Group; +import org.sakaiproject.site.tool.helper.managegroupsectionrole.impl.ImportedGroup; +import org.sakaiproject.site.tool.helper.managegroupsectionrole.impl.SiteManageGroupSectionRoleHandler; +import org.sakaiproject.tool.api.SessionManager; +import org.sakaiproject.tool.api.Tool; + +import uk.ac.cam.caret.sakai.rsf.producers.FrameAdjustingProducer; +import uk.ac.cam.caret.sakai.rsf.util.SakaiURLUtil; +import uk.org.ponder.messageutil.MessageLocator; +import uk.org.ponder.rsf.components.UIBranchContainer; +import uk.org.ponder.rsf.components.UICommand; +import uk.org.ponder.rsf.components.UIContainer; +import uk.org.ponder.rsf.components.UIForm; +import uk.org.ponder.rsf.components.UIMessage; +import uk.org.ponder.rsf.components.UIOutput; +import uk.org.ponder.rsf.components.decorators.UICSSDecorator; +import uk.org.ponder.rsf.flow.ARIResult; +import uk.org.ponder.rsf.flow.ActionResultInterceptor; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCase; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReporter; +import uk.org.ponder.rsf.view.ComponentChecker; +import uk.org.ponder.rsf.view.ViewComponentProducer; +import uk.org.ponder.rsf.viewstate.RawViewParameters; +import uk.org.ponder.rsf.viewstate.SimpleViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParamsReporter; + +/** + * Producer for page 2 of the group import + */ +public class GroupImportStep2Producer implements ViewComponentProducer, NavigationCaseReporter, ViewParamsReporter, ActionResultInterceptor { + + private static Log M_log = LogFactory.getLog(GroupImportStep2Producer.class); + public SiteManageGroupSectionRoleHandler handler; + public static final String VIEW_ID = "GroupImportStep2"; + public MessageLocator messageLocator; + public FrameAdjustingProducer frameAdjustingProducer; + public SessionManager sessionManager; + + public String getViewID() { + return VIEW_ID; + } + + public void fillComponents(UIContainer tofill, ViewParameters viewParams, ComponentChecker checker) { + + GroupImportViewParameters params = (GroupImportViewParameters) viewParams; + + UIBranchContainer content = UIBranchContainer.make(tofill, "content:"); + + List importedGroups = handler.getImportedGroups(); + + boolean badData = false; + + //get list of groups already in this site + List existingGroups = handler.getGroups(); + + //print each group + for(ImportedGroup importedGroup: importedGroups) { + UIBranchContainer branch = UIBranchContainer.make(content,"groups:", importedGroup.getGroupTitle()); + + boolean groupExists = false; + Group existingGroup = null; + + //add title + UIOutput.make(branch,"title",importedGroup.getGroupTitle()); + + //check if group already exists + for(Group g : existingGroups) { + if(StringUtils.equals(g.getTitle(), importedGroup.getGroupTitle())) { + existingGroup = g; + groupExists = true; + UIOutput.make(branch,"groupexistsmsg:",messageLocator.getMessage("import2.groupexists")); + } + } + + //if group already exists, get the users that are already in the group, + //merge so we get one list, then display the new or merged ones appropriately. + Set userIds = importedGroup.getUserIds(); + List existingUserIds = new ArrayList(); + if(groupExists) { + existingUserIds = handler.getGroupUserIds(existingGroup); + userIds.addAll(existingUserIds); + } + + //print each user + for(String userId: importedGroup.getUserIds()) { + + UIOutput output = UIOutput.make(branch,"member:",userId); + + //check user is valid + if(handler.isValidSiteUser(userId)){ + //is user existing? + if(existingUserIds.contains(userId)) { + //highlight grey + Map cssMap = new HashMap(); + cssMap.put("color","grey"); + output.decorate(new UICSSDecorator(cssMap)); + } + + } else { + badData = true; + //highlight red + Map cssMap = new HashMap(); + cssMap.put("color","red"); + output.decorate(new UICSSDecorator(cssMap)); + } + } + } + + UIForm createForm = UIForm.make(content, "form"); + + if(badData) { + UIMessage.make(content, "import2.error", "import2.error"); + handler.resetParams(); + + UICommand.make(createForm, "cancel", messageLocator.getMessage("cancel"), "#{SiteManageGroupSectionRoleHandler.processCancel}"); + + } else { + UIMessage.make(content, "import2.okay", "import2.okay"); + + UICommand.make(createForm, "continue", messageLocator.getMessage("import2.continue"), "#{SiteManageGroupSectionRoleHandler.processImportedGroups}"); + UICommand.make(createForm, "cancel", messageLocator.getMessage("cancel"), "#{SiteManageGroupSectionRoleHandler.processCancel}"); + } + + if(StringUtils.equals(params.status, "error")){ + UIMessage.make(content, "import2.couldntimportgroups", "import2.couldntimportgroups"); + } + + frameAdjustingProducer.fillComponents(tofill, "resize", "resetFrame"); + } + + public List reportNavigationCases() { + List togo = new ArrayList(); + togo.add(new NavigationCase("success", new SimpleViewParameters(GroupListProducer.VIEW_ID))); + togo.add(new NavigationCase("error", new GroupImportViewParameters(GroupImportStep2Producer.VIEW_ID, "error"))); + return togo; + } + + public void interceptActionResult(ARIResult result, ViewParameters incoming, Object actionReturn) { + if ("done".equals(actionReturn)) { + handler.resetParams(); + Tool tool = handler.getCurrentTool(); + result.resultingView = new RawViewParameters(SakaiURLUtil.getHelperDoneURL(tool, sessionManager)); + } + } + + public ViewParameters getViewParameters() { + return new GroupImportViewParameters(); + } + +} Property changes on: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupImportStep2Producer.java ___________________________________________________________________ Added: svn:keywords + Date Revision Author HeadURL Id Added: svn:eol-style + native Index: site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupListProducer.java =================================================================== --- site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupListProducer.java (revision 100780) +++ site-manage-group-section-role-helper/tool/src/java/org/sakaiproject/site/tool/helper/managegroupsectionrole/rsf/GroupListProducer.java (working copy) @@ -99,7 +99,8 @@ UIBranchContainer actions = UIBranchContainer.make(tofill,"actions:",Integer.toString(0)); UIInternalLink.make(actions,"add",UIMessage.make("group.newgroup"), new GroupEditViewParameters(GroupEditProducer.VIEW_ID, null)); UIInternalLink.make(actions,"auto_add",UIMessage.make("group.auto.newgroup"), new GroupAutoCreateViewParameters(GroupAutoCreateProducer.VIEW_ID, null)); - + UIInternalLink.make(actions,"import_add",UIMessage.make("group.import"), new GroupImportViewParameters(GroupImportStep1Producer.VIEW_ID, null)); + UIOutput.make(tofill, "group-list-title", messageLocator.getMessage("group.list")); UIForm deleteForm = UIForm.make(tofill, "delete-group-form"); Index: site-manage-group-section-role-helper/tool/src/bundle/org/sakaiproject/site/tool/managegroupsectionrole/bundle/Messages.properties =================================================================== --- site-manage-group-section-role-helper/tool/src/bundle/org/sakaiproject/site/tool/managegroupsectionrole/bundle/Messages.properties (revision 100780) +++ site-manage-group-section-role-helper/tool/src/bundle/org/sakaiproject/site/tool/managegroupsectionrole/bundle/Messages.properties (working copy) @@ -47,4 +47,24 @@ exist.group.role = (A group with this role already exists) ### limit of site group title #### -site_group_title_length_limit=Title length cannot exceed {0} characters. Please provide a shorter title. \ No newline at end of file +site_group_title_length_limit=Title length cannot exceed {0} characters. Please provide a shorter title. + +group.import = Import from file +group.importinstruction = Import groups from a spreadsheet or csv file + +import1.title = Upload a file containing the groups you wish to create +import1.instr.req.header = File requirements +import1.instr.req.1 = The CSV file should contain the group details in the columns: group title, username. +import1.instr.req.2 = Columns must be in the order above, but do not include a row of column headers. +import1.instr.req.3 = Fields must be comma separated, contain no spaces between fields and each field surrounded with double quotes if it is to contain a space. +import1.error = The file you uploaded was not readable. Please check the file is of the correct format, and try again. +import1.continue = Continue + +import2.check = Verify the imported data +import2.error = The data you supplied contained invalid users or the users are not part of the site (highlighted in red). You need to correct these issues and start again. +import2.okay = The following data was found in the uploaded file. If this is correct, click 'Continue'. +import2.grouptitle = Group Title +import2.userid = User ID +import2.continue = Import groups +import2.couldntimportgroups = An error occurred importing the groups. Please contact an administrator. +import2.groupexists = This group already exists, the membership will be merged. The existing users are noted in grey. Index: site-manage-group-section-role-helper/tool/src/webapp/WEB-INF/requestContext.xml =================================================================== --- site-manage-group-section-role-helper/tool/src/webapp/WEB-INF/requestContext.xml (revision 100780) +++ site-manage-group-section-role-helper/tool/src/webapp/WEB-INF/requestContext.xml (working copy) @@ -43,6 +43,8 @@ + + + + + + + + + + + + + + + + + Index: site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep1.html =================================================================== --- site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep1.html (revision 0) +++ site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep1.html (revision 0) @@ -0,0 +1,35 @@ + + + + Import groups - select a file + + + + + + + +
+
+

import1.title

+

import1.instr.req.header

+
    +
  • import1.instr.req.1
  • +
  • import1.instr.req.2
  • +
  • import1.instr.req.1
  • +
+

import1.error

+
+
+ +
+

+ + +

+
+
+
+ + Property changes on: site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep1.html ___________________________________________________________________ Added: svn:mime-type + text/html Added: svn:keywords + Date Revision Author HeadURL Id Added: svn:eol-style + native Index: site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep2.html =================================================================== --- site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep2.html (revision 0) +++ site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep2.html (revision 0) @@ -0,0 +1,37 @@ + + + + Import from file - Confirm groups + + + + + + +
+
+

import2.check

+
import2.error
+
import2.okay
+

import2.couldntimportgroups

+ +
+

Group A

+ import2.groupexists +

jsmith26

+
+ + +
+ +

+ + +

+
+ +
+
+ + Property changes on: site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupImportStep2.html ___________________________________________________________________ Added: svn:mime-type + text/html Added: svn:keywords + Date Revision Author HeadURL Id Added: svn:eol-style + native Index: site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupList.html =================================================================== --- site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupList.html (revision 100780) +++ site-manage-group-section-role-helper/tool/src/webapp/content/templates/GroupList.html (working copy) @@ -18,6 +18,7 @@

Groups

Index: site-manage-group-section-role-helper/tool/pom.xml =================================================================== --- site-manage-group-section-role-helper/tool/pom.xml (revision 100780) +++ site-manage-group-section-role-helper/tool/pom.xml (working copy) @@ -60,6 +60,22 @@ ${rsfutil.version}-sakai_${sakairsf.sakai.version} war + + javax.servlet + servlet-api + + + commons-fileupload + commons-fileupload + + + net.sf.opencsv + opencsv + + + org.projectlombok + lombok + commons-lang