Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf Binary files differ Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java (.../ILearnerProgressDAO.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java (.../ILearnerProgressDAO.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -94,27 +94,27 @@ /** * Get learners who are at the given activities at the moment. */ - List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset); + List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset, boolean orderAscending); /** * Get learners who most recently finished the lesson. */ List getLearnersLatestCompletedForLesson(Long lessonId, Integer limit, Integer offset); /** - * Get learners whose first name, last name or login match any of the tokens from search phrase. - * Sort by most progressed first, then by name. - * Used by Learners tab in Monitoring interface. + * Get learners whose first name, last name or login match any of the tokens from search phrase. Sort by most + * progressed first, then by name. Used by Learners tab in Monitoring interface. */ List getLearnersByMostProgress(Long lessonId, String searchPhrase, Integer limit, Integer offset); /** - * Get all the learner progress records for a lesson where the progress is marked as completed. + * Get learner progress records for a lesson where the progress is marked as completed. * * @param lessonId * @return List */ - List getCompletedLearnerProgressForLesson(Long lessonId); + List getCompletedLearnerProgressForLesson(Long lessonId, Integer limit, Integer offset, + boolean orderAscending); /** * Get all the learner progress records for a lesson. Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILessonDAO.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILessonDAO.java (.../ILessonDAO.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILessonDAO.java (.../ILessonDAO.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -143,7 +143,11 @@ */ Integer getCountActiveLearnerByLesson(long lessonId); - List getLearnersByLesson(Long lessonId, String searchPhrase, Integer limit, Integer offset); + /** + * Get learners who are part of the lesson class. + */ + List getLearnersByLesson(Long lessonId, String searchPhrase, Integer limit, Integer offset, + boolean orderAscending); /** * Returns the count of all the learners that are a part of the lesson class. Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java (.../LearnerProgressDAO.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java (.../LearnerProgressDAO.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -49,7 +49,8 @@ private final static String LOAD_PROGRESS_REFFERING_TO_ACTIVITY = "from LearnerProgress p where p.previousActivity = :activity or p.currentActivity = :activity or p.nextActivity = :activity "; - private final static String LOAD_COMPLETED_PROGRESS_BY_LESSON = "from LearnerProgress p where p.lessonComplete > 0 and p.lesson.id = :lessonId"; + private final static String LOAD_COMPLETED_PROGRESS_BY_LESSON = "FROM LearnerProgress p WHERE p.lessonComplete > 0 " + + "AND p.lesson.id = :lessonId ORDER BY p.user.firstName , p.user.lastName , p.user.login "; private final static String LOAD_LEARNERS_LATEST_COMPLETED_BY_LESSON = "SELECT p.user FROM LearnerProgress p WHERE " + "p.lessonComplete > 0 and p.lesson.id = :lessonId ORDER BY p.finishDate DESC"; @@ -83,8 +84,9 @@ + "WHERE prog.current_activity_id = :activityId AND att.activity_id = :activityId " + "ORDER BY att.start_date_time DESC"; - private final static String LOAD_LEARNERS_BY_ACTIVITIES = "SELECT p.user FROM LearnerProgress p WHERE " - + " p.currentActivity.id IN (:activityIds)"; + private final static String LOAD_LEARNERS_BY_ACTIVITIES = "SELECT prog.user FROM LearnerProgress prog WHERE " + + " prog.currentActivity.id IN (:activityIds) " + + "ORDER BY prog.user.firstName , prog.user.lastName , prog.user.login "; private final static String COUNT_LEARNERS_BY_LESSON = "COUNT(*) FROM LearnerProgress prog WHERE prog.lesson.id = :lessonId"; private final static String COUNT_LEARNERS_BY_LESSON_ORDER_CLAUSE = " ORDER BY prog.user.firstName ASC, prog.user.lastName ASC, prog.user.login ASC"; @@ -150,8 +152,10 @@ @SuppressWarnings("unchecked") @Override - public List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset) { - Query query = getSession().createQuery(LearnerProgressDAO.LOAD_LEARNERS_BY_ACTIVITIES) + public List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset, + boolean orderAscending) { + Query query = getSession().createQuery( + LearnerProgressDAO.LOAD_LEARNERS_BY_ACTIVITIES.replaceAll("", orderAscending ? "ASC" : "DESC")) .setParameterList("activityIds", activityIds); if (limit != null) { query.setMaxResults(limit); @@ -203,9 +207,17 @@ @SuppressWarnings("unchecked") @Override - public List getCompletedLearnerProgressForLesson(Long lessonId) { - return getSession().createQuery(LearnerProgressDAO.LOAD_COMPLETED_PROGRESS_BY_LESSON) - .setLong("lessonId", lessonId).list(); + public List getCompletedLearnerProgressForLesson(Long lessonId, Integer limit, Integer offset, + boolean orderAscending) { + Query query = getSession().createQuery(LearnerProgressDAO.LOAD_COMPLETED_PROGRESS_BY_LESSON + .replaceAll("", orderAscending ? "ASC" : "DESC")).setLong("lessonId", lessonId); + if (limit != null) { + query.setMaxResults(limit); + } + if (offset != null) { + query.setFirstResult(offset); + } + return query.list(); } @SuppressWarnings("unchecked") Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LessonDAO.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LessonDAO.java (.../LessonDAO.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LessonDAO.java (.../LessonDAO.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -171,8 +171,9 @@ @SuppressWarnings("unchecked") @Override - public List getLearnersByLesson(Long lessonId, String searchPhrase, Integer limit, Integer offset) { - String queryText = LessonDAO.buildLearnersByLessonQuery(false, searchPhrase); + public List getLearnersByLesson(Long lessonId, String searchPhrase, Integer limit, Integer offset, + boolean orderAscending) { + String queryText = LessonDAO.buildLearnersByLessonQuery(false, searchPhrase, orderAscending); Query query = getSession().createQuery(queryText).setLong("lessonId", lessonId); if (limit != null) { query.setMaxResults(limit); @@ -185,7 +186,7 @@ @Override public Integer getCountLearnersByLesson(long lessonId, String searchPhrase) { - String queryText = LessonDAO.buildLearnersByLessonQuery(true, searchPhrase); + String queryText = LessonDAO.buildLearnersByLessonQuery(true, searchPhrase, true); Query query = getSession().createQuery(queryText).setLong("lessonId", lessonId); Object value = query.uniqueResult(); return ((Number) value).intValue(); @@ -346,7 +347,7 @@ return (Lesson) query.uniqueResult(); } - private static String buildLearnersByLessonQuery(boolean count, String searchPhrase) { + private static String buildLearnersByLessonQuery(boolean count, String searchPhrase, boolean orderAscending) { StringBuilder queryText = new StringBuilder("SELECT ").append(count ? "COUNT(*) " : "users ") .append(LessonDAO.LOAD_LEARNERS_BY_LESSON); if (!StringUtils.isBlank(searchPhrase)) { @@ -357,8 +358,10 @@ } } if (!count) { - queryText.append(" ORDER BY users.firstName ASC, users.lastName ASC, users.login ASC"); + String order = orderAscending ? "ASC" : "DESC"; + queryText.append(" ORDER BY users.firstName ").append(order).append(", users.lastName ").append(order) + .append(", users.login ").append(order); } return queryText.toString(); } -} +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/lesson/service/ILessonService.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_common/src/java/org/lamsfoundation/lams/lesson/service/ILessonService.java (.../ILessonService.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/service/ILessonService.java (.../ILessonService.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -74,7 +74,11 @@ */ Integer getCountActiveLessonLearners(Long lessonId); - List getLessonLearners(Long lessonId, String searchPhrase, Integer limit, Integer offset); + /** + * Get learners who are part of the lesson class. + */ + List getLessonLearners(Long lessonId, String searchPhrase, Integer limit, Integer offset, + boolean orderAscending); /** * Get the count of all the learners who are a part of the lesson class. Index: lams_common/src/java/org/lamsfoundation/lams/lesson/service/LessonService.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_common/src/java/org/lamsfoundation/lams/lesson/service/LessonService.java (.../LessonService.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/service/LessonService.java (.../LessonService.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -120,11 +120,13 @@ public Integer getCountActiveLessonLearners(Long lessonId) { return lessonDAO.getCountActiveLearnerByLesson(lessonId); } + @Override - public List getLessonLearners(Long lessonId, String searchPhrase, Integer limit, Integer offset) { - return lessonDAO.getLearnersByLesson(lessonId, searchPhrase, limit, offset); + public List getLessonLearners(Long lessonId, String searchPhrase, Integer limit, Integer offset, + boolean orderAscending) { + return lessonDAO.getLearnersByLesson(lessonId, searchPhrase, limit, offset, orderAscending); } - + @Override public Integer getCountLessonLearners(Long lessonId, String searchPhrase) { return lessonDAO.getCountLearnersByLesson(lessonId, searchPhrase); @@ -546,7 +548,8 @@ LessonService.log.debug("Setting learner progress to uncompleted for lesson " + lessonId); } int count = 0; - List progresses = learnerProgressDAO.getCompletedLearnerProgressForLesson(lessonId); + List progresses = learnerProgressDAO.getCompletedLearnerProgressForLesson(lessonId, null, null, + true); Activity firstAddedActivity = (Activity) baseDAO.find(Activity.class, firstAddedActivityId); for (LearnerProgress progress : progresses) { Index: lams_monitoring/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -ra1312b563d80489f36f43ee0432d2a9197e1f0b8 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_monitoring/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision a1312b563d80489f36f43ee0432d2a9197e1f0b8) +++ lams_monitoring/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -278,9 +278,12 @@ force.complete.activity.confirm =Are you sure you want to move learner "[0]" to activity "[1]"? force.complete.drop.fail =You have dropped the learner "[0]" on either its current or on its completed activity "[1]". force.complete.end.lesson.tooltip =To move a learner to the end of lesson, drag the learner icon over to this bar. -learner.group.list.title =Learners: learner.group.count =learners in total. learner.group.show =Double-click to see the full list. +learner.group.forward.1 =Next page +learner.group.forward.10 =10 pages forward +learner.group.backward.1 =Previous page +learner.group.backward.10 =10 pages back learner.finished.count =Finished Learners: [0] of [1] learner.finished.dialog.title =End of lesson learner.group.sort.button =Sort Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java (.../IMonitoringService.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java (.../IMonitoringService.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -700,7 +700,7 @@ /** * Get learners who are at the given activities at the moment. */ - List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset); + List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset, boolean orderAscending); /** * Get number of learners whose first name, last name or login match any of the tokens from search phrase. @@ -744,5 +744,5 @@ /** * Get list of users who completed the given lesson. */ - List getUsersCompletedLesson(Long lessonId); + List getUsersCompletedLesson(Long lessonId, Integer limit, Integer offset, boolean orderAscending); } Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -1553,13 +1553,13 @@ case MonitoringConstants.LESSON_TYPE_HAVENT_FINISHED_LESSON: Set allUsers = lesson.getAllLearners(); - List usersCompletedLesson = getUsersCompletedLesson(lessonId); + List usersCompletedLesson = getUsersCompletedLesson(lessonId, null, null, true); users = CollectionUtils.subtract(allUsers, usersCompletedLesson); break; case MonitoringConstants.LESSON_TYPE_HAVE_FINISHED_LESSON: case MonitoringConstants.COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON: - users = getUsersCompletedLesson(lessonId); + users = getUsersCompletedLesson(lessonId, null, null, true); break; case MonitoringConstants.LESSON_TYPE_HAVENT_STARTED_LESSON: @@ -1619,7 +1619,7 @@ int i = 0; for (String lessonIdStr : lessonIds) { lessonId = Long.parseLong(lessonIdStr); - List completedLesson = getUsersCompletedLesson(lessonId); + List completedLesson = getUsersCompletedLesson(lessonId, null, null, true); if (i++ == 0) { users = completedLesson; } else { @@ -1641,7 +1641,7 @@ // subtract the ones which have completed any of the selected lessons for (String lessonIdStr : lessonIds) { lessonId = Long.parseLong(lessonIdStr); - List completedLesson = getUsersCompletedLesson(lessonId); + List completedLesson = getUsersCompletedLesson(lessonId, null, null, true); users = CollectionUtils.subtract(users, completedLesson); } break; @@ -1667,11 +1667,11 @@ * @return */ @Override - public List getUsersCompletedLesson(Long lessonId) { + public List getUsersCompletedLesson(Long lessonId, Integer limit, Integer offset, boolean orderAscending) { List usersCompletedLesson = new LinkedList(); List completedLearnerProgresses = learnerProgressDAO - .getCompletedLearnerProgressForLesson(lessonId); + .getCompletedLearnerProgressForLesson(lessonId, limit, offset, orderAscending); for (LearnerProgress learnerProgress : completedLearnerProgresses) { usersCompletedLesson.add(learnerProgress.getUser()); } @@ -2360,8 +2360,8 @@ } @Override - public List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset) { - return learnerProgressDAO.getLearnersByActivities(activityIds, limit, offset); + public List getLearnersByActivities(Long[] activityIds, Integer limit, Integer offset, boolean orderAscending) { + return learnerProgressDAO.getLearnersByActivities(activityIds, limit, offset, orderAscending); } @Override Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringAction.java =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringAction.java (.../MonitoringAction.java) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringAction.java (.../MonitoringAction.java) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -656,64 +656,71 @@ return null; } + /** + * Get learners who are part of the lesson class. + */ public ActionForward getLessonLearners(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response) throws IOException { - String wddxPacket; - try { - Long lessonID = new Long(WebUtil.readLongParam(request, "lessonID")); - wddxPacket = getMonitoringService().getLessonLearners(lessonID, getUserId()); - } catch (Exception e) { - wddxPacket = handleException(e, "getLessonLearners").serializeMessage(); + HttpServletResponse response) throws IOException, JSONException { + Integer pageNumber = WebUtil.readIntParam(request, "pageNumber", true); + if (pageNumber == null) { + pageNumber = 1; } - PrintWriter writer = response.getWriter(); - writer.println(wddxPacket); + boolean orderAscending = WebUtil.readBooleanParam(request, "orderAscending", true); + long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + List learners = getLessonService().getLessonLearners(lessonId, null, 10, (pageNumber - 1) * 10, + orderAscending); + JSONArray learnersJSON = new JSONArray(); + for (User learner : learners) { + learnersJSON.put(WebUtil.userToJSON(learner)); + } + + Integer learnerCount = getMonitoringService().getCountLearnersCompletedLesson(lessonId); + + JSONObject responseJSON = new JSONObject(); + responseJSON.put("learners", learnersJSON); + responseJSON.put("learnerCount", learnerCount); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write(responseJSON.toString()); return null; } /** - * Gets learners or monitors of either the lesson only or the lesson and organisation containing it. + * Gets learners or monitors of the lesson and organisation containing it. */ @SuppressWarnings("unchecked") public ActionForward getClassMembers(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException { long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); String role = WebUtil.readStrParam(request, AttributeNames.PARAM_ROLE); boolean getMonitors = Role.MONITOR.equalsIgnoreCase(role); - boolean classOnly = WebUtil.readBooleanParam(request, "classOnly", true); Lesson lesson = getLessonService().getLesson(lessonId); Set classUsers = getMonitors ? lesson.getLessonClass().getStaffGroup().getUsers() : lesson.getLessonClass().getLearners(); JSONArray responseJSON = new JSONArray(); - // get class members for (User user : classUsers) { JSONObject userJSON = WebUtil.userToJSON(user); - if (!classOnly) { // mark that this user is a class member userJSON.put("classMember", true); if (lesson.getUser().equals(user)) { // mark this user is lesson author userJSON.put("lessonCreator", true); } - } responseJSON.put(userJSON); } - // add non-class, organisation members, if requested - if (!classOnly) { IUserManagementService userManagementService = MonitoringServiceProxy .getUserManagementService(getServlet().getServletContext()); List orgUsers = userManagementService.getUsersFromOrganisationByRole( - lesson.getOrganisation().getOrganisationId(), getMonitors ? Role.MONITOR : Role.LEARNER, false, - true); + lesson.getOrganisation().getOrganisationId(), getMonitors ? Role.MONITOR : Role.LEARNER, false, true); for (User user : orgUsers) { if (!classUsers.contains(user)) { JSONObject userJSON = WebUtil.userToJSON(user); userJSON.put("classMember", false); responseJSON.put(userJSON); } } - } response.setContentType("application/json;charset=utf-8"); response.getWriter().write(responseJSON.toString()); @@ -725,15 +732,25 @@ */ public ActionForward getCurrentLearners(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException { - JSONArray responseJSON = new JSONArray(); + JSONArray learnersJSON = new JSONArray(); + Integer learnerCount = null; + + Integer pageNumber = WebUtil.readIntParam(request, "pageNumber", true); + if (pageNumber == null) { + pageNumber = 1; + } + boolean orderAscending = WebUtil.readBooleanParam(request, "orderAscending", true); // if activity ID is provided, lesson ID is ignored Long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID, true); if (activityId == null) { long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); - List learners = getMonitoringService().getUsersCompletedLesson(lessonId); + List learners = getMonitoringService().getUsersCompletedLesson(lessonId, 10, (pageNumber - 1) * 10, + orderAscending); for (User learner : learners) { - responseJSON.put(WebUtil.userToJSON(learner)); + learnersJSON.put(WebUtil.userToJSON(learner)); } + + learnerCount = getMonitoringService().getCountLearnersCompletedLesson(lessonId); } else { boolean flaFormat = WebUtil.readBooleanParam(request, "flaFormat", true); Activity activity = getMonitoringService().getActivityById(activityId); @@ -750,12 +767,17 @@ } List learners = getMonitoringService().getLearnersByActivities(activities.toArray(new Long[] {}), - null, null); + null, null, orderAscending); for (User learner : learners) { - responseJSON.put(WebUtil.userToJSON(learner)); + learnersJSON.put(WebUtil.userToJSON(learner)); } + + learnerCount = getMonitoringService().getCountLearnersCurrentActivity(activity); } + JSONObject responseJSON = new JSONObject(); + responseJSON.put("learners", learnersJSON); + responseJSON.put("learnerCount", learnerCount); response.setContentType("application/json;charset=utf-8"); response.getWriter().write(responseJSON.toString()); return null; @@ -986,7 +1008,7 @@ // either sort by name or how much a learner progressed into the lesson List learners = isProgressSorted ? getMonitoringService().getLearnersByMostProgress(lessonId, searchPhrase, 10, (pageNumber - 1) * 10) - : getLessonService().getLessonLearners(lessonId, searchPhrase, 10, (pageNumber - 1) * 10); + : getLessonService().getLessonLearners(lessonId, searchPhrase, 10, (pageNumber - 1) * 10, true); JSONObject responseJSON = new JSONObject(); for (User learner : learners) { responseJSON.append("learners", WebUtil.userToJSON(learner)); @@ -1277,7 +1299,7 @@ long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); String searchPhrase = request.getParameter("term"); - List learners = getLessonService().getLessonLearners(lessonId, searchPhrase, 10, null); + List learners = getLessonService().getLessonLearners(lessonId, searchPhrase, 10, null, true); JSONArray responseJSON = new JSONArray(); for (User learner : learners) { JSONObject learnerJSON = new JSONObject(); Index: lams_monitoring/web/css/monitorLesson.css =================================================================== diff -u -r184121401ec92fa82a32c0f5b1f094d30dc4699e -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_monitoring/web/css/monitorLesson.css (.../monitorLesson.css) (revision 184121401ec92fa82a32c0f5b1f094d30dc4699e) +++ lams_monitoring/web/css/monitorLesson.css (.../monitorLesson.css) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -78,6 +78,28 @@ cursor: pointer; } +#learnerGroupDialog td { + padding: 0; +} + +#learnerGroupDialog td.learnerGroupNav { + padding: 5px 0; + cursor: pointer; +} + +#learnerGroupDialog td.learnerGroupNav:hover { + background-color: #D0E5F5; +} + +td.learnerGroupNav span { + margin: auto; +} + +#learnerGroupPage { + text-align: center; + width: 100px; +} + /********** LESSON TAB STYLES **********/ div#tabLesson { /* height: 540px;*/ @@ -196,7 +218,7 @@ margin: 6px 5px 5px 0; } -.topButtonsContainer #sequenceSearchPhraseLabel { +.topButtonsContainer #sequenceSearchPhraseIcon { float: right; margin: 9px 7px 5px 0; } @@ -237,16 +259,32 @@ border-right: thin solid #2E6E9E; } -#learnersSearchPhraseCell img { +#learnersSearchPhraseIcon { + margin-left: auto; + margin-right: auto; + margin-bottom: 4px; +} + +#learnersSearchPhrase { + width: 80%; +} + +#learnersSearchPhraseClear { cursor: pointer; - vertical-align: middle; + float: right; + margin: 3px 2px 0 0; + display: none; } -td.learnersHeaderPageCell,td.learnersPageShifter { +td.learnersHeaderPageCell, td.learnersPageShifter { min-width: 25px; cursor: pointer; } +td.learnersPageShifter span { + margin: auto; +} + td.learnersHeaderPageCell:hover,td.learnersPageShifter:hover { background-color: #D0E5F5; } Index: lams_monitoring/web/includes/javascript/monitorLesson.js =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_monitoring/web/includes/javascript/monitorLesson.js (.../monitorLesson.js) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_monitoring/web/includes/javascript/monitorLesson.js (.../monitorLesson.js) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -15,7 +15,6 @@ sequenceSearchedLearner = null, // how learners in pop up lists are currently sorted sortOrderAsc = { - learnerGroup : false, classLearner : false, classMonitor : false }, @@ -201,8 +200,8 @@ // reset sort order sortOrderAsc['classLearner'] = false; sortOrderAsc['classMonitor'] = false; - sortDialogList('classLearner'); - sortDialogList('classMonitor'); + sortLessonClassDialogList('classLearner'); + sortLessonClassDialogList('classMonitor'); colorDialogList('classLearner'); colorDialogList('classMonitor'); @@ -267,13 +266,6 @@ ] }); - $('#classLearnerSortButton').click(function(){ - sortDialogList('classLearner'); - }); - $('#classMonitorSortButton').click(function(){ - sortDialogList('classMonitor'); - }); - // sets up dialog for emailing learners $('#emailDialog').dialog({ 'autoOpen' : false, @@ -301,20 +293,15 @@ * Shows all learners in the lesson class. */ function showLessonLearnersDialog() { - $.ajax({ - dataType : 'json', + var ajaxProperties = { url : LAMS_URL + 'monitoring/monitoring.do', - cache : false, data : { - 'method' : 'getClassMembers', - 'lessonID' : lessonId, - 'role' : 'LEARNER', - 'classOnly' : true - }, - success : function(response) { - showLearnerGroupDialog(null, LABELS.LESSON_GROUP_DIALOG_CLASS, response, false, false, true); + 'method' : 'getLessonLearners', + 'lessonID' : lessonId } - }); + }; + + showLearnerGroupDialog(ajaxProperties, LABELS.LESSON_GROUP_DIALOG_CLASS, false, false, true); } /** @@ -610,18 +597,14 @@ $('#learnerGroupDialog').dialog({ 'autoOpen' : false, 'height' : 360, - 'width' : 330, - 'minWidth' : 330, + 'width' : 400, + 'minWidth' : 400, 'modal' : true, 'resizable' : true, 'show' : 'fold', 'hide' : 'fold', 'open' : function(){ autoRefreshBlocked = true; - // reset sort order - sortOrderAsc['learnerGroup'] = false; - sortDialogList('learnerGroup'); - colorDialogList('learnerGroup'); // until operator selects an user, buttons remain disabled $('button.learnerGroupDialogSelectableButton').blur().removeClass('ui-state-hover') .attr('disabled', 'disabled'); @@ -639,7 +622,7 @@ // make sure there is only one selected learner if (selectedLearner.length == 1) { // go to "force complete" mode, similar to draggin user to an activity - var activityId = $(this).dialog('option', 'activityId'), + var activityId = $(this).dialog('option', 'ajaxProperties').data.activityID, dropArea = sequenceCanvas.add('#completedLearnersContainer'); dropArea.css('cursor', 'url(' + LAMS_URL + 'images/icons/user.png),pointer') @@ -686,10 +669,6 @@ ] }); - $('#learnerGroupSortButton').click(function(){ - sortDialogList('learnerGroup'); - }); - // small info box on Sequence tab, activated when the tab is showed $('#sequenceInfoDialog').dialog({ 'autoOpen' : false, @@ -1210,7 +1189,15 @@ dblTap(learnerGroup, function(event){ // double click on learner group icon to see list of learners event.stopPropagation(); - showLearnerGroupDialog(activity.id, activity.title, null, true, usersViewable, false); + var ajaxProperties = { + url : LAMS_URL + 'monitoring/monitoring.do', + data : { + 'method' : 'getCurrentLearners', + 'activityID' : activity.id, + 'flaFormat' : flaFormat + } + }; + showLearnerGroupDialog(ajaxProperties, activity.title, true, usersViewable, false); }); } @@ -1279,7 +1266,14 @@ }).css('cursor', 'pointer').appendTo(iconsContainer); dblTap(groupIcon, function(){ - showLearnerGroupDialog(null, LABELS.LEARNER_FINISHED_DIALOG_TITLE, null, true, false, false); + var ajaxProperties = { + url : LAMS_URL + 'monitoring/monitoring.do', + data : { + 'method' : 'getCurrentLearners', + 'lessonID' : lessonId + } + }; + showLearnerGroupDialog(ajaxProperties, LABELS.LEARNER_FINISHED_DIALOG_TITLE, true, false, false); }); } } @@ -1410,8 +1404,7 @@ data : { 'method' : 'getClassMembers', 'lessonID' : lessonId, - 'role' : 'LEARNER', - 'classOnly' : false + 'role' : 'LEARNER' }, success : function(response) { learners = response; @@ -1425,8 +1418,7 @@ data : { 'method' : 'getClassMembers', 'lessonID' : lessonId, - 'role' : 'MONITOR', - 'classOnly' : false + 'role' : 'MONITOR' }, success : function(response) { monitors = response; @@ -1595,6 +1587,7 @@ 'select' : function(event, ui){ // learner's ID in ui.item.value is not used here $(this).val(ui.item.label); + $('#learnersSearchPhraseClear').show(); loadLearnerProgressPage(1, ui.item.label); return false; } @@ -1603,6 +1596,9 @@ .keypress(function(e){ if (e.which == 13) { $(this).autocomplete("close"); + if ($(this).val()) { + $('#learnersSearchPhraseClear').show(); + } loadLearnerProgressPage(1); } }); @@ -1626,8 +1622,8 @@ * Do the actual shifting of page numbers bar. */ function shiftLearnerProgressPageHeader(startIndex, endIndex) { - var pageLeftCell = $('#learnersPageLeft'), - pageCount = Math.ceil(learnerPossibleNumber / 10); + var pageLeftCell = $('#learnersPageLeft'); + var pageCount = Math.ceil(learnerPossibleNumber / 10); $('#tabLearnerControlTable td.learnersHeaderPageCell').remove(); if (startIndex < 1) { @@ -1803,6 +1799,7 @@ function learnersClearSearchPhrase(){ $('#learnersSearchPhrase').val('').autocomplete("close"); loadLearnerProgressPage(1, ''); + $('#learnersSearchPhraseClear').hide(); } //********** COMMON FUNCTIONS ********** @@ -1853,32 +1850,93 @@ /** * Show a dialog with user list and optional Force Complete and View Learner buttons. */ -function showLearnerGroupDialog(activityId, dialogTitle, learners, allowForceComplete, allowView, allowEmail) { - var learnerGroupList = $('#learnerGroupList').empty(), - learnerGroupDialog = $('#learnerGroupDialog'); +function showLearnerGroupDialog(ajaxProperties, dialogTitle, allowForceComplete, allowView, allowEmail) { + var learnerGroupDialog = $('#learnerGroupDialog'), + learnerGroupList = $('#learnerGroupList', learnerGroupDialog).empty(), + // no parameters provided? just work on what we saved + isRefresh = ajaxProperties == null, + learners = null, + learnerCount = null; - if (!learners) { - $.ajax({ + if (isRefresh) { + // ajax and other properties were saved when the dialog was opened + ajaxProperties = learnerGroupDialog.dialog('option', 'ajaxProperties'); + allowForceComplete = learnerGroupDialog.dialog('option', 'allowForceComplete'); + allowView = learnerGroupDialog.dialog('option', 'allowView'); + allowEmail = learnerGroupDialog.dialog('option', 'allowEmail'); + } else { + // add few standard properties to ones provided by method calls + ajaxProperties = $.extend(true, ajaxProperties, { dataType : 'json', - url : LAMS_URL + 'monitoring/monitoring.do', cache : false, async : false, data : { - 'method' : 'getCurrentLearners', - 'lessonID' : lessonId, - // activity ID can be null; if it is not, lesson ID is ignored - 'activityID' : activityId, - 'flaFormat' : flaFormat - }, - success : function(response) { - learners = response; + 'pageNumber' : 1, + 'orderAscending' : true } }); } + var pageNumber = ajaxProperties.data.pageNumber; + + // set values for current variable instances + ajaxProperties.success = function(response) { + learners = response.learners; + learnerCount = response.learnerCount; + }; + + // make the call + $.ajax(ajaxProperties); + + // did all users already drift away to an another activity or there was an error? + // close the dialog and refresh the main screen + if (!learnerCount) { + if (isRefresh) { + learnerGroupDialog.dialog('close'); + } + updateSequenceTab(); + return; + } + + // did some users already drift away to an another activity? + // move back until you get a page with any users + var maxPageNumber = Math.ceil(learnerCount / 10); + if (pageNumber > maxPageNumber) { + shiftLearnerGroup(-1); + return; + } + + // hide unnecessary controls + if (pageNumber + 10 <= maxPageNumber) { + $('#learnerGroupPagePlus10', learnerGroupDialog).css('visibility', 'visible'); + } else { + $('#learnerGroupPagePlus10', learnerGroupDialog).css('visibility', 'hidden'); + } + if (pageNumber - 10 < 1) { + $('#learnerGroupPageMinus10', learnerGroupDialog).css('visibility', 'hidden'); + } else { + $('#learnerGroupPageMinus10', learnerGroupDialog).css('visibility', 'visible'); + } + if (pageNumber + 1 <= maxPageNumber) { + $('#learnerGroupPagePlus1', learnerGroupDialog).css('visibility', 'visible'); + } else { + $('#learnerGroupPagePlus1', learnerGroupDialog).css('visibility', 'hidden'); + } + if (pageNumber - 1 < 1) { + $('#learnerGroupPageMinus1', learnerGroupDialog).css('visibility', 'hidden'); + } else { + $('#learnerGroupPageMinus1', learnerGroupDialog).css('visibility', 'visible'); + } + if (maxPageNumber < 2) { + $('#learnerGroupPage', learnerGroupDialog).css('visibility', 'hidden'); + } else { + $('#learnerGroupPage', learnerGroupDialog).css('visibility', 'visible').text(pageNumber + ' / ' + maxPageNumber); + } + $.each(learners, function(learnerIndex, learner) { - var viewUrl = LAMS_URL + 'monitoring/monitoring.do?method=getLearnerActivityURL&userID=' - + learner.id + '&activityID=' + activityId + '&lessonID=' + lessonId, + var viewUrl = allowView ? LAMS_URL + 'monitoring/monitoring.do?method=getLearnerActivityURL&userID=' + + learner.id + '&activityID=' + ajaxProperties.data.activityID + '&lessonID=' + lessonId + : null, learnerDiv = $('
').attr({ 'userId' : learner.id, 'viewUrl' : viewUrl @@ -1906,6 +1964,9 @@ } }); + colorDialogList('learnerGroup'); + + if (!isRefresh) { // show buttons depending on parameters $('button#learnerGroupDialogForceCompleteButton') .css('display', allowForceComplete ? 'inline' : 'none'); @@ -1918,10 +1979,15 @@ .dialog('option', { 'title' : dialogTitle, - 'activityId' : activityId + // save properties for refresh + 'ajaxProperties' : ajaxProperties, + 'allowForceComplete' : allowForceComplete, + 'allowView' : allowView, + 'allowEmail' : allowEmail }) .dialog('open'); } +} /** @@ -1951,12 +2017,12 @@ /** - * Change order of learner sorting in group dialog. + * Change order of learner sorting in class dialog. */ -function sortDialogList(listId) { - var list = $('#' + listId + 'List'); - var items = list.children('div.dialogListItem'); - var orderAsc = sortOrderAsc[listId]; +function sortLessonClassDialogList(listId) { + var list = $('#' + listId + 'List'), + items = list.children('div.dialogListItem'), + orderAsc = sortOrderAsc[listId]; if (items.length > 1) { items.each(function(){ $(this).detach(); @@ -1980,6 +2046,27 @@ } } +/** + * Change order of learner sorting in group dialog. + */ +function sortLearnerGroupDialogList() { + var learnerGroupDialog = $('#learnerGroupDialog'), + sortIcon = $('#learnerGroupSort span', learnerGroupDialog), + ajaxProperties = learnerGroupDialog.dialog('option', 'ajaxProperties'), + // reverse current order after click + orderAscending = !ajaxProperties.data.orderAscending; + + if (orderAscending) { + sortIcon.removeClass('ui-icon-triangle-1-s').addClass('ui-icon-triangle-1-n'); + } else { + sortIcon.removeClass('ui-icon-triangle-1-n').addClass('ui-icon-triangle-1-s'); + } + + ajaxProperties.data.orderAscending = orderAscending; + // refresh the list + showLearnerGroupDialog(); +} + function selectAllInDialogList(listId) { var targetState = $('#' + listId + 'SelectAll').is(':checked') ? 'checked' : null; $('#' + listId + 'List input').each(function(){ @@ -1997,7 +2084,22 @@ }); } +/** +* Change page in the group dialog. +*/ +function shiftLearnerGroupList(shift) { + var learnerGroupDialog = $('#learnerGroupDialog'), + ajaxProperties = learnerGroupDialog.dialog('option', 'ajaxProperties'), + pageNumber = ajaxProperties.data.pageNumber + shift; + if (pageNumber < 0) { + pageNumber = 1; + } + ajaxProperties.data.pageNumber = pageNumber; + // refresh the dialog with new parameters + showLearnerGroupDialog(); +} + /** * Makes a XML element with given attributes. * jQuery does not work well with SVG in Chrome, so all this manipulation need to be done manually. Index: lams_monitoring/web/monitor.jsp =================================================================== diff -u -r8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9 -r2f67a20e73128f03e7b4221ca09426c14bef2abf --- lams_monitoring/web/monitor.jsp (.../monitor.jsp) (revision 8cb13884a046af1fee45dc7ab6e6f5a7f21c07c9) +++ lams_monitoring/web/monitor.jsp (.../monitor.jsp) (revision 2f67a20e73128f03e7b4221ca09426c14bef2abf) @@ -69,8 +69,6 @@ LEARNER_GROUP_SHOW : '', LEARNER_GROUP_REMOVE_PROGRESS : decoderDiv.html('').text(), - - LEARNER_GROUP_LIST_TITLE : '', VIEW_LEARNER_BUTTON : '', @@ -433,13 +431,16 @@ onClick="javascript:closeBranchingSequence()"> - - - + > + +
@@ -458,20 +459,28 @@
- -
- - + + + + - << - + >> + >
-
- - -
-
+ + + + + + + + + + + +
+ + + + + + + + + + +
@@ -514,12 +556,14 @@ + title="" + click="javascript:sortLessonClassDialogList('classLearner')">▲ + title="" + click="javascript:sortLessonClassDialogList('classMonitor')">▲