Index: lams_admin/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -rb812eb010aa5c6d01ef10b19d6325900b7ae5963 -r7134a85eec27c8939889059d62f1c35a216e5059 --- lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision b812eb010aa5c6d01ef10b19d6325900b7ae5963) +++ lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 7134a85eec27c8939889059d62f1c35a216e5059) @@ -597,6 +597,7 @@ sysadmin.lesson.im = Enable Instant Messaging sysadmin.lesson.force.restart = Learners always start from the first activity sysadmin.lesson.allow.restart = Learners can restart the lesson +sysadmin.lesson.start.in.monitor = Start lesson in Monitor sysadmin.lesson.default = Lesson default settings config.enable.portrait.editing = Enable profile portrait editing label.search = Search... @@ -699,4 +700,4 @@ admin.user.add.to.lessons = Add user to existing lessons ai.config.title = Artificial Intelligence ai.config.link = AI management -sysadmin.maintain.session.delete = Delete user session +sysadmin.maintain.session.delete = Delete user session \ No newline at end of file Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/ExtServerCommonForm.java =================================================================== diff -u -r0993bbd812a25ddb84feec64dd0e4847ce32d164 -r7134a85eec27c8939889059d62f1c35a216e5059 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/ExtServerCommonForm.java (.../ExtServerCommonForm.java) (revision 0993bbd812a25ddb84feec64dd0e4847ce32d164) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/ExtServerCommonForm.java (.../ExtServerCommonForm.java) (revision 7134a85eec27c8939889059d62f1c35a216e5059) @@ -28,17 +28,19 @@ private Boolean enableLessonNotifications; /** - * Should Learner start the lesson from the beginning each time he enters it. - * Content is not removed, LessonProgress is deleted, not archived. + * Should Learner start the lesson from the beginning each time he enters it. Content is not removed, LessonProgress + * is deleted, not archived. */ private Boolean forceLearnerRestart; /** - * Should Learners be allowed to restart the lesson after finishing it. - * Content is not removed, LessonProgress is archived and then deleted. + * Should Learners be allowed to restart the lesson after finishing it. Content is not removed, LessonProgress is + * archived and then deleted. */ private Boolean allowLearnerRestart; + private boolean startInMonitor; + /** * Should learners be displayed activity gradebook on lesson complete. */ @@ -140,11 +142,19 @@ this.allowLearnerRestart = allowLearnerRestart; } + public boolean isStartInMonitor() { + return startInMonitor; + } + + public void setStartInMonitor(boolean startInMonitor) { + this.startInMonitor = startInMonitor; + } + public Boolean getGradebookOnComplete() { return gradebookOnComplete; } public void setGradebookOnComplete(Boolean gradebookOnComplete) { this.gradebookOnComplete = gradebookOnComplete; } -} +} \ No newline at end of file Index: lams_admin/web/integration/extLessonForm.jsp =================================================================== diff -u -r0993bbd812a25ddb84feec64dd0e4847ce32d164 -r7134a85eec27c8939889059d62f1c35a216e5059 --- lams_admin/web/integration/extLessonForm.jsp (.../extLessonForm.jsp) (revision 0993bbd812a25ddb84feec64dd0e4847ce32d164) +++ lams_admin/web/integration/extLessonForm.jsp (.../extLessonForm.jsp) (revision 7134a85eec27c8939889059d62f1c35a216e5059) @@ -21,8 +21,15 @@ - +
+ + +
+ +
- - + \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/web/controller/LtiController.java =================================================================== diff -u -r0993bbd812a25ddb84feec64dd0e4847ce32d164 -r7134a85eec27c8939889059d62f1c35a216e5059 --- lams_central/src/java/org/lamsfoundation/lams/web/controller/LtiController.java (.../LtiController.java) (revision 0993bbd812a25ddb84feec64dd0e4847ce32d164) +++ lams_central/src/java/org/lamsfoundation/lams/web/controller/LtiController.java (.../LtiController.java) (revision 7134a85eec27c8939889059d62f1c35a216e5059) @@ -85,8 +85,9 @@ * pages */ @RequestMapping("") - public String unspecified(HttpServletRequest request, HttpServletResponse respnse) throws IOException, - UserAccessDeniedException, RepositoryCheckedException, UserInfoFetchException, UserInfoValidationException { + public String unspecified(HttpServletRequest request, HttpServletResponse respnse) + throws IOException, UserAccessDeniedException, RepositoryCheckedException, UserInfoFetchException, + UserInfoValidationException { String consumerKey = request.getParameter(LtiUtils.OAUTH_CONSUMER_KEY); String resourceLinkId = request.getParameter(BasicLTIConstants.RESOURCE_LINK_ID); String tcGradebookId = request.getParameter(BasicLTIConstants.LIS_RESULT_SOURCEDID); @@ -126,8 +127,9 @@ //check if the new lesson should be created after course copy, that potentially has happened on LMS side; //(we can detect it by comparing orgId of the custom_lessonid's organisation and CONTEXT_ID's one). - boolean isLessonCopyRequired = lesson.getOrganisation() != null - && !lesson.getOrganisation().getOrganisationId().equals(currentOrganisationId); + boolean isLessonCopyRequired = + lesson.getOrganisation() != null && !lesson.getOrganisation().getOrganisationId() + .equals(currentOrganisationId); if (isLessonCopyRequired) { //add users to the course @@ -193,8 +195,9 @@ * design and start a lesson. */ @RequestMapping("/addLesson") - private String addLesson(HttpServletRequest request, HttpServletResponse response) throws IOException, - UserAccessDeniedException, RepositoryCheckedException, UserInfoFetchException, UserInfoValidationException { + private String addLesson(HttpServletRequest request, HttpServletResponse response) + throws IOException, UserAccessDeniedException, RepositoryCheckedException, UserInfoFetchException, + UserInfoValidationException { Integer userId = getUser().getUserID(); String contextId = request.getParameter(BasicLTIConstants.CONTEXT_ID); String customContextMembershipUrl = request.getParameter(LtiUtils.CUSTOM_CONTEXT_MEMBERSHIPS_URL); @@ -239,7 +242,8 @@ request.setAttribute(LtiUtils.CONTENT_ITEM_RETURN_URL, contentItemReturnUrl); request.setAttribute("title", request.getParameter("title")); //text parameter can be null in case of BB server - String description = request.getParameter("text") == null ? "" + String description = request.getParameter("text") == null + ? "" : request.getParameter("text").replaceAll("\\<[^>]*>", ""); request.setAttribute("desc", description); request.setAttribute("data", request.getParameter("data")); @@ -252,8 +256,9 @@ * Starts a lesson. Then prompts to learnerMonitor page or autosubmitForm (in case of ContentItemSelectionRequest). */ @RequestMapping("/startLesson") - public String startLesson(HttpServletRequest request, HttpServletResponse response) throws IOException, - UserAccessDeniedException, RepositoryCheckedException, UserInfoValidationException, UserInfoFetchException { + public String startLesson(HttpServletRequest request, HttpServletResponse response) + throws IOException, UserAccessDeniedException, RepositoryCheckedException, UserInfoValidationException, + UserInfoFetchException { Integer userId = getUser().getUserID(); User user = getRealUser(getUser()); @@ -280,21 +285,25 @@ // 1. init lesson Boolean liveEditEnabled = extServer.getLiveEditEnabled() == null ? false : extServer.getLiveEditEnabled(); Lesson lesson = monitoringService.initializeLesson(title, desc, new Long(ldIdStr), - organisation.getOrganisationId(), user.getUserId(), null, false, enableLessonIntro, - liveEditEnabled, extServer.getEnableLessonNotifications(), extServer.getForceLearnerRestart(), + organisation.getOrganisationId(), user.getUserId(), null, false, enableLessonIntro, liveEditEnabled, + extServer.getEnableLessonNotifications(), extServer.getForceLearnerRestart(), extServer.getAllowLearnerRestart(), extServer.getGradebookOnComplete(), null, null); Long lessonId = lesson.getLessonId(); // 2. create lessonClass for lesson List staffList = new LinkedList<>(); staffList.add(user); List learnerList = new LinkedList<>(); - Vector learnerVector = userManagementService - .getUsersFromOrganisationByRole(organisation.getOrganisationId(), Role.LEARNER, true); + Vector learnerVector = userManagementService.getUsersFromOrganisationByRole( + organisation.getOrganisationId(), Role.LEARNER, true); learnerList.addAll(learnerVector); monitoringService.createLessonClassForLesson(lessonId, organisation, organisation.getName() + "Learners", learnerList, organisation.getName() + "Staff", staffList, user.getUserId()); - // 3. start lesson - monitoringService.startLesson(lessonId, user.getUserId()); + + if (!extServer.isStartInMonitor()) { + // 3. start lesson + monitoringService.startLesson(lessonId, user.getUserId()); + } + // store information which extServer has started the lesson /* @@ -308,8 +317,8 @@ * BUT if there is another integration client which does not use deep linking and sends proper resource link ID * right away, then we use this link. Currently we are aware of desire2learn that uses this approach. */ - boolean useResourceLinkId = toolConsumerFamily == null - || !toolConsumerFamily.toLowerCase().contains("blackboard"); + boolean useResourceLinkId = + toolConsumerFamily == null || !toolConsumerFamily.toLowerCase().contains("blackboard"); integrationService.createExtServerLessonMap(lessonId, useResourceLinkId ? resourceLinkId : null, extServer); integrationService.addUsersUsingMembershipService(extServer, lessonId, extCourseId, resourceLinkId, @@ -469,8 +478,9 @@ * Once lesson was created, start showing learnerMonitor page to everybody regardless of his role. */ @RequestMapping("/learnerMonitor") - public String learnerMonitor(HttpServletRequest request, HttpServletResponse response) throws IOException, - UserAccessDeniedException, RepositoryCheckedException, UserInfoValidationException, UserInfoFetchException { + public String learnerMonitor(HttpServletRequest request, HttpServletResponse response) + throws IOException, UserAccessDeniedException, RepositoryCheckedException, UserInfoValidationException, + UserInfoFetchException { Integer userId = getUser().getUserID(); String consumerKey = request.getParameter(LtiUtils.OAUTH_CONSUMER_KEY); String resourceLinkId = request.getParameter(BasicLTIConstants.RESOURCE_LINK_ID); @@ -516,4 +526,4 @@ return userManagementService.getUserByLogin(dto.getLogin()); } -} +} \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LessonManagerServlet.java =================================================================== diff -u -r0993bbd812a25ddb84feec64dd0e4847ce32d164 -r7134a85eec27c8939889059d62f1c35a216e5059 --- lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LessonManagerServlet.java (.../LessonManagerServlet.java) (revision 0993bbd812a25ddb84feec64dd0e4847ce32d164) +++ lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LessonManagerServlet.java (.../LessonManagerServlet.java) (revision 7134a85eec27c8939889059d62f1c35a216e5059) @@ -115,13 +115,13 @@ * This method is called when a form has its tag value method equals to get. * * @param request - * the request send by the client to the server + * the request send by the client to the server * @param response - * the response send by the server to the client + * the response send by the server to the client * @throws ServletException - * if an error occurred + * if an error occurred * @throws IOException - * if an error occurred + * if an error occurred */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -158,14 +158,14 @@ String enableNotificationString = WebUtil.readStrParam(request, CentralConstants.PARAM_ENABLE_NOTIFICATIONS, true); - Boolean enableNotifications = enableNotificationString == null ? null - : Boolean.valueOf(enableNotificationString); + Boolean enableNotifications = + enableNotificationString == null ? null : Boolean.valueOf(enableNotificationString); String allowLearnerRestartString = WebUtil.readStrParam(request, CentralConstants.PARAM_ALLOW_LEARNER_RESTART, true); // whether this lesson was created with this option ON - boolean enforceAllowLearnerRestart = StringUtils.isNotBlank(allowLearnerRestartString) - && Boolean.valueOf(allowLearnerRestartString); + boolean enforceAllowLearnerRestart = + StringUtils.isNotBlank(allowLearnerRestartString) && Boolean.valueOf(allowLearnerRestartString); Long ldId = null; Long lsId = null; @@ -215,8 +215,8 @@ element = document.createElement(CentralConstants.ELEM_LESSON); element.setAttribute(CentralConstants.ATTR_LESSON_ID, lessonId.toString()); - } else if (method.equals(CentralConstants.METHOD_DELETE) - || method.equals(CentralConstants.METHOD_REMOVE_LESSON)) { + } else if (method.equals(CentralConstants.METHOD_DELETE) || method.equals( + CentralConstants.METHOD_REMOVE_LESSON)) { verifyPostRequestMethod(request); lsId = Long.parseLong(lsIdStr); @@ -264,8 +264,9 @@ } else if (method.equals(CentralConstants.METHOD_JOIN_LESSON)) { lsId = Long.parseLong(lsIdStr); - Thread t = new Thread(new AddUsersToLessonThread(serverId, datetime, username, hashValue, lsId, - courseId, locale, country, learnerIds, monitorIds, firstNames, lastNames, emails, request)); + Thread t = new Thread( + new AddUsersToLessonThread(serverId, datetime, username, hashValue, lsId, courseId, locale, + country, learnerIds, monitorIds, firstNames, lastNames, emails, request)); t.start(); element = document.createElement(CentralConstants.ELEM_LESSON); @@ -369,13 +370,13 @@ * This method is called when a form has its tag value method equals to post. * * @param request - * the request send by the client to the server + * the request send by the client to the server * @param response - * the response send by the server to the client + * the response send by the server to the client * @throws ServletException - * if an error occurred + * if an error occurred * @throws IOException - * if an error occurred + * if an error occurred */ @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -384,8 +385,7 @@ private Long startLesson(String serverId, String datetime, String hashValue, String username, long ldId, String courseId, String title, String desc, boolean enforceAllowLearnerRestart, String countryIsoCode, - String langIsoCode, String customCSV, Boolean enableNotifications) - throws RemoteException { + String langIsoCode, String customCSV, Boolean enableNotifications) throws RemoteException { try { ExtServer extServer = integrationService.getExtServer(serverId); Authenticator.authenticate(extServer, datetime, username, hashValue); @@ -397,16 +397,19 @@ // 1. init lesson Lesson lesson = monitoringService.initializeLesson(title, desc, ldId, organisation.getOrganisationId(), - user.getUserId(), customCSV, false, false, - extServer.getLiveEditEnabled(), + user.getUserId(), customCSV, false, false, extServer.getLiveEditEnabled(), enableNotifications == null ? extServer.getEnableLessonNotifications() : enableNotifications, extServer.getForceLearnerRestart(), enforceAllowLearnerRestart ? true : extServer.getAllowLearnerRestart(), extServer.getGradebookOnComplete(), null, null); // 2. create lessonClass for lesson createLessonClass(lesson, organisation, user); - // 3. start lesson - monitoringService.startLesson(lesson.getLessonId(), user.getUserId()); + + if (!extServer.isStartInMonitor()) { + // 3. start lesson + monitoringService.startLesson(lesson.getLessonId(), user.getUserId()); + } + // store information which extServer has started the lesson integrationService.createExtServerLessonMap(lesson.getLessonId(), extServer); @@ -805,8 +808,8 @@ List staffList = new LinkedList<>(); staffList.add(creator); List learnerList = new LinkedList<>(); - Vector learnerVector = userManagementService - .getUsersFromOrganisationByRole(organisation.getOrganisationId(), Role.LEARNER, true); + Vector learnerVector = userManagementService.getUsersFromOrganisationByRole( + organisation.getOrganisationId(), Role.LEARNER, true); learnerList.addAll(learnerVector); monitoringService.createLessonClassForLesson(lesson.getLessonId(), organisation, organisation.getName() + " learners", learnerList, organisation.getName() + " staff", staffList, @@ -880,18 +883,18 @@ String[] learnerIdArray = (learnerIds != null) ? learnerIds.split(",") : new String[0]; String[] monitorIdArray = (monitorIds != null) ? monitorIds.split(",") : new String[0]; - String[] firstNameArray = (firstNames != null) - ? firstNames.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1) + String[] firstNameArray = (firstNames != null) ? firstNames.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", + -1) : new String[0]; + String[] lastNameArray = (lastNames != null) + ? lastNames.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1) : new String[0]; - String[] lastNameArray = (lastNames != null) ? lastNames.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1) - : new String[0]; String[] emailArray = (emails != null) ? emails.split(",") : new String[0]; // in case there is firstNames available - check all arrays have the same length, as otherwise it's // prone to ArrayOutOfBounds exceptions - if ((firstNames != null) && ((firstNameArray.length != lastNameArray.length) - || (firstNameArray.length != emailArray.length) - || (firstNameArray.length != (learnerIdArray.length + monitorIdArray.length)))) { + if ((firstNames != null) && ((firstNameArray.length != lastNameArray.length) || (firstNameArray.length + != emailArray.length) || (firstNameArray.length != (learnerIdArray.length + + monitorIdArray.length)))) { log.error("Invalid parameters sent: wrong array length. " + "learnerIds=" + learnerIds + " &monitorIds=" + monitorIds + " &firstNames=" + firstNames + " &lastNames=" + lastNames + " &emails=" + emails + " &array lengths=" + learnerIdArray.length + "!" @@ -965,7 +968,7 @@ * @param lessonId * @param courseID * @param outputsUser - * if outputsUser is null return results for the whole lesson, otherwise - for the specified learner + * if outputsUser is null return results for the whole lesson, otherwise - for the specified learner * @return * @throws Exception */ @@ -1122,7 +1125,7 @@ * @param courseID * @param isAuthoredToolOutputs * @param outputsUser - * if outputsUser is null return results for the whole lesson, otherwise - for the specified learner + * if outputsUser is null return results for the whole lesson, otherwise - for the specified learner * @return * @throws Exception */ @@ -1177,9 +1180,8 @@ for (ToolActivity activity : activities) { Long toolContentId = activity.getToolContentId(); if (toolOutputDefinitionsMap.get(toolContentId) == null) { - SortedMap toolOutputDefinitions = lamsCoreToolService - .getOutputDefinitionsFromTool(toolContentId, - ToolOutputDefinition.DATA_OUTPUT_DEFINITION_TYPE_CONDITION); + SortedMap toolOutputDefinitions = lamsCoreToolService.getOutputDefinitionsFromTool( + toolContentId, ToolOutputDefinition.DATA_OUTPUT_DEFINITION_TYPE_CONDITION); toolOutputDefinitionsMap.put(toolContentId, toolOutputDefinitions); } } @@ -1217,11 +1219,12 @@ toolSession = dbToolSession; } } - Map toolOutputDefinitions = toolOutputDefinitionsMap - .get(activity.getToolContentId()); + Map toolOutputDefinitions = toolOutputDefinitionsMap.get( + activity.getToolContentId()); - learnerElement.appendChild(getActivityOutputsElement(document, activity, learner, learnerProgress, - toolSession, toolOutputDefinitions, isAuthoredToolOutputs)); + learnerElement.appendChild( + getActivityOutputsElement(document, activity, learner, learnerProgress, toolSession, + toolOutputDefinitions, isAuthoredToolOutputs)); } toolOutputsElement.appendChild(learnerElement); @@ -1280,8 +1283,8 @@ * THIS IS A HACK to retrieve the first tool activity manually so it can be cast as a ToolActivity - if it is * one */ - Activity firstActivity = monitoringService - .getActivityById(lesson.getLearningDesign().getFirstActivity().getActivityId()); + Activity firstActivity = monitoringService.getActivityById( + lesson.getLearningDesign().getFirstActivity().getActivityId()); activities.add(firstActivity); activities.addAll(lesson.getLearningDesign().getActivities()); @@ -1340,8 +1343,8 @@ boolean completed = progress.getProgressState(activity) == LearnerProgress.ACTIVITY_COMPLETED; activityElement.setAttribute("completed", "" + completed); - activityAttempted = completed - || (progress.getProgressState(activity) == LearnerProgress.ACTIVITY_ATTEMPTED); + activityAttempted = + completed || (progress.getProgressState(activity) == LearnerProgress.ACTIVITY_ATTEMPTED); activityElement.setAttribute("attempted", "" + activityAttempted); } else { @@ -1357,8 +1360,8 @@ ToolOutputDefinition definition = toolOutputDefinitions.get(outputName); if (isAuthoredToolOutputs) { - ActivityEvaluation evaluation = (ActivityEvaluation) userManagementService - .findById(ActivityEvaluation.class, activity.getActivityId()); + ActivityEvaluation evaluation = (ActivityEvaluation) userManagementService.findById( + ActivityEvaluation.class, activity.getActivityId()); if (evaluation != null) { if (outputName.equals(evaluation.getToolOutputDefinition())) { ToolOutput toolOutput = lamsCoreToolService.getOutputFromTool(outputName, toolSession, @@ -1378,8 +1381,9 @@ } } catch (RuntimeException e) { - log.error("Runtime exception when attempted to get outputs for activity: " - + activity.getActivityId() + ", continuing for other activities", e); + log.error( + "Runtime exception when attempted to get outputs for activity: " + activity.getActivityId() + + ", continuing for other activities", e); } } @@ -1486,4 +1490,4 @@ return lessonsElem; } -} +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/integration/ExtServer.java =================================================================== diff -u -r0993bbd812a25ddb84feec64dd0e4847ce32d164 -r7134a85eec27c8939889059d62f1c35a216e5059 --- lams_common/src/java/org/lamsfoundation/lams/integration/ExtServer.java (.../ExtServer.java) (revision 0993bbd812a25ddb84feec64dd0e4847ce32d164) +++ lams_common/src/java/org/lamsfoundation/lams/integration/ExtServer.java (.../ExtServer.java) (revision 7134a85eec27c8939889059d62f1c35a216e5059) @@ -89,19 +89,22 @@ private Boolean enableLessonNotifications; /** - * Should Learner start the lesson from the beginning each time he enters it. - * Content is not removed, LessonProgress is deleted, not archived. + * Should Learner start the lesson from the beginning each time he enters it. Content is not removed, LessonProgress + * is deleted, not archived. */ @Column(name = "force_restart") private Boolean forceLearnerRestart; /** - * Should Learners be allowed to restart the lesson after finishing it. - * Content is not removed, LessonProgress is archived and then deleted. + * Should Learners be allowed to restart the lesson after finishing it. Content is not removed, LessonProgress is + * archived and then deleted. */ @Column(name = "allow_restart") private Boolean allowLearnerRestart; + @Column(name = "start_in_monitor") + private boolean startInMonitor; + /** * Should learners be displayed activity gradebook on lesson complete. */ @@ -402,6 +405,14 @@ this.allowLearnerRestart = allowLearnerRestart; } + public boolean isStartInMonitor() { + return startInMonitor; + } + + public void setStartInMonitor(boolean startInMonitor) { + this.startInMonitor = startInMonitor; + } + public Boolean getGradebookOnComplete() { return gradebookOnComplete; }