Index: lams_monitoring/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -ra65e539d10de41687a557eed3f5a12e4f40f1fcc -rbb00a93afc4de53199b77c3a719814292958e53f --- lams_monitoring/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision a65e539d10de41687a557eed3f5a12e4f40f1fcc) +++ lams_monitoring/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision bb00a93afc4de53199b77c3a719814292958e53f) @@ -238,17 +238,18 @@ tab.lesson = Lesson tab.sequence = Sequence tab.learners = Learners -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.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. +force.complete.click = Click on an activity to move learners [0] or click outside any activity to cancel. +force.complete.end.lesson.confirm = Are you sure you want to move learners [0] to the end of lesson? +force.complete.activity.confirm = Are you sure you want to move learners [0] to activity "[1]"? +force.complete.drop.fail = You have dropped learners [0] on either their current or on their completed activity "[1]". +force.complete.end.lesson.tooltip = To move learner to the end of lesson, drag them over to this bar. learner.group.count = learners in total. learner.group.show = Double-click for full list learner.finished.count = Finished Learners: [0] of [1] learner.finished.dialog.title = End of lesson learner.group.sort.button = Sort -button.force.complete = Move learner to... +button.force.complete.all = Move all learners to... +button.force.complete = Move selected learners to... button.view.learner = View learner button.close = Close button.help = Help @@ -262,7 +263,7 @@ learner.group.select.all = Select/Unselect all email.notifications.problems.sending.emails = Some problems occurred while sending emails. Please, contact your system administrator. learner.group.remove.progress = You are about to remove student(s) from a lesson. The student(s) will not have access to this lesson any longer. Do you also want to remove the student(s) progress? -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 = You are moving learners [0] to activity "[1]". You can opt to delete the content of activities that have been previously done, so the learners have to enter the content/answers again. force.complete.remove.content.yes = Delete content force.complete.remove.content.no = Keep content label.schedule.gate.activity.completion.based = This gate is based on each learner's previous activity completion time Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringController.java =================================================================== diff -u -r77e42df82be23d6e1652ced2f049c53fca74160f -rbb00a93afc4de53199b77c3a719814292958e53f --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringController.java (.../MonitoringController.java) (revision 77e42df82be23d6e1652ced2f049c53fca74160f) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringController.java (.../MonitoringController.java) (revision bb00a93afc4de53199b77c3a719814292958e53f) @@ -583,7 +583,9 @@ } long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); - String learnerIDs = request.getParameter(MonitoringConstants.PARAM_LEARNER_ID); + String learnerIDsParam = request.getParameter(MonitoringConstants.PARAM_LEARNER_ID); + // are we moving selected learners or all of learners who are currently in the activity + Long moveAllFromActivityId = WebUtil.readLongParam(request, "moveAllFromActivityID", true); Integer requesterId = getUserId(); boolean removeLearnerContent = WebUtil.readBooleanParam(request, MonitoringConstants.PARAM_REMOVE_LEARNER_CONTENT, false); @@ -600,39 +602,45 @@ .toString(); } - StringBuffer learnerIdNameBuf = new StringBuffer(); - String message = null; - User learner = null; - boolean oneOrMoreProcessed = false; - try { - for (String learnerIDString : learnerIDs.split(",")) { - if (oneOrMoreProcessed) { - learnerIdNameBuf.append(", "); - } else { - oneOrMoreProcessed = true; - } + List learners = null; + if (moveAllFromActivityId == null) { + learners = new LinkedList<>(); + for (String learnerIDString : learnerIDsParam.split(",")) { Integer learnerID = Integer.valueOf(learnerIDString); - message = monitoringService.forceCompleteActivitiesByUser(learnerID, requesterId, lessonId, activityId, - removeLearnerContent); + User learner = (User) userManagementService.findById(User.class, learnerID); + learners.add(learner); + } + } else { + learners = monitoringService.getLearnersByActivities(new Long[] { moveAllFromActivityId }, null, null, + true); + } - learner = (User) userManagementService.findById(User.class, learnerID); + String message = null; + StringBuilder learnerIdNameBuilder = new StringBuilder(); + + try { + for (User learner : learners) { + message = monitoringService.forceCompleteActivitiesByUser(learner.getUserId(), requesterId, lessonId, + activityId, removeLearnerContent); learnerService.createCommandForLearner(lessonId, learner.getLogin(), command); - learnerIdNameBuf.append(learner.getLogin()).append(" (").append(learnerID).append(")"); + learnerIdNameBuilder.append(learner.getLogin()).append(" (").append(learner.getUserId()).append(")") + .append(", "); } } catch (SecurityException e) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); return; } + String learnerIdNameString = learnerIdNameBuilder.substring(0, learnerIdNameBuilder.length() - 2); if (log.isDebugEnabled()) { - log.debug("Force complete for learners " + learnerIdNameBuf.toString() + " lesson " + lessonId + ". " + log.debug("Force complete for learners " + learnerIdNameString.toString() + " lesson " + lessonId + ". " + message); } // audit log force completion attempt String messageKey = (activityId == null) ? "audit.force.complete.end.lesson" : "audit.force.complete"; - Object[] args = new Object[] { learnerIdNameBuf.toString(), activityDescription, lessonId }; + Object[] args = new Object[] { learnerIdNameString, activityDescription, lessonId }; String auditMessage = messageService.getMessage(messageKey, args); logEventService.logEvent(LogEvent.TYPE_FORCE_COMPLETE, requesterId, null, lessonId, activityId, auditMessage + " " + message); Index: lams_monitoring/web/includes/javascript/monitorLesson.js =================================================================== diff -u -r21012de4a17935353bd0a69d6c5752bc01a6dabb -rbb00a93afc4de53199b77c3a719814292958e53f --- lams_monitoring/web/includes/javascript/monitorLesson.js (.../monitorLesson.js) (revision 21012de4a17935353bd0a69d6c5752bc01a6dabb) +++ lams_monitoring/web/includes/javascript/monitorLesson.js (.../monitorLesson.js) (revision bb00a93afc4de53199b77c3a719814292958e53f) @@ -922,36 +922,47 @@ */ function initSequenceTab(){ var learnerGroupDialogContents = $('#learnerGroupDialogContents'); - $('#learnerGroupDialogForceCompleteButton', learnerGroupDialogContents).click(function() { + $('#learnerGroupDialogForceCompleteButton, #learnerGroupDialogForceCompleteAllButton', learnerGroupDialogContents).click(function() { var dialog = $('#learnerGroupDialog'), - selectedLearners = $('.dialogList div.dialogListItemSelected', dialog), - // go to "force complete" mode, similar to draggin user to an activity + // are we moving selected learners or all of learners who are currently in the activity + moveAll = $(this).attr('id') == 'learnerGroupDialogForceCompleteAllButton', + selectedLearners = moveAll ? null : $('.dialogList div.dialogListItemSelected', dialog), + // go to "force complete" mode, similar to dragging user to an activity activityId = dialog.data('ajaxProperties').data.activityID, dropArea = sequenceCanvas.add('#completedLearnersContainer'); dropArea.css('cursor', 'url(' + LAMS_URL + 'images/icons/' - + (selectedLearners.length > 1 ? 'group' : 'user') + + (moveAll || selectedLearners.length > 1 ? 'group' : 'user') + '.png),pointer') .one('click', function(event) { - var learners = []; - selectedLearners.each(function(){ - var learner = $(this); - learners.push({ - 'id' : learner.attr('userId'), - 'name' : learner.text() - }); - }); dropArea.off('click').css('cursor', 'default'); - forceComplete(activityId, learners, event.pageX, event.pageY); + if (moveAll) { + // setting learners as 'true' is a special switch meaning "move all" + forceComplete(activityId, true, event.pageX, event.pageY); + } else { + var learners = []; + selectedLearners.each(function(){ + var learner = $(this); + learners.push({ + 'id' : learner.attr('userId'), + 'name' : learner.text() + }); + }); + forceComplete(activityId, learners, event.pageX, event.pageY); + } }); dialog.modal('hide'); - var learnerNames = ''; - selectedLearners.each(function(){ - learnerNames += $(this).text() + ', '; - }); - learnerNames = learnerNames.slice(0, -2); - alert(LABELS.FORCE_COMPLETE_CLICK.replace('[0]',learnerNames)); + if (moveAll) { + alert(LABELS.FORCE_COMPLETE_CLICK.replace('[0]', '')); + } else { + var learnerNames = ''; + selectedLearners.each(function(){ + learnerNames += $(this).text() + ', '; + }); + learnerNames = learnerNames.slice(0, -2); + alert(LABELS.FORCE_COMPLETE_CLICK.replace('[0]', '"' + learnerNames + '"')); + } }); $('#learnerGroupDialogViewButton', learnerGroupDialogContents).click(function() { @@ -1059,15 +1070,15 @@ $('#forceBackwardsRemoveContentNoButton', forceBackwardsDialogContents).click(function(){ var forceBackwardsDialog = $('#forceBackwardsDialog'); - forceCompleteExecute(forceBackwardsDialog.data('learners'), + forceCompleteExecute(forceBackwardsDialog.data('learners'), null, forceBackwardsDialog.data('activityId'), false); forceBackwardsDialog.modal('hide'); }); $('#forceBackwardsRemoveContentYesButton', forceBackwardsDialogContents).click(function(){ var forceBackwardsDialog = $('#forceBackwardsDialog'); - forceCompleteExecute(forceBackwardsDialog.data('learners'), + forceCompleteExecute(forceBackwardsDialog.data('learners'), null, forceBackwardsDialog.data('activityId'), true); forceBackwardsDialog.modal('hide'); @@ -1347,7 +1358,10 @@ autoRefreshBlocked = true; var foundActivities = [], - targetActivity = null; + targetActivity = null, + // if "true", then we are moving all learners from the given activity + // otherwise it is a list of selected learners IDs + moveAll = learners === true; // check all activities and "users who finished lesson" bar $('g[id]:not([id*="_to_"])', sequenceCanvas).add('#completedLearnersContainer').each(function(){ // find which activity learner was dropped on @@ -1395,14 +1409,17 @@ isEndLesson = !targetActivity.is('g'), learnerNames = ''; - $.each(learners, function(){ - learnerNames += this.name + ', '; - }); - learnerNames = learnerNames.slice(0, -2); + if (!moveAll) { + $.each(learners, function(){ + learnerNames += this.name + ', '; + }); + learnerNames = '"' + learnerNames.slice(0, -2) + '"'; + } + if (isEndLesson) { executeForceComplete = currentActivityId && confirm(LABELS.FORCE_COMPLETE_END_LESSON_CONFIRM - .replace('[0]',learnerNames)); + .replace('[0]', learnerNames)); } else { var targetActivityId = +targetActivity.attr('id'); if (currentActivityId != targetActivityId) { @@ -1447,7 +1464,7 @@ } if (executeForceComplete) { - forceCompleteExecute(learners, targetActivityId, false); + forceCompleteExecute(moveAll ? null : learners, moveAll ? currentActivityId : null, targetActivityId, false); } autoRefreshBlocked = false; @@ -1457,16 +1474,23 @@ /** * Tell server to force complete the learner. */ -function forceCompleteExecute(learners, activityId, removeContent) { +function forceCompleteExecute(learners, moveAllFromActivityId, activityId, removeContent) { var learnerIds = ''; - $.each(learners, function() { - learnerIds += this.id + ','; - }) + if (learners) { + $.each(learners, function() { + learnerIds += this.id + ','; + }); + learnerIds = learnerIds.slice(0, -1); + } + var data={ - 'lessonID' : lessonId, - 'learnerID' : learnerIds.slice(0, -1), - 'activityID' : activityId, - 'removeContent' : removeContent + 'lessonID' : lessonId, + // either we list selected learners to move + // or we move all learners from the given activity + 'learnerID' : learnerIds, + 'moveAllFromActivityID' : moveAllFromActivityId, + 'activityID' : activityId, + 'removeContent' : removeContent }; data[csrfTokenName] = csrfTokenValue; @@ -1539,7 +1563,7 @@ var learnerDisplayName = getLearnerDisplayName(learner); activityLearnerId = 'act' + activity.id + 'learner' + learner.id, elementAttributes = { - 'id' : activityLearnerId, + 'id' : activityLearnerId, 'x' : coord.x + learnerIndex*15 + 1, // a bit lower for Optional Activity 'y' : coord.y, Index: lams_monitoring/web/monitor.jsp =================================================================== diff -u -r21012de4a17935353bd0a69d6c5752bc01a6dabb -rbb00a93afc4de53199b77c3a719814292958e53f --- lams_monitoring/web/monitor.jsp (.../monitor.jsp) (revision 21012de4a17935353bd0a69d6c5752bc01a6dabb) +++ lams_monitoring/web/monitor.jsp (.../monitor.jsp) (revision bb00a93afc4de53199b77c3a719814292958e53f) @@ -706,17 +706,21 @@
- + - - -