Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -rc9aead8dc4d1f820cff644f7973adf5072a1bcf7 -r15045d0b9b0dbb930f42a9da7757207e7a325341 Binary files differ Index: lams_common/src/java/org/lamsfoundation/lams/tool/ToolContentManager.java =================================================================== diff -u -rc135649b64e98c9233da20bdcfb7689598116314 -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_common/src/java/org/lamsfoundation/lams/tool/ToolContentManager.java (.../ToolContentManager.java) (revision c135649b64e98c9233da20bdcfb7689598116314) +++ lams_common/src/java/org/lamsfoundation/lams/tool/ToolContentManager.java (.../ToolContentManager.java) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -76,6 +76,11 @@ */ public void removeToolContent(Long toolContentId, boolean removeSessionData) throws SessionDataExistsException, ToolException; + + /** + * Removes content previously added by the given user. + */ + public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException; /** * Export the XML fragment for the tool's content, along with any files needed for the content. Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java =================================================================== diff -u -rc135649b64e98c9233da20bdcfb7689598116314 -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java (.../ILamsCoreToolService.java) (revision c135649b64e98c9233da20bdcfb7689598116314) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java (.../ILamsCoreToolService.java) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -176,8 +176,13 @@ * @throws ToolException */ public void notifyToolToDeleteContent(ToolActivity toolActivity) throws ToolException; - + /** + * Ask a tool to delete content entered by the given user, if exists. + */ + public void notifyToolToDeleteLearnerContent(ToolActivity toolActivity, Integer userId) throws ToolException; + + /** * Ask a tool for its OutputDefinitions, based on the given toolContentId. If the tool doesn't have any content * matching the toolContentId then it should create the OutputDefinitions based on the tool's default content. * Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java =================================================================== diff -u -rc135649b64e98c9233da20bdcfb7689598116314 -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java (.../LamsCoreToolService.java) (revision c135649b64e98c9233da20bdcfb7689598116314) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java (.../LamsCoreToolService.java) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -268,6 +268,19 @@ throw new ToolException(message, e); } } + + @Override + public void notifyToolToDeleteLearnerContent(ToolActivity toolActivity, Integer userId) throws ToolException { + try { + ToolContentManager contentManager = (ToolContentManager) findToolService(toolActivity.getTool()); + contentManager.removeLearnerContent(toolActivity.getToolContentId(), userId); + } catch (NoSuchBeanDefinitionException e) { + String message = "A tool which is defined in the database appears to missing from the classpath. Unable to delete learner content. ToolActivity " + + toolActivity; + LamsCoreToolService.log.error(message, e); + throw new ToolException(message, e); + } + } @Override public SortedMap getOutputDefinitionsFromTool(Long toolContentId, int definitionType) Index: lams_monitoring/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r5b633ecc884b7d321a5164af26bfe268629a2d3f -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_monitoring/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 5b633ecc884b7d321a5164af26bfe268629a2d3f) +++ lams_monitoring/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -279,6 +279,9 @@ force.complete.click =Click on an activity to move learner "[0]" or outside any activity to cancel. force.complete.end.lesson.confirm =Are you sure you want to move learner "[0]" to the end of lesson? force.complete.activity.confirm =Are you sure you want to move learner "[0]" to activity "[1]"? +force.complete.remove.content =You are moving learner "[0]" to activity "[1]". You can opt to delete the content of activities that have been previously done, so the learner has to enter the content/answers again. +force.complete.remove.content.yes =Delete content +force.complete.remove.content.no =Keep content 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: Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/MonitoringConstants.java =================================================================== diff -u -r1d8bb6927b7d4341f8f5111179e53e1b1ee40d88 -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/MonitoringConstants.java (.../MonitoringConstants.java) (revision 1d8bb6927b7d4341f8f5111179e53e1b1ee40d88) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/MonitoringConstants.java (.../MonitoringConstants.java) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -41,6 +41,7 @@ public static final String PARAM_LESSON_START_DATE = "lessonStartDate"; public static final String PARAM_SCHEDULED_NUMBER_DAYS_TO_LESSON_FINISH = "scheduledNumberDaysToLessonFinish"; public static final String PARAM_LEARNER_ID = "learnerID"; + public static final String PARAM_REMOVE_LEARNER_CONTENT = "removeContent"; public static final String KEY_GROUPING_ACTIVITY = "groupingActivityID"; public static final String KEY_GROUPS = "groups"; public static final String KEY_GROUP_NAME = "groupName"; Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java =================================================================== diff -u -r40952c4f84fb81252c3ef18a3e1cc2c0d256622e -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java (.../IMonitoringService.java) (revision 40952c4f84fb81252c3ef18a3e1cc2c0d256622e) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java (.../IMonitoringService.java) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -75,8 +75,8 @@ public Lesson initializeLessonWithoutLDcopy(String lessonName, String lessonDescription, long learningDesignID, User user, String customCSV, Boolean enableLessonIntro, Boolean displayDesignImage, Boolean learnerExportAvailable, Boolean learnerPresenceAvailable, Boolean learnerImAvailable, - Boolean liveEditEnabled, Boolean enableLessonNotifications, Boolean learnerRestart, Integer scheduledNumberDaysToLessonFinish, - Lesson precedingLesson); + Boolean liveEditEnabled, Boolean enableLessonNotifications, Boolean learnerRestart, + Integer scheduledNumberDaysToLessonFinish, Lesson precedingLesson); /** * Initialize a new lesson so as to start the learning process. It needs to notify lams which learning design it @@ -281,7 +281,8 @@ */ public Boolean setLiveEditEnabled(long lessonId, Integer userId, Boolean liveEditEnabled); - public String forceCompleteActivitiesByUser(Integer learnerId, Integer requesterId, long lessonId, Long activityId); + public String forceCompleteActivitiesByUser(Integer learnerId, Integer requesterId, long lessonId, Long activityId, + boolean removeLearnerContent); /** * Archive the specified lesson. When archived, the data is retained but the learners cannot access the details. @@ -425,7 +426,7 @@ * @throws IOException */ public String getLearningDesignDetails(Long lessonID) throws IOException; - + public List getAllContributeActivityDTO(Long lessonID); /** Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java =================================================================== diff -u -r40952c4f84fb81252c3ef18a3e1cc2c0d256622e -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision 40952c4f84fb81252c3ef18a3e1cc2c0d256622e) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -1274,7 +1274,8 @@ * @see org.lamsfoundation.lams.monitoring.service.IMonitoringService#forceCompleteLessonByUser(Integer,long,long) */ @Override - public String forceCompleteActivitiesByUser(Integer learnerId, Integer requesterId, long lessonId, Long activityId) { + public String forceCompleteActivitiesByUser(Integer learnerId, Integer requesterId, long lessonId, Long activityId, + boolean removeLearnerContent) { Lesson lesson = lessonDAO.getLesson(new Long(lessonId)); checkOwnerOrStaffMember(requesterId, lesson, "force complete"); @@ -1308,7 +1309,7 @@ .getCompletedActivities().containsKey(parentActivity) || ((parentActivity .getParentActivity() != null) && learnerProgress.getCompletedActivities().containsKey( parentActivity.getParentActivity())))))) { - return forceUncompleteActivity(learnerProgress, stopActivity); + return forceUncompleteActivity(learnerProgress, stopActivity, removeLearnerContent); } } @@ -1496,20 +1497,23 @@ * achieve it. */ @SuppressWarnings("unchecked") - private String forceUncompleteActivity(LearnerProgress learnerProgress, Activity targetActivity) { + private String forceUncompleteActivity(LearnerProgress learnerProgress, Activity targetActivity, + boolean removeLearnerContent) { User learner = learnerProgress.getUser(); Activity currentActivity = learnerProgress.getCurrentActivity(); + // set of activities for which "attempted" and "completed" status will be removed + Set uncompleteActivities = new HashSet(); + uncompleteActivities.add(targetActivity); + if (currentActivity == null) { // Learner has finished the whole lesson. Find the last activity by traversing the transition. currentActivity = learnerProgress.getLesson().getLearningDesign().getFirstActivity(); while (currentActivity.getTransitionFrom() != null) { currentActivity = currentActivity.getTransitionFrom().getToActivity(); } + uncompleteActivities.add(currentActivity); } - // set of activities for which "attempted" and "completed" status will be removed - Set uncompleteActivities = new HashSet(); - // check if the target is a part of complex activity CompletedActivityProgress completedActivityProgress = learnerProgress.getCompletedActivities().get( targetActivity); @@ -1547,7 +1551,7 @@ Set groupings = new HashSet(); // remove completed activities step by step, all the way from current to target activity - do { + while (!currentActivity.equals(targetActivity)) { uncompleteActivities.add(currentActivity); if (currentActivity.isComplexActivity()) { @@ -1600,17 +1604,19 @@ groupings.add(currentActivity); } } + } - } while (!currentActivity.equals(targetActivity)); - // forget that user completed and attempted activiites for (Activity activity : uncompleteActivities) { learnerProgress.getAttemptedActivities().remove(activity); learnerProgress.getCompletedActivities().remove(activity); + if (removeLearnerContent && activity.isToolActivity()) { + // remove learner content from this activity + lamsCoreToolService.notifyToolToDeleteLearnerContent((ToolActivity) activity, learner.getUserId()); + } } // set target activity as attempted - learnerProgress.getCompletedActivities().remove(targetActivity); learnerProgress.getAttemptedActivities().put(targetActivity, completedActivityProgress.getStartDate()); if (targetParentActivity != null) { // set parent as attempted Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringAction.java =================================================================== diff -u -r40952c4f84fb81252c3ef18a3e1cc2c0d256622e -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringAction.java (.../MonitoringAction.java) (revision 40952c4f84fb81252c3ef18a3e1cc2c0d256622e) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringAction.java (.../MonitoringAction.java) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -201,8 +201,8 @@ Boolean liveEditEnabled = WebUtil.readBooleanParam(request, "liveEditEnabled", false); Boolean learnerRestart = WebUtil.readBooleanParam(request, "learnerRestart", false); Lesson newLesson = monitoringService.initializeLesson(title, desc, ldId, organisationId, getUserId(), null, - false, false, learnerExportAvailable, learnerPresenceAvailable, learnerImAvailable, - liveEditEnabled, false, learnerRestart, null, null); + false, false, learnerExportAvailable, learnerPresenceAvailable, learnerImAvailable, liveEditEnabled, + false, learnerRestart, null, null); PrintWriter writer = response.getWriter(); writer.println(newLesson.getLessonId()); @@ -549,8 +549,11 @@ long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); Integer learnerId = new Integer(WebUtil.readIntParam(request, MonitoringConstants.PARAM_LEARNER_ID)); Integer requesterId = getUserId(); + boolean removeLearnerContent = WebUtil.readBooleanParam(request, + MonitoringConstants.PARAM_REMOVE_LEARNER_CONTENT, false); - String message = monitoringService.forceCompleteActivitiesByUser(learnerId, requesterId, lessonId, activityId); + String message = monitoringService.forceCompleteActivitiesByUser(learnerId, requesterId, lessonId, activityId, + removeLearnerContent); if (LamsDispatchAction.log.isDebugEnabled()) { LamsDispatchAction.log.debug("Force complete for learner " + learnerId + " lesson " + lessonId + ". " Index: lams_monitoring/web/includes/javascript/monitorLesson.js =================================================================== diff -u -r883c4cc054a636dc8017da1b244b89bdaf0ff974 -r15045d0b9b0dbb930f42a9da7757207e7a325341 --- lams_monitoring/web/includes/javascript/monitorLesson.js (.../monitorLesson.js) (revision 883c4cc054a636dc8017da1b244b89bdaf0ff974) +++ lams_monitoring/web/includes/javascript/monitorLesson.js (.../monitorLesson.js) (revision 15045d0b9b0dbb930f42a9da7757207e7a325341) @@ -93,13 +93,13 @@ if (checked) { $('#imAvailableField').attr('disabled', null); - alert(LESSON_PRESENCE_ENABLE_ALERT_LABEL); + alert(LABELS.LESSON_PRESENCE_ENABLE_ALERT); } else { $('#imAvailableField').attr({ 'checked' : null, 'disabled' : 'disabled' }); - alert(LESSON_PRESENCE_DISABLE_ALERT_LABEL); + alert(LABELS.LESSON_PRESENCE_DISABLE_ALERT); } } }); @@ -120,10 +120,10 @@ success : function() { if (checked) { $('#openImButton').css('display', 'inline'); - alert(LESSON_IM_ENABLE_ALERT_LABEL); + alert(LABELS.LESSON_IM_ENABLE_ALERT); } else { $('#openImButton').css('display', 'none'); - alert(LESSON_IM_DISABLE_ALERT_LABEL); + alert(LABELS.LESSON_IM_DISABLE_ALERT); } } }); @@ -230,7 +230,7 @@ 'resizable' : false, 'show' : 'fold', 'hide' : 'fold', - 'title' : EMAIL_BUTTON_LABEL, + 'title' : LABELS.EMAIL_BUTTON, 'open' : function(){ autoRefreshBlocked = true; $('#emailFrame').attr('src', @@ -259,7 +259,7 @@ 'classOnly' : true }, success : function(response) { - showLearnerGroupDialog(null, LESSON_GROUP_DIALOG_CLASS_LABEL, response, false, false, true); + showLearnerGroupDialog(null, LABELS.LESSON_GROUP_DIALOG_CLASS, response, false, false, true); } }); } @@ -288,8 +288,8 @@ method = "archiveLesson"; break; case 7: //FINISHED - if (confirm(LESSON_REMOVE_ALERT_LABEL)){ - if (confirm(LESSON_REMOVE_DOUBLECHECK_ALERT_LABEL)) { + if (confirm(LABELS.LESSON_REMOVE_ALERT)){ + if (confirm(LABELS.LESSON_REMOVE_DOUBLECHECK_ALERT)) { method = "removeLesson"; } } @@ -337,25 +337,25 @@ var label = null; switch (lessonStateId) { case 1: - label = LESSON_STATE_CREATED_LABEL; + label = LABELS.LESSON_STATE_CREATED; break; case 2: - label = LESSON_STATE_SCHEDULED_LABEL; + label = LABELS.LESSON_STATE_SCHEDULED; break; case 3: - label = LESSON_STATE_STARTED_LABEL; + label = LABELS.LESSON_STATE_STARTED; break; case 4: - label = LESSON_STATE_SUSPENDED_LABEL; + label = LABELS.LESSON_STATE_SUSPENDED; break; case 5: - label = LESSON_STATE_FINISHED_LABEL; + label = LABELS.LESSON_STATE_FINISHED; break; case 6: - label = LESSON_STATE_ARCHIVED_LABEL; + label = LABELS.LESSON_STATE_ARCHIVED; break; case 7: - label = LESSON_STATE_REMOVED_LABEL; + label = LABELS.LESSON_STATE_REMOVED; break; } $('#lessonStateLabel').text(label); @@ -366,20 +366,20 @@ selectField.children('option:not([value="-1"])').remove(); switch (lessonStateId) { case 3: - $('