Index: lams_build/lib/lams/lams-central.jar =================================================================== diff -u -re96add634141f1413a107b009e61f39c52ea5c5c -r6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c Binary files differ Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r0340817df8d420d1feafa8ad9a43f667023515b2 -r6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c Binary files differ Index: lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LearningDesignRepositoryServlet.java =================================================================== diff -u -r744f5620f6d13c0fa4f44e42b708dbec50bfe9b4 -r6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c --- lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LearningDesignRepositoryServlet.java (.../LearningDesignRepositoryServlet.java) (revision 744f5620f6d13c0fa4f44e42b708dbec50bfe9b4) +++ lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LearningDesignRepositoryServlet.java (.../LearningDesignRepositoryServlet.java) (revision 6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c) @@ -326,27 +326,43 @@ // do export exportLD(request, response); - } else if (method != null && method.equals("getLearningDesignsJSON")) { + } else if (method != null && ( method.equals("getLearningDesignsJSON") || method.equals("getPagedHomeLearningDesignsJSON")) ) { - ExtUserUseridMap userMap = null; - boolean prefix = usePrefix == null ? true : Boolean.parseBoolean(usePrefix); - if (firstName == null && lastName == null) { - userMap = integrationService.getExtUserUseridMap(serverMap, username, prefix); - } else { - userMap = integrationService.getImplicitExtUserUseridMap(serverMap, username, firstName, lastName, - lang, country, email, prefix, isUpdateUserDetails); - } + ExtUserUseridMap userMap = null; + boolean prefix = usePrefix == null ? true : Boolean.parseBoolean(usePrefix); + if (firstName == null && lastName == null) { + userMap = integrationService.getExtUserUseridMap(serverMap, username, prefix); + } else { + userMap = integrationService.getImplicitExtUserUseridMap(serverMap, username, firstName, lastName, + lang, country, email, prefix, isUpdateUserDetails); + } + + // create group for external course if necessary + integrationService.getExtCourseClassMap(serverMap, userMap, courseId, country, lang, courseName, LoginRequestDispatcher.METHOD_AUTHOR); + Integer userId = userMap.getUser().getUserId(); + + boolean allowInvalidDesigns = WebUtil.readBooleanParam(request, "allowInvalidDesigns", false); + + String folderContentsJSON = null; + if ( method.equals("getLearningDesignsJSON") ) { + Integer folderID = WebUtil.readIntParam(request, "folderID", true); + folderContentsJSON = service.getFolderContentsJSON(folderID, userId, allowInvalidDesigns); + } else { + Integer folderID = WebUtil.readIntParam(request, "folderID", true); + Integer page = WebUtil.readIntParam(request, "page", true); + Integer size = WebUtil.readIntParam(request, "size", true); + String sortName = request.getParameter("sortName"); + String sortDate = request.getParameter("sortDate"); + String search = request.getParameter("search"); + folderContentsJSON = service.getPagedLearningDesignsJSON(userId, allowInvalidDesigns, search, page, size, + sortName == null ? null : ( sortName.equals("0") ? "DESC" : "ASC" ), + sortDate == null ? null : ( sortDate.equals("0") ? "DESC" : "ASC" )); + } - // create group for external course if necessary - integrationService.getExtCourseClassMap(serverMap, userMap, courseId, country, lang, courseName, LoginRequestDispatcher.METHOD_AUTHOR); - Integer userId = userMap.getUser().getUserId(); - - Integer folderID = WebUtil.readIntParam(request, "folderID", true); - boolean allowInvalidDesigns = WebUtil.readBooleanParam(request, "allowInvalidDesigns", false); - String folderContentsJSON = service.getFolderContentsJSON(folderID, userId, allowInvalidDesigns); - - response.setContentType("application/json;charset=UTF-8"); - response.getWriter().write(folderContentsJSON); + log.debug("LearningDesignRepositoryServlet returning "+folderContentsJSON); + + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(folderContentsJSON); //TODO remove the next else-paragraph as soon as all integrations will start using new method. (After this also stop checking for (method != null && method.equals("getLearningDesignsJSONFormat"))) } else { @@ -395,7 +411,7 @@ } } - + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } Index: lams_central/src/java/org/lamsfoundation/lams/workspace/service/IWorkspaceManagementService.java =================================================================== diff -u -re6e981f6a6fff2779cdcbb39513e76b10ccc131f -r6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c --- lams_central/src/java/org/lamsfoundation/lams/workspace/service/IWorkspaceManagementService.java (.../IWorkspaceManagementService.java) (revision e6e981f6a6fff2779cdcbb39513e76b10ccc131f) +++ lams_central/src/java/org/lamsfoundation/lams/workspace/service/IWorkspaceManagementService.java (.../IWorkspaceManagementService.java) (revision 6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c) @@ -137,10 +137,26 @@ /** * Returns Folder Contents in JSON format. + * If folderID == null, returns the top level folders available to the user. + * If folderID == -1, return only the learning designs in the root of the user's folder + * Otherwise returns the learning designs and subfolders of the given folder. + * Sample output: */ - String getFolderContentsJSON(Integer folderID, Integer userID, boolean allowInvalidDesigns) throws JSONException, + String getFolderContentsJSON(Integer folderID, Integer userID, boolean allowInvalidDesigns) throws JSONException, IOException, UserAccessDeniedException, RepositoryCheckedException; + /** + * Returns a section of the learning designs in the root of the user's personal folder. Returns the data in in JSON + * format. If searchString is not null, it does a case insenstive "contains" comparison on name (title). Otherwise + * sortName and sortDate should be null, ASC or DESC and the data will be paged. + * Sample output: + * {"total_rows":2,"rows":[{"learningDesignId":19,"description":"Team Based Learning: Blah Blah","name":"Blah Blah", + * "date":"2015-07-13 10:16:35.0"},{"learningDesignId":18,"description":"Team Based Learning Design: BBBBBB", + * "name":"TBL_BBBBB","date":"2015-07-13 10:07:41.0"}]} + */ + public String getPagedLearningDesignsJSON(Integer userID, boolean allowInvalidDesigns, String searchString, int page, int size, + String sortName, String sortDate) throws JSONException, IOException; + /** * This method creates a new folder under the given parentFolder * inside the user's default workspace. Index: lams_central/src/java/org/lamsfoundation/lams/workspace/service/WorkspaceManagementService.java =================================================================== diff -u -r5e39743e8bd500d0e121cf4c95b9c9fc77eb80fc -r6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c --- lams_central/src/java/org/lamsfoundation/lams/workspace/service/WorkspaceManagementService.java (.../WorkspaceManagementService.java) (revision 5e39743e8bd500d0e121cf4c95b9c9fc77eb80fc) +++ lams_central/src/java/org/lamsfoundation/lams/workspace/service/WorkspaceManagementService.java (.../WorkspaceManagementService.java) (revision 6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c) @@ -34,8 +34,11 @@ import java.util.Set; import java.util.SortedSet; import java.util.Vector; +import java.util.regex.Pattern; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.log4j.Logger; +import org.apache.tomcat.util.json.JSONArray; import org.apache.tomcat.util.json.JSONException; import org.apache.tomcat.util.json.JSONObject; import org.lamsfoundation.lams.authoring.service.IAuthoringService; @@ -72,7 +75,6 @@ import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.wddx.FlashMessage; -import org.lamsfoundation.lams.web.HomeAction; import org.lamsfoundation.lams.workspace.WorkspaceFolderContent; import org.lamsfoundation.lams.workspace.dto.FolderContentDTO; import org.lamsfoundation.lams.workspace.dto.UpdateContentDTO; @@ -165,7 +167,7 @@ if ((resourceID == null) || (resourceType == null) || (userID == null)) { errorMessage = messageService.getMessage("delete.resource.error.value.miss"); } else if (FolderContentDTO.DESIGN.equals(resourceType)) { - return deleteLearningDesign(resourceID, userID); + return deleteLearningDesignWDDX(resourceID, userID); } else if (FolderContentDTO.FOLDER.equals(resourceType)) { return deleteFolder(new Integer(resourceID.intValue()), userID); } else if (FolderContentDTO.FILE.equals(resourceType)) { @@ -398,29 +400,45 @@ @SuppressWarnings("unchecked") public String getFolderContentsJSON(Integer folderID, Integer userID, boolean allowInvalidDesigns) throws JSONException, IOException, UserAccessDeniedException, RepositoryCheckedException { + + return getFolderContentsJSON(folderID, userID, allowInvalidDesigns, false); + } + + public String getFolderContentsJSON(Integer folderID, Integer userID, boolean allowInvalidDesigns, boolean designsOnly) + throws JSONException, IOException, UserAccessDeniedException, RepositoryCheckedException { JSONObject result = new JSONObject(); Vector folderContents = null; - // get user accessible folders in the start - if (folderID == null) { - folderContents = new Vector(3); - + // folderID == null: get all user accessible folders + // folderID == -1: get the learning designs at the root of the user's home folder - used for simplified deployment + if (folderID == null || folderID == -1 ) { + FolderContentDTO userFolder = getUserWorkspaceFolder(userID); - if (userFolder != null) { - folderContents.add(userFolder); - } - FolderContentDTO myGroupsFolder = new FolderContentDTO(messageService.getMessage("organisations"), + if ( folderID == null ) { + folderContents = new Vector(3); + + if (userFolder != null) { + folderContents.add(userFolder); + } + + FolderContentDTO myGroupsFolder = new FolderContentDTO(messageService.getMessage("organisations"), messageService.getMessage("folder"), null, null, FolderContentDTO.FOLDER, WorkspaceAction.ORG_FOLDER_ID.longValue(), WorkspaceFolder.READ_ACCESS, null); - folderContents.add(myGroupsFolder); + folderContents.add(myGroupsFolder); - FolderContentDTO publicFolder = getPublicWorkspaceFolder(userID); - if (publicFolder != null) { - folderContents.add(publicFolder); - } - // special behaviour for organisation folders + FolderContentDTO publicFolder = getPublicWorkspaceFolder(userID); + if (publicFolder != null) { + folderContents.add(publicFolder); + } + + } else if ( userFolder != null ) { + return getFolderContentsJSON(userFolder.getResourceID().intValue(), userID, allowInvalidDesigns, true); + + } // else we want to return an empty JSON, which will be done by falling through to the folderContents loop. + + // special behaviour for organisation folders } else if (folderID.equals(WorkspaceAction.ORG_FOLDER_ID)) { folderContents = getAccessibleOrganisationWorkspaceFolders(userID); Collections.sort(folderContents); @@ -442,7 +460,7 @@ // fill JSON object with folders and LDs for (FolderContentDTO folderContent : folderContents) { String contentType = folderContent.getResourceType(); - if (FolderContentDTO.FOLDER.equals(contentType)) { + if (FolderContentDTO.FOLDER.equals(contentType) && !designsOnly) { JSONObject subfolderJSON = new JSONObject(); subfolderJSON.put("name", folderContent.getName()); subfolderJSON.put("isRunSequencesFolder", @@ -453,6 +471,8 @@ JSONObject learningDesignJSON = new JSONObject(); learningDesignJSON.put("name", folderContent.getName()); learningDesignJSON.put("learningDesignId", folderContent.getResourceID()); + learningDesignJSON.put("description", folderContent.getDescription()); + learningDesignJSON.put("date", folderContent.getLastModifiedDateTime()); result.append("learningDesigns", learningDesignJSON); } else { if (log.isDebugEnabled()) { @@ -464,6 +484,60 @@ return result.toString(); } + @Override + @SuppressWarnings("unchecked") + public String getPagedLearningDesignsJSON(Integer userID, boolean allowInvalidDesigns, String searchString, + int page, int size, String sortName, String sortDate) throws JSONException, IOException { + + JSONArray result = new JSONArray(); + Pattern searchPattern = searchString != null ? Pattern.compile(Pattern.quote(searchString), Pattern.CASE_INSENSITIVE) : null; + FolderContentDTO userFolder = getUserWorkspaceFolder(userID); + long numDesigns = 0; + + if (userFolder != null) { + Integer mode = allowInvalidDesigns ? WorkspaceManagementService.AUTHORING + : WorkspaceManagementService.MONITORING; + + int folderId = userFolder.getResourceID().intValue(); + List designs = null; + if (WorkspaceManagementService.AUTHORING.equals(mode)) { + if ( searchPattern != null ) + designs = learningDesignDAO.getAllPagedLearningDesigns(folderId, null, null, sortName, sortDate); + else + designs = learningDesignDAO.getAllPagedLearningDesigns(folderId, page, size, sortName, sortDate); + } else { + if ( searchPattern != null ) + designs = learningDesignDAO.getValidPagedLearningDesigns(folderId, null, null, sortName, sortDate); + else + designs = learningDesignDAO.getValidPagedLearningDesigns(folderId, page, size, sortName, sortDate); + } + + + Iterator iterator = designs.iterator(); + while (iterator.hasNext()) { + LearningDesign design = (LearningDesign) iterator.next(); + if (searchPattern == null || (searchPattern.matcher(design.getTitle()).find()) ) { + JSONObject learningDesignJSON = new JSONObject(); + learningDesignJSON.put("name", StringEscapeUtils.escapeHtml(design.getTitle())); + learningDesignJSON.put("learningDesignId", design.getLearningDesignId()); + learningDesignJSON.put("description", StringEscapeUtils.escapeHtml(design.getDescription())); + learningDesignJSON.put("date", design.getLastModifiedDateTime()); + result.put(learningDesignJSON); + } + } + + // what is the total number (so the pager knows whether to allow paging) + // if we did a search, then no paging just return the whole lot. + // otherwise need the whole count from the db. + numDesigns = searchPattern != null ? result.length() : learningDesignDAO.countAllLearningDesigns(folderId, !allowInvalidDesigns); + } + + JSONObject completeResult = new JSONObject(); + completeResult.put("total_rows", numDesigns); + completeResult.put("rows", result); + return completeResult.toString(); + } + /** * This method returns the permissions specific to the given workspaceFolder for the given user. * @@ -825,7 +899,7 @@ * @return String The acknowledgement/error message in WDDX format for FLASH * @throws IOException */ - private String deleteLearningDesign(Long learningDesignID, Integer userID) throws IOException { + private String deleteLearningDesignWDDX(Long learningDesignID, Integer userID) throws IOException { User user = (User) baseDAO.find(User.class, userID); FlashMessage flashMessage = null; if (user != null) { Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/dao/ILearningDesignDAO.java =================================================================== diff -u -r01fa7b9ff8bf04b7dbe1056d1e9e8fdd1a113410 -r6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/dao/ILearningDesignDAO.java (.../ILearningDesignDAO.java) (revision 01fa7b9ff8bf04b7dbe1056d1e9e8fdd1a113410) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/dao/ILearningDesignDAO.java (.../ILearningDesignDAO.java) (revision 6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c) @@ -92,4 +92,23 @@ public List getLearningDesignTitlesByWorkspaceFolder(Integer workspaceFolderID, String prefix); public List getAccessByUser(Integer userId); + + /** + * Get a portion of the learning designs in the given folder. If page & size are null, the effect the same data + * is returned as getAllLearningDesignsInFolder but sorted. + */ + public List getAllPagedLearningDesigns(Integer workspaceFolderID, Integer page, Integer size, + String sortName, String sortDate); + + /** + * Get a portion of the valid learning designs in the given folder. If page & size are null, the effect the same data + * is returned as getAllValidLearningDesignsInFolder but sorted. + */ + public List getValidPagedLearningDesigns(Integer workspaceFolderID, Integer page, Integer size, + String sortName, String sortDate); + + /** + * Count how many learning designs exist in a given folder. + */ + public long countAllLearningDesigns(Integer workspaceFolderID, boolean validDesignsOnly); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/dao/hibernate/LearningDesignDAO.java =================================================================== diff -u -r01fa7b9ff8bf04b7dbe1056d1e9e8fdd1a113410 -r6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/dao/hibernate/LearningDesignDAO.java (.../LearningDesignDAO.java) (revision 01fa7b9ff8bf04b7dbe1056d1e9e8fdd1a113410) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/dao/hibernate/LearningDesignDAO.java (.../LearningDesignDAO.java) (revision 6b0e0c0668f4d5ee32ae9e3fe76e12395f187e8c) @@ -23,7 +23,9 @@ /* $$Id$$ */ package org.lamsfoundation.lams.learningdesign.dao.hibernate; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.hibernate.HibernateException; import org.hibernate.Query; @@ -45,6 +47,13 @@ private static final String ALL_IN_FOLDER ="from " + TABLENAME +" in class " + LearningDesign.class.getName()+ " where workspace_folder_id=?"; + + private static final String COUNT_VALID_IN_FOLDER = "SELECT COUNT(*) from " + TABLENAME + + " where valid_design_flag=true AND workspace_folder_id=?"; + + private static final String COUNT_ALL_IN_FOLDER = "SELECT COUNT(*) from " + TABLENAME + " where workspace_folder_id=?"; + + private static final String FIND_BY_ORIGINAL ="from " + TABLENAME +" in class " + LearningDesign.class.getName()+ " where original_learning_design_id=?"; private static final String FIND_LD_NAMES_IN_FOLDER = "select title from " + LearningDesign.class.getName()+ @@ -124,4 +133,46 @@ public List getAccessByUser(Integer userId) { return this.getHibernateTemplate().find(ACCESS_BY_USER, userId); } + + @SuppressWarnings("unchecked") + public List getAllPagedLearningDesigns(Integer workspaceFolderID, Integer page, Integer size, String sortName, String sortDate) { + String sortingOrder = setupSortString(sortName, sortDate); + Query query = getSession().createQuery(ALL_IN_FOLDER + sortingOrder) + .setParameter(0, workspaceFolderID.longValue()); + if ( page != null && size != null ) + query.setFirstResult(page * size).setMaxResults(size); + + return (List) query.list(); + } + + @SuppressWarnings("unchecked") + public List getValidPagedLearningDesigns(Integer workspaceFolderID, Integer page, Integer size, String sortName, String sortDate) { + String sortingOrder = setupSortString(sortName, sortDate); + Query query = getSession().createQuery(VALID_IN_FOLDER + sortingOrder) + .setParameter(0, workspaceFolderID.longValue()); + if ( page != null && size != null ) + query.setFirstResult(page * size).setMaxResults(size); + + return (List) query.list(); + } + + private String setupSortString(String sortName, String sortDate) { + if ( sortName != null && sortDate != null ) { + return " order by title "+sortName +", last_modified_date_time "+sortDate; + } else if ( sortDate != null ) { + return " order by last_modified_date_time "+sortDate; + } else { + // default to sorting by name + return " order by title "+ (sortName!=null ? sortName : "ASC"); + } + } + + public long countAllLearningDesigns(Integer workspaceFolderID, boolean validDesignsOnly) { + Map properties = new HashMap(); + properties.put("workspaceFolder.workspaceFolderId", workspaceFolderID); + if ( validDesignsOnly ) + properties.put("validDesign", Boolean.valueOf(validDesignsOnly)); + return countByProperties(LearningDesign.class, properties); + } + } \ No newline at end of file