Index: lams_build/lib/lams/lams.jar =================================================================== RCS file: /usr/local/cvsroot/lams_build/lib/lams/lams.jar,v diff -u -r1.420.2.78 -r1.420.2.79 Binary files differ Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgress.hbm.xml =================================================================== RCS file: /usr/local/cvsroot/lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgress.hbm.xml,v diff -u -r1.1.10.2 -r1.1.10.3 --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgress.hbm.xml 15 Oct 2014 07:48:47 -0000 1.1.10.2 +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgress.hbm.xml 21 Jun 2016 10:25:32 -0000 1.1.10.3 @@ -4,13 +4,6 @@ "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > - - Fisheye: Tag 1.2.2.1 refers to a dead (removed) revision in file `lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.hbm.xml'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.1.2.1 refers to a dead (removed) revision in file `lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/LearnerProgressArchive.hbm.xml'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040064.sql =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040064.sql,v diff -u -r1.1.2.1 -r1.1.2.2 Binary files differ Fisheye: Tag 1.1.2.1 refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.1.2.1 refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/lesson/LearnerProgressArchive.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.1.12.3 refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/lesson/ProgressCompletedActivity.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java,v diff -u -r1.15.2.13 -r1.15.2.14 --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java 11 May 2016 07:07:29 -0000 1.15.2.13 +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java 21 Jun 2016 10:25:32 -0000 1.15.2.14 @@ -150,8 +150,8 @@ List getLearnersAttemptedActivity(Activity activity); /** - * Get all the users records where the user has ever attempted the given activity. Uses the progress records to - * determine the users. + * Get all the users records where the user has completed the given activity. Uses the progress records to determine + * the users. */ List getLearnersCompletedActivity(Activity activity); @@ -196,4 +196,9 @@ * Get number of learners who are at the given activities at the moment. */ Map getNumUsersCurrentActivities(Long[] activityIds); + + /** + * Get the last attempt ID for the given learner and lesson. + */ + Integer getLearnerProgressArchiveMaxAttemptID(Integer userId, Long lessonId); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java,v diff -u -r1.19.2.13 -r1.19.2.14 --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java 11 May 2016 07:07:28 -0000 1.19.2.13 +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java 21 Jun 2016 10:25:32 -0000 1.19.2.14 @@ -47,9 +47,11 @@ protected Logger log = Logger.getLogger(LearnerProgressDAO.class); - private final static String LOAD_PROGRESS_BY_LEARNER = "from LearnerProgress p where p.user.id = :learnerId and p.lesson.id = :lessonId"; + private final static String LOAD_PROGRESS_BY_LEARNER = "from LearnerProgress p where p.user.id = :learnerId " + + "and p.lesson.id = :lessonId"; - 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_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 ORDER BY p.user.firstName , p.user.lastName , p.user.login "; @@ -75,7 +77,8 @@ + " index(compAct) = act"; private final static String COUNT_CURRENT_ACTIVITY = "select prog.currentActivity.activityId, count(prog) " - + "from LearnerProgress prog WHERE prog.currentActivity.activityId IN (:activityIds) GROUP BY prog.currentActivity.activityId"; + + "from LearnerProgress prog WHERE prog.currentActivity.activityId IN (:activityIds) " + + "GROUP BY prog.currentActivity.activityId"; private final static String LOAD_PROGRESS_BY_LESSON = "from LearnerProgress p " + " where p.lesson.id = :lessonId order by p.user.lastName, p.user.firstName, p.user.userId"; @@ -110,6 +113,9 @@ private final static String LOAD_LEARNERS_BY_MOST_PROGRESS_ORDER_CLAUSE = " GROUP BY u.user_id " + "ORDER BY prog.lesson_completed_flag DESC, comp_count DESC, u.first_name ASC, u.last_name ASC, u.login ASC"; + private final static String FIND_PROGRESS_ARCHIVE_MAX_ATTEMPT = "SELECT MAX(p.attemptId) FROM LearnerProgressArchive p " + + "WHERE p.user.id = :learnerId AND p.lesson.id = :lessonId"; + @Override public LearnerProgress getLearnerProgress(Long learnerProgressId) { return (LearnerProgress) getSession().get(LearnerProgress.class, learnerProgressId); @@ -338,4 +344,11 @@ } return result; } + + @Override + public Integer getLearnerProgressArchiveMaxAttemptID(Integer userId, Long lessonId) { + Object value = getSession().createQuery(LearnerProgressDAO.FIND_PROGRESS_ARCHIVE_MAX_ATTEMPT) + .setInteger("learnerId", userId).setLong("lessonId", lessonId).uniqueResult(); + return value == null ? null : ((Number) value).intValue(); + } } \ No newline at end of file Index: lams_learning/.classpath =================================================================== RCS file: /usr/local/cvsroot/lams_learning/.classpath,v diff -u -r1.12.2.9 -r1.12.2.10 --- lams_learning/.classpath 29 Jan 2016 08:41:39 -0000 1.12.2.9 +++ lams_learning/.classpath 21 Jun 2016 10:25:33 -0000 1.12.2.10 @@ -20,5 +20,6 @@ + Index: lams_learning/conf/language/lams/ApplicationResources.properties =================================================================== RCS file: /usr/local/cvsroot/lams_learning/conf/language/lams/ApplicationResources.properties,v diff -u -r1.59.2.3 -r1.59.2.4 --- lams_learning/conf/language/lams/ApplicationResources.properties 11 May 2016 07:07:35 -0000 1.59.2.3 +++ lams_learning/conf/language/lams/ApplicationResources.properties 21 Jun 2016 10:25:33 -0000 1.59.2.4 @@ -14,6 +14,8 @@ message.activity.loading =The next task is loading. Please wait.... message.lesson.finished =Congratulations, {0}, you have finished. message.lesson.finishedCont =You have now completed the {0} lesson. You can return at anytime to this lesson and revisit and review activities by double clicking on the blue icons in the left hand progress bar. You can now close this window. +message.lesson.restart =You can give the lesson another an attempt by pressing this button: +message.lesson.restart.button =Restart exit.heading =You have exited from this Lesson. exit.message =You can resume this lesson using the Resume button. label.next.button =Next Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java,v diff -u -r1.18.10.6 -r1.18.10.7 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java 11 May 2016 07:07:36 -0000 1.18.10.6 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java 21 Jun 2016 10:25:33 -0000 1.18.10.7 @@ -91,6 +91,11 @@ * in case of problems. */ LearnerProgress getProgress(Integer learnerId, Long lessonId); + + /** + * Get the last attempt ID for the given learner and lesson. + */ + Integer getProgressArchiveMaxAttemptID(Integer userId, Long lessonId); /** * Returns the current progress data, in the DTO format required by the jsp progress screen, of the User. Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java,v diff -u -r1.112.2.10 -r1.112.2.11 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java 11 May 2016 07:07:36 -0000 1.112.2.10 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java 21 Jun 2016 10:25:33 -0000 1.112.2.11 @@ -383,6 +383,11 @@ public LearnerProgress getProgressById(Long progressId) { return learnerProgressDAO.getLearnerProgress(progressId); } + + @Override + public Integer getProgressArchiveMaxAttemptID(Integer userId, Long lessonId) { + return learnerProgressDAO.getLearnerProgressArchiveMaxAttemptID(userId, lessonId); + } /** * @see org.lamsfoundation.lams.learning.service.ICoreLearnerService#getStructuredProgressDTOs(java.lang.Long, Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerServiceProxy.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerServiceProxy.java,v diff -u -r1.8.16.2 -r1.8.16.3 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerServiceProxy.java 11 May 2016 07:07:36 -0000 1.8.16.2 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerServiceProxy.java 21 Jun 2016 10:25:33 -0000 1.8.16.3 @@ -27,6 +27,7 @@ import javax.servlet.ServletContext; import org.lamsfoundation.lams.learning.web.util.ActivityMapping; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.springframework.web.context.WebApplicationContext; @@ -81,6 +82,10 @@ return (ILamsToolService) LearnerServiceProxy.getDomainService(serlvetContext, "lamsToolService"); } + public static final IMonitoringService getMonitoringService(ServletContext servletContext) { + return (IMonitoringService) LearnerServiceProxy.getDomainService(servletContext, "monitoringService"); + } + /** * Return the activity mapping service object. * Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java,v diff -u -r1.17.12.5 -r1.17.12.6 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java 11 May 2016 07:07:36 -0000 1.17.12.5 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java 21 Jun 2016 10:25:33 -0000 1.17.12.6 @@ -89,6 +89,7 @@ if (lessonFinishCallbackUrl != null) { request.setAttribute("lessonFinishUrl", lessonFinishCallbackUrl); } + request.setAttribute("lessonID", progress.getLesson().getLessonId()); } ActionForward forward = null; Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java,v diff -u -r1.52.2.11 -r1.52.2.12 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java 7 Jun 2016 09:00:40 -0000 1.52.2.11 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java 21 Jun 2016 10:25:33 -0000 1.52.2.12 @@ -24,7 +24,11 @@ package org.lamsfoundation.lams.learning.web.action; import java.io.IOException; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -44,10 +48,15 @@ import org.lamsfoundation.lams.learning.web.util.ActivityMapping; import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.lesson.CompletedActivityProgress; +import org.lamsfoundation.lams.lesson.CompletedActivityProgressArchive; import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.lesson.LearnerProgressArchive; import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.Configuration; import org.lamsfoundation.lams.util.ConfigurationKeys; import org.lamsfoundation.lams.util.WebUtil; @@ -172,6 +181,53 @@ } /** + * Archives current learner progress and moves a learner back to the start of lesson. + */ + public ActionForward restartLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // fetch necessary parameters + long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + User user = LearningWebUtil.getUser(learnerService); + Integer userID = user.getUserId(); + + // find number of previous attempts + Integer attemptID = learnerService.getProgressArchiveMaxAttemptID(userID, lessonID); + if (attemptID == null) { + attemptID = 0; + } + attemptID++; + + // make a copy of attempted and completed activities + LearnerProgress learnerProgress = learnerService.getProgress(userID, lessonID); + Map attemptedActivities = new HashMap(learnerProgress.getAttemptedActivities()); + Map completedActivities = new HashMap(); + for (Entry entry : learnerProgress.getCompletedActivities().entrySet()) { + CompletedActivityProgressArchive activityArchive = new CompletedActivityProgressArchive(learnerProgress, + entry.getKey(), entry.getValue().getStartDate(), entry.getValue().getFinishDate()); + completedActivities.put(entry.getKey(), activityArchive); + } + + // save the historic attempt + LearnerProgressArchive learnerProgressArchive = new LearnerProgressArchive(user, learnerProgress.getLesson(), + attemptID, attemptedActivities, completedActivities, learnerProgress.getCurrentActivity(), + learnerProgress.getLessonComplete(), learnerProgress.getStartDate(), learnerProgress.getFinishDate()); + + // move learner to the beginning of lesson the same way Monitor can + IMonitoringService monitoringService = LearnerServiceProxy + .getMonitoringService(getServlet().getServletContext()); + monitoringService.forceCompleteActivitiesByUser(userID, userID, lessonID, + learnerProgress.getLesson().getLearningDesign().getFirstActivity().getActivityId(), true); + + IUserManagementService userManagementService = LearnerServiceProxy + .getUserManagementService(getServlet().getServletContext()); + userManagementService.save(learnerProgressArchive); + + // display Learner interface with updated data + return joinLesson(mapping, form, request, response); + } + + /** * Produces necessary data for learner progress bar. */ @SuppressWarnings("unchecked") Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java,v diff -u -r1.7.2.4 -r1.7.2.5 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java 11 May 2016 07:07:36 -0000 1.7.2.4 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java 21 Jun 2016 10:25:33 -0000 1.7.2.5 @@ -84,6 +84,7 @@ if (lessonFinishCallbackUrl != null) { request.setAttribute("lessonFinishUrl", lessonFinishCallbackUrl); } + request.setAttribute("lessonID", learnerProgress.getLesson().getLessonId()); return mapping.findForward("lessonComplete"); } Index: lams_learning/web/lessonComplete.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_learning/web/lessonComplete.jsp,v diff -u -r1.26.2.2 -r1.26.2.3 --- lams_learning/web/lessonComplete.jsp 13 Mar 2016 05:37:52 -0000 1.26.2.2 +++ lams_learning/web/lessonComplete.jsp 21 Jun 2016 10:25:33 -0000 1.26.2.3 @@ -56,6 +56,13 @@ +
+ + + + +
+
Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java =================================================================== RCS file: /usr/local/cvsroot/lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java,v diff -u -r1.195.2.29 -r1.195.2.30 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java 11 May 2016 07:14:44 -0000 1.195.2.29 +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java 21 Jun 2016 10:25:31 -0000 1.195.2.30 @@ -989,7 +989,11 @@ @Override public String forceCompleteActivitiesByUser(Integer learnerId, Integer requesterId, long lessonId, Long activityId, boolean removeLearnerContent) { - securityService.isLessonMonitor(lessonId, requesterId, "force complete", true); + if (requesterId.equals(learnerId)) { + securityService.isLessonLearner(lessonId, requesterId, "force complete", true); + } else { + securityService.isLessonMonitor(lessonId, requesterId, "force complete", true); + } Lesson lesson = lessonDAO.getLesson(new Long(lessonId)); User learner = (User) baseDAO.find(User.class, learnerId);