Index: gradebook/app/sakai-tool/src/webapp/WEB-INF/applicationContext.xml =================================================================== --- gradebook/app/sakai-tool/src/webapp/WEB-INF/applicationContext.xml (revision 0) +++ gradebook/app/sakai-tool/src/webapp/WEB-INF/applicationContext.xml (revision 0) @@ -0,0 +1,21 @@ + + + + + + + true + + + + text/csv + + + + + csv + + + + Property changes on: gradebook/app/sakai-tool/src/webapp/WEB-INF/applicationContext.xml ___________________________________________________________________ Added: svn:eol-style + native Index: gradebook/app/sakai-tool/src/webapp/WEB-INF/web.xml =================================================================== --- gradebook/app/sakai-tool/src/webapp/WEB-INF/web.xml (revision 62347) +++ gradebook/app/sakai-tool/src/webapp/WEB-INF/web.xml (working copy) @@ -45,7 +45,7 @@ sakai.gradebook.tool - org.sakaiproject.jsf.util.JsfTool + org.sakaiproject.tool.gradebook.ui.GradebookFilePickerServlet default entry.servlet Index: gradebook/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java =================================================================== --- gradebook/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java (revision 0) +++ gradebook/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java (revision 0) @@ -0,0 +1,58 @@ +/** + * + */ +package org.sakaiproject.tool.gradebook.ui; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.sakaiproject.content.api.FilePickerHelper; +import org.sakaiproject.entity.api.Reference; +import org.sakaiproject.entity.api.ResourceProperties; +import org.sakaiproject.jsf.util.HelperAwareJsfTool; +import org.sakaiproject.tool.api.ToolSession; +import org.sakaiproject.tool.cover.SessionManager; + +/** + * @author bsawert + * + */ +public class GradebookFilePickerServlet extends HelperAwareJsfTool { + + protected boolean sendToHelper(HttpServletRequest req, HttpServletResponse res, String target) { + ToolSession toolSession = SessionManager.getCurrentToolSession(); + + ToolSession session = SessionManager.getCurrentToolSession(); + if (session.getAttribute(FilePickerHelper.FILE_PICKER_CANCEL) == null && + session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS) != null) { + + // attachments are References, which cannot be Serialized + // get reference strings and store those instead + + List refs = (List) session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS); + + if (refs != null && refs.size() > 0) { + // we are only processing a single reference - the first one + Reference ref = (Reference) refs.get(0); + + // save reference string + String refString = ref.getReference(); + session.setAttribute(SpreadsheetUploadBean.PICKED_FILE_REFERENCE, refString); + + // save display name + ResourceProperties rp = ref.getProperties(); + String pickedFileDesc = (String) rp.get(rp.getNamePropDisplayName()); + session.setAttribute(SpreadsheetUploadBean.PICKED_FILE_DESC, pickedFileDesc); + } + + session.removeAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS); + session.removeAttribute(FilePickerHelper.FILE_PICKER_CANCEL); + } + + return super.sendToHelper(req, res, target); + } + + +} Property changes on: gradebook/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java ___________________________________________________________________ Added: svn:keywords + Date Revision Author HeadURL Id Added: svn:eol-style + native Index: gradebook/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/SpreadsheetUploadBean.java =================================================================== --- gradebook/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/SpreadsheetUploadBean.java (revision 62347) +++ gradebook/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/SpreadsheetUploadBean.java (working copy) @@ -23,15 +23,15 @@ import java.io.InputStreamReader; import java.io.Serializable; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; +import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; +import javax.faces.component.UIComponent; +import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import javax.faces.model.SelectItem; @@ -40,29 +40,37 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.myfaces.custom.fileupload.UploadedFile; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterCsv; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterXls; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetUtil; +import org.sakaiproject.component.cover.ComponentManager; +import org.sakaiproject.content.api.ContentResource; +import org.sakaiproject.content.api.FilePickerHelper; +import org.sakaiproject.entity.api.Entity; +import org.sakaiproject.entity.api.Reference; +import org.sakaiproject.entity.api.ResourceProperties; +import org.sakaiproject.entity.cover.EntityManager; +import org.sakaiproject.exception.ServerOverloadException; +import org.sakaiproject.jsf.util.JsfTool; import org.sakaiproject.section.api.coursemanagement.EnrollmentRecord; import org.sakaiproject.section.api.coursemanagement.User; import org.sakaiproject.service.gradebook.shared.ConflictingAssignmentNameException; import org.sakaiproject.service.gradebook.shared.ConflictingSpreadsheetNameException; -import org.sakaiproject.tool.gradebook.AbstractGradeRecord; +import org.sakaiproject.tool.api.Tool; +import org.sakaiproject.tool.api.ToolSession; +import org.sakaiproject.tool.cover.SessionManager; import org.sakaiproject.tool.gradebook.Assignment; import org.sakaiproject.tool.gradebook.AssignmentGradeRecord; import org.sakaiproject.tool.gradebook.Category; import org.sakaiproject.tool.gradebook.Comment; -import org.sakaiproject.tool.gradebook.CourseGrade; -import org.sakaiproject.tool.gradebook.GradableObject; import org.sakaiproject.tool.gradebook.Gradebook; +import org.sakaiproject.tool.gradebook.LetterGradePercentMapping; import org.sakaiproject.tool.gradebook.jsf.FacesUtil; -import org.sakaiproject.tool.gradebook.LetterGradePercentMapping; public class SpreadsheetUploadBean extends GradebookDependentBean implements Serializable { private String title; private UploadedFile upFile; + private String pickedFileReference; + private String pickedFileDesc; private static final Log logger = LogFactory.getLog(SpreadsheetUploadBean.class); private Spreadsheet spreadsheet; private Map rosterMap; @@ -85,6 +93,7 @@ private String selectedCategory; private Gradebook localGradebook; private StringBuilder externallyMaintainedImportMsg; + private UIComponent uploadButton; // Used for bulk upload of gradebook items // Holds list of unknown user ids @@ -98,6 +107,9 @@ private static final String IMPORT_NO_CHANGES = "import_entire_no_changes"; private static final String IMPORT_ASSIGNMENT_NOTSUPPORTED= "import_assignment_entire_notsupported"; private static final String IMPORT_ASSIGNMENT_NEG_VALUE = "import_assignment_entire_negative_score"; + private static final int MAX_FILE_PICKER_UPLOADS = 1; + static final String PICKED_FILE_REFERENCE = "pickedFileReference"; + static final String PICKED_FILE_DESC = "pickedFileDesc"; private String pageName; @@ -505,35 +517,70 @@ * @throws Exception */ public String processFileEntire() throws Exception { - if(logger.isDebugEnabled()) logger.debug("check if upFile is intialized"); - if(upFile == null){ - if(logger.isDebugEnabled()) logger.debug("upFile not initialized"); - FacesUtil.addErrorMessage(getLocalizedString("import_entire_file_missing")); - return null; - } + InputStream inputStream = null; + String fileName = null; + List contents = null; - if(logger.isDebugEnabled()){ - logger.debug("file size " + upFile.getSize() + "file name " + upFile.getName() + "file Content Type " + upFile.getContentType() + ""); + if (upFile != null) { + if (upFile != null && logger.isDebugEnabled()) { + logger.debug("file size " + upFile.getSize() + "file name " + upFile.getName() + "file Content Type " + upFile.getContentType() + ""); + } + + if (logger.isDebugEnabled()) logger.debug("check that the file is csv file"); + + if (!upFile.getName().endsWith("csv")) { + FacesUtil.addErrorMessage(getLocalizedString("import_entire_filetype_error",new String[] {upFile.getName()})); + return null; + } + + fileName = upFile.getName(); + inputStream = new BufferedInputStream(upFile.getInputStream()); } + else { + savePickedUploadFile(); + + if (pickedFileReference != null) { + if (logger.isDebugEnabled()) logger.debug("check that the file is csv file"); + + if (pickedFileDesc == null || !pickedFileDesc.endsWith("csv")) { + FacesUtil.addErrorMessage(getLocalizedString("import_entire_filetype_error", new String[] {pickedFileDesc})); + return null; + } + + fileName = pickedFileDesc; + inputStream = getPickedFileStream(); + clearPickedFile(); + } + else { + // all null - no uploaded or picked file + if (logger.isDebugEnabled()) logger.debug("uploaded file not initialized"); + FacesUtil.addErrorMessage(getLocalizedString("import_entire_file_missing")); + return null; + } + } - if(logger.isDebugEnabled()) logger.debug("check that the file is csv file"); - if(!upFile.getName().endsWith("csv")){ - FacesUtil.addErrorMessage(getLocalizedString("import_entire_filetype_error",new String[] {upFile.getName()})); + if (inputStream == null) { + FacesUtil.addErrorMessage(getLocalizedString("upload_view_config_error")); return null; - } + } + + try { + contents = csvtoArray(inputStream); + inputStream.close(); + } + catch(IOException ioe) { + FacesUtil.addErrorMessage(getLocalizedString("upload_view_config_error")); + return null; + } // reset error lists unknownUsers = new ArrayList(); unknownAssignments = new ArrayList(); - - // process file to set up objects - InputStream inputStream = new BufferedInputStream(upFile.getInputStream()); - List contents; - contents = csvtoArray(inputStream); + spreadsheet = new Spreadsheet(); spreadsheet.setDate(new Date()); spreadsheet.setTitle(this.getTitle()); - spreadsheet.setFilename(upFile.getName()); + spreadsheet.setFilename(fileName); spreadsheet.setLineitems(contents); assignmentList = new ArrayList(); @@ -629,32 +676,67 @@ } public String processFile() throws Exception { - if(logger.isDebugEnabled()) logger.debug("check if upFile is intialized"); - if(upFile == null){ - if(logger.isDebugEnabled()) logger.debug("upFile not initialized"); - FacesUtil.addErrorMessage(getLocalizedString("upload_view_failure")); - return null; - } + InputStream inputStream = null; + String fileName = null; + List contents = null; - if(logger.isDebugEnabled()){ - logger.debug("file size " + upFile.getSize() + "file name " + upFile.getName() + "file Content Type " + upFile.getContentType() + ""); + if (upFile != null) { + if (upFile != null && logger.isDebugEnabled()) { + logger.debug("file size " + upFile.getSize() + "file name " + upFile.getName() + "file Content Type " + upFile.getContentType() + ""); + } + + if (logger.isDebugEnabled()) logger.debug("check that the file is csv file"); + + if (!upFile.getName().endsWith("csv")) { + FacesUtil.addErrorMessage(getLocalizedString("upload_view_filetype_error",new String[] {upFile.getName()})); + return null; + } + + fileName = upFile.getName(); + inputStream = new BufferedInputStream(upFile.getInputStream()); } + else { + savePickedUploadFile(); + + if (pickedFileReference != null) { + if (logger.isDebugEnabled()) logger.debug("check that the file is csv file"); + + if (pickedFileDesc == null || !pickedFileDesc.endsWith("csv")) { + FacesUtil.addErrorMessage(getLocalizedString("upload_view_filetype_error", new String[] {pickedFileDesc})); + return null; + } + + fileName = pickedFileDesc; + inputStream = getPickedFileStream(); + clearPickedFile(); + } + else { + // all null - no uploaded or picked file + if (logger.isDebugEnabled()) logger.debug("uploaded file not initialized"); + FacesUtil.addErrorMessage(getLocalizedString("upload_view_failure")); + return null; + } + } - if(logger.isDebugEnabled()) logger.debug("check that the file is csv file"); - if(!upFile.getName().endsWith("csv")){ - FacesUtil.addErrorMessage(getLocalizedString("upload_view_filetype_error",new String[] {upFile.getName()})); + if (inputStream == null) { + FacesUtil.addErrorMessage(getLocalizedString("upload_view_config_error")); return null; - } - - InputStream inputStream = new BufferedInputStream(upFile.getInputStream()); - List contents; - contents = csvtoArray(inputStream); + } + + try { + contents = csvtoArray(inputStream); + inputStream.close(); + } + catch(IOException ioe) { + FacesUtil.addErrorMessage(getLocalizedString("upload_view_config_error")); + return null; + } + spreadsheet = new Spreadsheet(); spreadsheet.setDate(new Date()); spreadsheet.setTitle(this.getTitle()); - spreadsheet.setFilename(upFile.getName()); + spreadsheet.setFilename(fileName); spreadsheet.setLineitems(contents); - assignmentList = new ArrayList(); studentRows = new ArrayList(); assignmentColumnSelectItems = new ArrayList(); @@ -714,7 +796,7 @@ FacesUtil.addErrorMessage(getLocalizedString("upload_view_filecontent_error")); return null; } - + return "spreadsheetUploadPreview"; } @@ -1869,6 +1951,103 @@ } } } + + /** + * Process an upload ActionEvent from spreadsheetUpload.jsp or spreadsheetEntireGBImport.jsp + * Source of this action is the Upload button on either page + * + * @param event + */ + public void launchFilePicker(ActionEvent event) { + try { + String titleText = FacesUtil.getLocalizedString("upload_view_page_title"); + String instructionText = FacesUtil.getLocalizedString("upload_view_instructions_text"); + + ToolSession currentToolSession = SessionManager.getCurrentToolSession(); + currentToolSession.setAttribute(FilePickerHelper.FILE_PICKER_MAX_ATTACHMENTS, FilePickerHelper.CARDINALITY_SINGLE); + currentToolSession.setAttribute(FilePickerHelper.FILE_PICKER_TITLE_TEXT, titleText); + currentToolSession.setAttribute(FilePickerHelper.FILE_PICKER_INSTRUCTION_TEXT, instructionText); + currentToolSession.setAttribute(FilePickerHelper.FILE_PICKER_RESOURCE_FILTER, + ComponentManager.get("org.sakaiproject.content.api.ContentResourceFilter.spreadsheetCsvFile")); + ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); + context.redirect("sakai.filepicker.helper/tool"); + } + catch(Exception e) { + logger.error(this + ".launchFilePicker - " + e); + e.printStackTrace(); + } + } + + /** + * Extract and store the reference to the uploaded file. + * Only process the first reference - don't do multiple uploads. + * + */ + public void savePickedUploadFile() { + ToolSession session = SessionManager.getCurrentToolSession(); + if (session.getAttribute(PICKED_FILE_REFERENCE) != null) { + pickedFileReference = (String) session.getAttribute(PICKED_FILE_REFERENCE); + pickedFileDesc = (String) session.getAttribute(PICKED_FILE_DESC); + } + } + + /** + * Use the uploaded file reference to get an InputStream. + * Must be a reference to a ContentResource + * + * @return InputStream + */ + private InputStream getPickedFileStream() { + InputStream inStream = null; + + if (pickedFileReference != null) { + try { + Reference ref = EntityManager.newReference(pickedFileReference); + if (ref != null) { + Entity ent = ref.getEntity(); + if (ent instanceof ContentResource) { + // entity came from file picker, so it should be a content resource + inStream = ((ContentResource) ent).streamContent(); + } + } + } + catch(ServerOverloadException soe) { + logger.error(soe.getStackTrace()); + } + } + + return inStream; + } + + private void clearPickedFile() { + ToolSession session = SessionManager.getCurrentToolSession(); + session.removeAttribute(PICKED_FILE_REFERENCE); + session.removeAttribute(PICKED_FILE_DESC); + + pickedFileDesc = null; + pickedFileReference = null; + } + + /** + * @return the pickedFileDesc + */ + public String getPickedFileDesc() { + // check the session attribute first + ToolSession session = SessionManager.getCurrentToolSession(); + if (session.getAttribute(PICKED_FILE_DESC) != null) { + pickedFileDesc = (String) session.getAttribute(PICKED_FILE_DESC); + } + + return pickedFileDesc; + } + + /** + * @param pickedFileDesc the pickedFileDesc to set + */ + public void setPickedFileDesc(String pickedFileDesc) { + this.pickedFileDesc = pickedFileDesc; + } + } Index: gradebook/app/ui/src/bundle/org/sakaiproject/tool/gradebook/bundle/Messages.properties =================================================================== --- gradebook/app/ui/src/bundle/org/sakaiproject/tool/gradebook/bundle/Messages.properties (revision 62347) +++ gradebook/app/ui/src/bundle/org/sakaiproject/tool/gradebook/bundle/Messages.properties (working copy) @@ -403,7 +403,7 @@ upload_view_instructions = Instructions: upload_view_instructions_text = Your Spreadsheet file must be saved in csv format.
One column of your csv file must contain individual's usernames.
The first row of your csv must contain headings for the columns. upload_view_title = Title * -upload_view_choose_file = Choose a file * +upload_view_choose_file = Filename * upload_view_save = Save upload_view_cancel = Cancel upload_view_filetype_error = The file "{0}" that you uploaded is not a valid file type. Only "csv" files are valid for uploading. Index: gradebook/app/ui/src/webapp/spreadsheetUpload.jsp =================================================================== --- gradebook/app/ui/src/webapp/spreadsheetUpload.jsp (revision 62347) +++ gradebook/app/ui/src/webapp/spreadsheetUpload.jsp (working copy) @@ -37,19 +37,30 @@ + <%/* old commons.fileupload code + */%> + + <%/* + */%> + + + + <%/* + */%> + Index: gradebook/app/ui/src/webapp/spreadsheetEntireGBImport.jsp =================================================================== --- gradebook/app/ui/src/webapp/spreadsheetEntireGBImport.jsp (revision 62347) +++ gradebook/app/ui/src/webapp/spreadsheetEntireGBImport.jsp (working copy) @@ -56,21 +56,29 @@ + <%/* + */%> + + + + + <%/* + */%> + - - + <%-- Button to do the actual import --%>

@@ -83,4 +91,4 @@ <%-- End of upload completed spreadsheet form --%> - \ No newline at end of file +