Index: lams_gradebook/.externalToolBuilders/SASS_lams_gradebook.launch =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/.externalToolBuilders/SASS_lams_gradebook.launch (.../SASS_lams_gradebook.launch) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/.externalToolBuilders/SASS_lams_gradebook.launch (.../SASS_lams_gradebook.launch) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -5,6 +5,12 @@ + + + + + + Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/action/GradebookAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/action/GradebookLearningAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/action/GradebookMonitoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookController.java =================================================================== diff -u --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookController.java (revision 0) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,642 @@ +/**************************************************************** + * Copyright (C) 2008 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.gradebook.web.controller; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.gradebook.GradebookUserLesson; +import org.lamsfoundation.lams.gradebook.dto.GBLessonGridRowDTO; +import org.lamsfoundation.lams.gradebook.dto.GBUserGridRowDTO; +import org.lamsfoundation.lams.gradebook.dto.GradebookGridRowDTO; +import org.lamsfoundation.lams.gradebook.service.IGradebookService; +import org.lamsfoundation.lams.gradebook.util.GBGridView; +import org.lamsfoundation.lams.gradebook.util.GradebookConstants; +import org.lamsfoundation.lams.gradebook.util.GradebookUtil; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.web.bean.ActivityURL; +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.learningdesign.Group; +import org.lamsfoundation.lams.learningdesign.ToolActivity; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.lesson.service.ILessonService; +import org.lamsfoundation.lams.security.ISecurityService; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.Role; +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; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author lfoxton + * + * Handles the general requests for content in gradebook + */ +@Controller +@RequestMapping("/gradebook") +public class GradebookController { + + private static Logger logger = Logger.getLogger(GradebookController.class); + + @Autowired + @Qualifier("gradebookService") + private static IGradebookService gradebookService; + + @Autowired + @Qualifier("userService") + private static IUserManagementService userService; + + @Autowired + @Qualifier("lessonService") + private static ILessonService lessonService; + + @Autowired + @Qualifier("securityService") + private static ISecurityService securityService; + + @Autowired + @Qualifier("learnerService") + private static ICoreLearnerService learnerService; + + @RequestMapping("") + @ResponseBody + public void unspecified() throws Exception { + } + + /** + * Returns an xml representation of the activity grid for gradebook + * + * This has two modes, userView and activityView + * + * User view will get the grid data for a specified user, which is all their activity marks/outputs etc + * + * Activity view will get the grid data for all activities, without user info, instead there is an average mark for + * each activity + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @RequestMapping("/getActivityGridData") + @ResponseBody + public String getActivityGridData(HttpServletRequest request, HttpServletResponse response) throws Exception { + // Getting the params passed in from the jqGrid + int page = WebUtil.readIntParam(request, GradebookConstants.PARAM_PAGE); + int rowLimit = WebUtil.readIntParam(request, GradebookConstants.PARAM_ROWS); + String sortOrder = WebUtil.readStrParam(request, GradebookConstants.PARAM_SORD); + String sortBy = WebUtil.readStrParam(request, GradebookConstants.PARAM_SIDX, true); + Boolean isSearch = WebUtil.readBooleanParam(request, GradebookConstants.PARAM_SEARCH); + String searchField = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_FIELD, true); + String searchOper = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_OPERATION, true); + String searchString = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_STRING, true); + GBGridView view = GradebookUtil.readGBGridViewParam(request, GradebookConstants.PARAM_VIEW, false); + + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (!securityService.isLessonParticipant(lessonID, getUser().getUserID(), "get activity gradebook data", + false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a learner in the lesson"); + return null; + } + + // Getting userID param, it is passed differently from different views + UserDTO currentUserDTO = getUser(); + Integer userID = null; + if (view == GBGridView.MON_USER) { + userID = WebUtil.readIntParam(request, GradebookConstants.PARAM_USERID); + } else if (view == GBGridView.LRN_ACTIVITY) { + if (currentUserDTO != null) { + userID = currentUserDTO.getUserID(); + } + } + + List gradebookActivityDTOs = new ArrayList<>(); + + // Get the user gradebook list from the db + // A slightly different list is needed for userview or activity view + if ((view == GBGridView.MON_USER) || (view == GBGridView.LRN_ACTIVITY)) {//2nd level && from personal marks page (2nd level or 1st) + gradebookActivityDTOs = gradebookService.getGBActivityRowsForLearner(lessonID, userID, + currentUserDTO.getTimeZone()); + } else if (view == GBGridView.MON_ACTIVITY) { + gradebookActivityDTOs = gradebookService.getGBActivityRowsForLesson(lessonID, currentUserDTO.getTimeZone(), + true); + } + + if ((sortBy == null) || sortBy.equals("")) { + sortBy = GradebookConstants.PARAM_START_DATE; + } + + String ret = GradebookUtil.toGridXML(gradebookActivityDTOs, view, sortBy, isSearch, searchField, searchOper, + searchString, sortOrder, rowLimit, page); + + response.setContentType("text/xml; charset=utf-8"); + return ret; + } + + @SuppressWarnings("unchecked") + @RequestMapping("/getLessonCompleteGridData") + @ResponseBody + public String getLessonCompleteGridData(HttpServletRequest request, HttpServletResponse response) throws Exception { + // Getting the params passed in from the jqGrid + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + UserDTO currentUserDTO = getUser(); + Integer userId = currentUserDTO.getUserID(); + if (!securityService.isLessonParticipant(lessonId, userId, "get lesson complete gradebook data", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a learner in the lesson"); + } + + List gradebookActivityDTOs = gradebookService.getGBLessonComplete(lessonId, userId); + + ObjectNode resultJSON = JsonNodeFactory.instance.objectNode(); + resultJSON.put(GradebookConstants.ELEMENT_RECORDS, gradebookActivityDTOs.size()); + + ArrayNode rowsJSON = JsonNodeFactory.instance.arrayNode(); + for (GradebookGridRowDTO gradebookActivityDTO : gradebookActivityDTOs) { + ObjectNode rowJSON = JsonNodeFactory.instance.objectNode(); + String id = gradebookActivityDTO.getId(); + String[] idParts = id.split("_"); + if (idParts.length > 1) { + // if activity is grouped, use just the real activity ID and leave out group ID + // as we know there will be no ID clash in this single learner gradebook table + id = idParts[0]; + } + rowJSON.put(GradebookConstants.ELEMENT_ID, id); + + ArrayNode cellJSON = JsonNodeFactory.instance.arrayNode(); + cellJSON.add(gradebookActivityDTO.getRowName()); + cellJSON.add(gradebookActivityDTO.getStatus()); + cellJSON.add(gradebookActivityDTO.getAverageMark() == null ? GradebookConstants.CELL_EMPTY + : GradebookUtil.niceFormatting(gradebookActivityDTO.getAverageMark())); + cellJSON.add(gradebookActivityDTO.getMark() == null ? GradebookConstants.CELL_EMPTY + : GradebookUtil.niceFormatting(gradebookActivityDTO.getMark())); + + rowJSON.set(GradebookConstants.ELEMENT_CELL, cellJSON); + rowsJSON.add(rowJSON); + } + resultJSON.set(GradebookConstants.ELEMENT_ROWS, rowsJSON); + + // make a mapping of activity ID -> URL, same as in progress bar + ObjectNode activityURLJSON = JsonNodeFactory.instance.objectNode(); + Object[] ret = learnerService.getStructuredActivityURLs(userId, lessonId); + for (ActivityURL activity : (List) ret[0]) { + String url = activity.getUrl(); + if (url != null) { + if (url.startsWith("learner.do")) { + url = "learning/" + url; + } + String serverUrl = Configuration.get(ConfigurationKeys.SERVER_URL); + if (!url.startsWith(serverUrl)) { + // monitor mode URLs should be prepended with server URL + url = serverUrl + url; + } + activityURLJSON.put(activity.getActivityId().toString(), activity.getUrl()); + } + } + resultJSON.set("urls", activityURLJSON); + + boolean isWeighted = gradebookService.isWeightedMarks(lessonId); + GradebookUserLesson gradebookUserLesson = gradebookService.getGradebookUserLesson(lessonId, userId); + resultJSON.put("learnerLessonMark", + gradebookUserLesson == null || gradebookUserLesson.getMark() == null ? GradebookConstants.CELL_EMPTY + : GradebookUtil.niceFormatting(gradebookUserLesson.getMark(), isWeighted)); + Double averageLessonMark = gradebookService.getAverageMarkForLesson(lessonId); + resultJSON.put("averageLessonMark", averageLessonMark == null ? GradebookConstants.CELL_EMPTY + : GradebookUtil.niceFormatting(averageLessonMark, isWeighted)); + + response.setContentType("application/json;charset=utf-8"); + response.getWriter().print(resultJSON.toString()); + return resultJSON.toString(); + } + + /** + * Returns an xml representation of the user grid for gradebook + * + * This has three modes: userView, activityView and courseMonitorView + * + * User view will get all the learners in a lesson and print their gradebook data with their mark for the entire + * lesson + * + * Activity view will take an extra parameter (activityID) and instead show the user's mark just for one activity + * + * Course monitor view gets the same as the user view, but the link is set to the lesson level gradebook instead of + * learner + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @RequestMapping + @ResponseBody + public String getUserGridData(HttpServletRequest request, HttpServletResponse response) throws Exception { + + // Getting the params passed in from the jqGrid + int page = WebUtil.readIntParam(request, GradebookConstants.PARAM_PAGE); + int rowLimit = WebUtil.readIntParam(request, GradebookConstants.PARAM_ROWS); + String sortOrder = WebUtil.readStrParam(request, GradebookConstants.PARAM_SORD); + String sortBy = WebUtil.readStrParam(request, GradebookConstants.PARAM_SIDX, true); + Boolean isSearch = WebUtil.readBooleanParam(request, GradebookConstants.PARAM_SEARCH); + String searchField = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_FIELD, true); + String searchString = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_STRING, true); + GBGridView view = GradebookUtil.readGBGridViewParam(request, GradebookConstants.PARAM_VIEW, false); + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID, true); + Integer organisationID = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID, true); + UserDTO user = getUser(); + + // in case of toolbar searching (which uses different parameters than a single field searching) get those + // parameters + if (isSearch && (searchField == null)) { + searchField = GradebookConstants.PARAM_ROW_NAME; + searchString = WebUtil.readStrParam(request, GradebookConstants.PARAM_ROW_NAME, true); + } + + // Get the user gradebook list from the db + List gradebookUserDTOs = new ArrayList<>(); + + int totalUsers = 0; + // if leesonID is specified show results based on lesson + if (lessonID != null) { + if (!securityService.isLessonMonitor(lessonID, user.getUserID(), "get gradebook", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + return null; + } + + Lesson lesson = lessonService.getLesson(lessonID); + //GBGridView.MON_USER - 1st table of gradebook lesson monitor + //GBGridView.MON_COURSE - Subgrid of 1st table of gradebook course monitor + if (view == GBGridView.MON_USER || view == GBGridView.MON_COURSE) { + gradebookUserDTOs = gradebookService.getGBUserRowsForLesson(lesson, page - 1, rowLimit, sortBy, + sortOrder, searchString, user.getTimeZone()); + totalUsers = lesson.getAllLearners().size(); + + // Subgrid of 2nd table of gradebook lesson monitor + } else if (view == GBGridView.MON_ACTIVITY) { + String rowID = WebUtil.readStrParam(request, AttributeNames.PARAM_ACTIVITY_ID); + + Long activityID = null; + + // Splitting the rowID param to get the activity/group id pair + String[] split = rowID.split("_"); + if (split.length == 2) { + activityID = Long.parseLong(split[0]); + } else { + activityID = Long.parseLong(rowID); + } + + // Getting the group id if it is there + Long groupId = WebUtil.readLongParam(request, GradebookConstants.PARAM_GROUP_ID, true); + + Activity activity = gradebookService.getActivityById(activityID); + if ((activity != null) && (activity instanceof ToolActivity)) { + gradebookUserDTOs = gradebookService.getGBUserRowsForActivity(lesson, (ToolActivity) activity, + groupId, page - 1, rowLimit, sortBy, sortOrder, searchString, user.getTimeZone()); + + //calculate totalUsers + totalUsers = lesson.getAllLearners().size(); + if (groupId != null) { + Group group = (Group) userService.findById(Group.class, groupId); + if (group != null) { + totalUsers = group.getUsers().size(); + } + } + + } else { + // return null and the grid will report an error + GradebookController.logger.error("No activity found for: " + activityID); + return null; + } + } + + // 2nd table of gradebook course monitor + // if organisationID is specified (but not lessonID) then show results for organisation + } else if (organisationID != null) { + if (!securityService.isGroupMonitor(organisationID, user.getUserID(), "get gradebook", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the organisation"); + return null; + } + + Organisation org = (Organisation) userService.findById(Organisation.class, organisationID); + gradebookUserDTOs = gradebookService.getGBUserRowsForOrganisation(org, page - 1, rowLimit, sortOrder, + searchString); + totalUsers = gradebookService.getCountUsersByOrganisation(organisationID, searchString); + + } else { + logger.error("Missing parameters: either lessonID or organisationID should be specified."); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing parameters"); + return null; + } + + //calculate totalPages + int totalPages = new Double( + Math.ceil(new Integer(totalUsers).doubleValue() / new Integer(rowLimit).doubleValue())).intValue(); + String ret = GradebookUtil.toGridXML(gradebookUserDTOs, page, totalPages, view); + + response.setContentType("text/xml; charset=utf-8"); + ; + return ret; + } + + /** + * Returns an xml representation of the lesson grid for a course for gradebook + * + * This has two modes, learnerView and monitorView + * + * Learner view will get the data specific to one user + * + * Monitor will get the data average for whole lessons + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + @RequestMapping("/getCourseGridData") + @ResponseBody + public String getCourseGridData(HttpServletRequest request, HttpServletResponse response) throws Exception { + // Getting the params passed in from the jqGrid + int page = WebUtil.readIntParam(request, GradebookConstants.PARAM_PAGE); + int rowLimit = WebUtil.readIntParam(request, GradebookConstants.PARAM_ROWS); + String sortOrder = WebUtil.readStrParam(request, GradebookConstants.PARAM_SORD); + String sortBy = WebUtil.readStrParam(request, GradebookConstants.PARAM_SIDX, true); + Boolean isSearch = WebUtil.readBooleanParam(request, GradebookConstants.PARAM_SEARCH); + String searchField = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_FIELD, true); + String searchOper = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_OPERATION, true); + String searchString = WebUtil.readStrParam(request, GradebookConstants.PARAM_SEARCH_STRING, true); + GBGridView view = GradebookUtil.readGBGridViewParam(request, GradebookConstants.PARAM_VIEW, false); + Integer courseID = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + Organisation organisation = (Organisation) userService.findById(Organisation.class, courseID); + + // in case of toolbar searching (which uses different parameters than a single field searching) get those + // parameters + if (isSearch && (searchField == null)) { + searchField = GradebookConstants.PARAM_ROW_NAME; + searchOper = GradebookConstants.SEARCH_CONTAINS; + searchString = WebUtil.readStrParam(request, GradebookConstants.PARAM_ROW_NAME, true); + } + + if (sortBy == null) { + sortBy = GradebookConstants.PARAM_ID; + } + + if (sortOrder == null) { + sortOrder = GradebookConstants.SORT_ASC; + } + + Set lessons = organisation.getLessons(); + if (lessons == null) { + return null; + } + + User user; + User viewer = getRealUser(); + if (view == GBGridView.MON_USER) { + Integer userID = WebUtil.readIntParam(request, GradebookConstants.PARAM_USERID); + user = (User) userService.findById(User.class, userID); + } else { + user = getRealUser(); + } + + //permission check + if (view == GBGridView.MON_USER) { + if (!securityService.isGroupMonitor(courseID, viewer.getUserId(), "get course gradebook", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the organisation"); + return null; + } + + } else if (view == GBGridView.MON_COURSE || view == GBGridView.LIST) { + if (!securityService.hasOrgRole(courseID, viewer.getUserId(), + new String[] { Role.GROUP_MANAGER, Role.GROUP_ADMIN }, "get course gradebook", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, + "User is not a group manager or admin in the organisation"); + return null; + } + + } else if (view == GBGridView.LRN_COURSE) { + if (!securityService.hasOrgRole(courseID, viewer.getUserId(), new String[] { Role.LEARNER }, + "get course gradebook for learner", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a learner in the organisation"); + return null; + } + + } else { + return null; + } + + if ((organisation == null) || (user == null) || (viewer == null)) { + // Grid will handle error, just log and return null + GradebookController.logger + .error("Error: request for course gradebook data with null course or user. CourseID: " + courseID); + return null; + } + List gradebookLessonDTOs = gradebookService.getGBLessonRows(organisation, user, viewer, + view, page - 1, rowLimit, sortBy, sortOrder, searchString, getUser().getTimeZone()); + + String ret; + if (view == GBGridView.MON_COURSE || view == GBGridView.LIST) { + int totalPages = new Double( + Math.ceil(new Integer(lessons.size()).doubleValue() / new Integer(rowLimit).doubleValue())) + .intValue(); + ret = GradebookUtil.toGridXML(gradebookLessonDTOs, page, totalPages, view); + + } else { + ret = GradebookUtil.toGridXML(gradebookLessonDTOs, view, sortBy, isSearch, searchField, searchOper, + searchString, sortOrder, rowLimit, page); + } + + response.setContentType("text/xml; charset=utf-8"); + ; + return ret; + } + + /** + * Gets the total mark for a user's lesson and writes the result in the response + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @RequestMapping("/getLessonMarkAggregate") + @ResponseBody + public String getLessonMarkAggregate(HttpServletRequest request, HttpServletResponse response) throws Exception { + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + Integer userID = WebUtil.readIntParam(request, GradebookConstants.PARAM_USERID); + + if (getUser().getUserID().equals(userID)) { + if (!securityService.isLessonParticipant(lessonID, userID, "get lesson mark aggregate", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a participant in the lesson"); + return null; + } + } else { + if (!securityService.isLessonMonitor(lessonID, getUser().getUserID(), "get lesson mark aggregate", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + return null; + } + } + + Lesson lesson = lessonService.getLesson(lessonID); + User learner = (User) userService.findById(User.class, userID); + + if ((lesson != null) && (learner != null)) { + GradebookUserLesson lessonMark = gradebookService.getGradebookUserLesson(lessonID, userID); + if (lessonMark.getMark() != null) { + response.setContentType("text/plain; charset=utf-8"); + + return GradebookUtil.niceFormatting(lessonMark.getMark()); + } + } else { + // Grid will handle error, just log and return null + GradebookController.logger + .error("Error: request for course gradebook data with null user or lesson. lessonID: " + lessonID); + } + return null; + } + + /** + * Gets the average mark for an activity and writes the result in the response + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + @RequestMapping("/getActivityMarkAverage") + @ResponseBody + public String getActivityMarkAverage(HttpServletRequest request, HttpServletResponse response) throws Exception { + String rowID = WebUtil.readStrParam(request, AttributeNames.PARAM_ACTIVITY_ID); + + Long activityID = null; + Long groupID = null; + + // Splitting the rowID param to get the activity/group id pair + String[] split = rowID.split("_"); + if (split.length == 2) { + activityID = Long.parseLong(split[0]); + groupID = Long.parseLong(split[1]); + } else { + activityID = Long.parseLong(rowID); + } + + Activity activity = gradebookService.getActivityById(activityID); + if (activity == null) { + logger.error("Activity with ID: " + activityID + " could not be found when getting activity mark average"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing parameters"); + return null; + } + Integer userID = getUser().getUserID(); + for (Lesson lesson : (Set) activity.getLearningDesign().getLessons()) { + if (!securityService.isLessonMonitor(lesson.getLessonId(), userID, "get activity mark average", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + return null; + } + } + + Double averageMark = gradebookService.getAverageMarkForActivity(activityID, groupID); + response.setContentType("text/plain, charset=utf-8"); + if (averageMark != null) { + + return GradebookUtil.niceFormatting(averageMark); + } else { + + return GradebookConstants.CELL_EMPTY; + } + + } + + /** + * Gets the average mark for lesson and writes the result in the response + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @RequestMapping("/getAverageMarkForLesson") + public String getAverageMarkForLesson(HttpServletRequest request, HttpServletResponse response) throws Exception { + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (!securityService.isLessonMonitor(lessonID, getUser().getUserID(), "get lesson mark average", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + return null; + } + + Double averageMark = gradebookService.getAverageMarkForLesson(lessonID); + + response.setContentType("text/plain; charset=utf-8"); + if (averageMark != null) { + + return GradebookUtil.niceFormatting(averageMark); + } else { + + return GradebookConstants.CELL_EMPTY; + } + } + + private UserDTO getUser() { + HttpSession ss = SessionManager.getSession(); + return (UserDTO) ss.getAttribute(AttributeNames.USER); + } + + private User getRealUser() { + UserDTO userDTO = getUser(); + if (userDTO != null) { + return userService.getUserByLogin(userDTO.getLogin()); + } else { + return null; + } + } + +} \ No newline at end of file Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookLearningController.java =================================================================== diff -u --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookLearningController.java (revision 0) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookLearningController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,106 @@ +/**************************************************************** + * Copyright (C) 2008 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.gradebook.web.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.security.ISecurityService; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @author lfoxton + * + * Handles the learner interfaces for gradebook + * + * This is where marking for an activity/lesson takes place + */ +@Controller +@RequestMapping("/gradebookLearning") +public class GradebookLearningController { + + private static Logger logger = Logger.getLogger(GradebookLearningController.class); + + @Autowired + @Qualifier("userService") + private static IUserManagementService userService; + + @Autowired + @Qualifier("securityService") + private static ISecurityService securityService; + + @RequestMapping("") + public String unspecified() throws Exception { + return null; + } + + @RequestMapping + public String courseLearner(HttpServletRequest request, HttpServletResponse response) throws Exception { + + try { + Integer oranisationID = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + UserDTO user = getUser(); + if (user == null) { + logger.error("User missing from session. "); + return "error"; + } + if (!securityService.hasOrgRole(oranisationID, user.getUserID(), + new String[] { Role.GROUP_MANAGER, Role.MONITOR, Role.LEARNER }, "get course gradebook for learner", + false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a participant in the organisation"); + return null; + } + if (logger.isDebugEnabled()) { + GradebookLearningController.logger + .debug("Getting learner gradebook for organisation: " + oranisationID); + } + + Organisation organisation = (Organisation) userService.findById(Organisation.class, oranisationID); + request.setAttribute("organisationID", oranisationID); + request.setAttribute("organisationName", organisation.getName()); + request.setAttribute("fullName", user.getFirstName() + " " + user.getLastName()); + + return "gradebookCourseLearner"; + } catch (Exception e) { + GradebookLearningController.logger.error("Failed to load learner gradebook", e); + return "error"; + } + } + + private UserDTO getUser() { + HttpSession ss = SessionManager.getSession(); + return (UserDTO) ss.getAttribute(AttributeNames.USER); + } +} \ No newline at end of file Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookMonitoringController.java =================================================================== diff -u --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookMonitoringController.java (revision 0) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/web/controller/GradebookMonitoringController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,452 @@ +/**************************************************************** + * Copyright (C) 2008 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.gradebook.web.controller; + +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.gradebook.service.IGradebookService; +import org.lamsfoundation.lams.gradebook.util.GBGridView; +import org.lamsfoundation.lams.gradebook.util.GradebookConstants; +import org.lamsfoundation.lams.gradebook.util.GradebookUtil; +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.lesson.dto.LessonDetailsDTO; +import org.lamsfoundation.lams.lesson.service.ILessonService; +import org.lamsfoundation.lams.security.ISecurityService; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.Role; +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.ExcelCell; +import org.lamsfoundation.lams.util.ExcelUtil; +import org.lamsfoundation.lams.util.FileUtil; +import org.lamsfoundation.lams.util.JsonUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author lfoxton + * + * Handles the monitor interfaces for gradebook + * + * This is where marking for an activity/lesson takes place + */ +@Controller +@RequestMapping("/gradebookMonitoring") +public class GradebookMonitoringController { + + private static Logger log = Logger.getLogger(GradebookMonitoringController.class); + + @Autowired + @Qualifier("gradebookService") + private static IGradebookService gradebookService; + + @Autowired + @Qualifier("userService") + private static IUserManagementService userService; + + @Autowired + @Qualifier("lessonService") + private static ILessonService lessonService; + + @Autowired + @Qualifier("securityService") + private static ISecurityService securityService; + + @RequestMapping("") + public String unspecified(HttpServletRequest request, HttpServletResponse response) throws Exception { + try { + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (GradebookMonitoringController.log.isDebugEnabled()) { + GradebookMonitoringController.log.debug("Getting gradebook for lesson " + lessonId); + } + UserDTO user = getUser(); + if (user == null) { + GradebookMonitoringController.log.error("User missing from session. "); + return "error"; + } + if (!securityService.isLessonMonitor(lessonId, user.getUserID(), "get lesson gradebook", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + return null; + } + + Lesson lesson = lessonService.getLesson(lessonId); + boolean marksReleased = (lesson.getMarksReleased() != null) && lesson.getMarksReleased(); + LessonDetailsDTO lessonDetatilsDTO = lesson.getLessonDetails(); + request.setAttribute("lessonDetails", lessonDetatilsDTO); + request.setAttribute("marksReleased", marksReleased); + + List weights = gradebookService.getWeights(lesson.getLearningDesign()); + if (weights.size() > 0) { + request.setAttribute("weights", weights); + } + + request.setAttribute("isInTabs", WebUtil.readBooleanParam(request, "isInTabs", false)); + + return "gradebookMonitor"; + } catch (Exception e) { + GradebookMonitoringController.log.error("Failed to load lesson gradebook", e); + return "error"; + } + } + + @RequestMapping("/courseMonitor") + public String courseMonitor(HttpServletRequest request, HttpServletResponse response) throws Exception { + + try { + Integer organisationID = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + if (GradebookMonitoringController.log.isDebugEnabled()) { + GradebookMonitoringController.log.debug("Getting gradebook for organisation " + organisationID); + } + + UserDTO user = getUser(); + if (user == null) { + GradebookMonitoringController.log.error("User missing from session. "); + return "error"; + } + if (!securityService.hasOrgRole(organisationID, user.getUserID(), + new String[] { Role.GROUP_MANAGER, Role.GROUP_ADMIN }, "get course gradebook page", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the organisation"); + return null; + } + + Organisation organisation = (Organisation) userService.findById(Organisation.class, organisationID); + request.setAttribute("organisationID", organisationID); + request.setAttribute("organisationName", organisation.getName()); + + return "gradebookCourseMonitor"; + } catch (Exception e) { + GradebookMonitoringController.log.error("Failed to load course gradebook", e); + return "error"; + } + } + + /** + * Updates a user's mark or feedback for an entire lesson + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @RequestMapping("/updateUserLessonGradebookData") + @ResponseBody + public void updateUserLessonGradebookData(HttpServletRequest request, HttpServletResponse response) + throws Exception { + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (!securityService.isLessonMonitor(lessonID, getUser().getUserID(), "update lesson gradebook", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + } + + Integer userID = WebUtil.readIntParam(request, GradebookConstants.PARAM_ID); + User learner = (User) userService.findById(User.class, userID); + if (learner == null) { + GradebookMonitoringController.log + .error("User with ID " + userID + " could not be found to update his lesson gradebook"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "User could not be found"); + } + + String markStr = WebUtil.readStrParam(request, GradebookConstants.PARAM_MARK, true); + String feedback = WebUtil.readStrParam(request, GradebookConstants.PARAM_FEEDBACK, true); + Lesson lesson = lessonService.getLesson(lessonID); + if ((markStr != null) && !markStr.equals("")) { + Double mark = Double.parseDouble(markStr); + gradebookService.updateUserLessonGradebookMark(lesson, learner, mark); + } + if (feedback != null) { + gradebookService.updateUserLessonGradebookFeedback(lesson, learner, feedback); + } + + } + + /** + * Updates a user's mark or feedback for an activity, then aggregates their total lesson mark + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @RequestMapping("/updateUserActivityGradebookData") + @ResponseBody + public void updateUserActivityGradebookData(HttpServletRequest request, HttpServletResponse response) + throws Exception { + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (!securityService.isLessonMonitor(lessonID, getUser().getUserID(), "update activity gradebook", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + } + + GBGridView view = GradebookUtil.readGBGridViewParam(request, GradebookConstants.PARAM_VIEW, false); + + Long activityID = null; + Integer userID = null; + + // Fetch the id based on which grid it came from + if (view == GBGridView.MON_ACTIVITY) { + String rowID = WebUtil.readStrParam(request, AttributeNames.PARAM_ACTIVITY_ID); + activityID = getActivityFromParameter(rowID); + userID = WebUtil.readIntParam(request, GradebookConstants.PARAM_ID); + } else if (view == GBGridView.MON_USER) { + String rowID = WebUtil.readStrParam(request, GradebookConstants.PARAM_ID); + activityID = getActivityFromParameter(rowID); + userID = WebUtil.readIntParam(request, GradebookConstants.PARAM_USERID); + } + + Activity activity = gradebookService.getActivityById(activityID); + if ((activity == null) || !activity.isToolActivity()) { + GradebookMonitoringController.log + .error("Activity with ID " + activityID + " could not be found or it is not a Tool Activity"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Wrong activity"); + } + + User learner = (User) userService.findById(User.class, userID); + if (learner == null) { + GradebookMonitoringController.log + .error("User with ID " + userID + " could not be found to update his activity gradebook"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "User could not be found"); + } + + String markStr = WebUtil.readStrParam(request, GradebookConstants.PARAM_MARK, true); + String feedback = WebUtil.readStrParam(request, GradebookConstants.PARAM_FEEDBACK, true); + Lesson lesson = lessonService.getLesson(lessonID); + if ((markStr != null) && !markStr.equals("")) { + Double mark = Double.parseDouble(markStr); + gradebookService.updateUserActivityGradebookMark(lesson, learner, activity, mark, true, true); + } + + if (feedback != null) { + gradebookService.updateUserActivityGradebookFeedback(activity, learner, feedback); + } + + } + + private Long getActivityFromParameter(String rowID) { + Long activityID; + // Splitting the rowID param to get the activity/group id pair + String[] split = rowID.split("_"); + if (split.length == 2) { + activityID = Long.parseLong(split[0]); + } else { + activityID = Long.parseLong(rowID); + } + return activityID; + } + + /** + * Toggles the release mark flag for a lesson + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws Exception + */ + @RequestMapping("/toggleReleaseMarks") + public String toggleReleaseMarks(HttpServletRequest request, HttpServletResponse response) throws Exception { + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (!securityService.isLessonMonitor(lessonID, getUser().getUserID(), "toggle release marks", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + return null; + } + + gradebookService.toggleMarksReleased(lessonID); + response.setContentType("text/plain; charset=utf-8"); + return "success"; + } + + /** + * Exports Lesson Gradebook into excel. + */ + @RequestMapping("/exportExcelLessonGradebook") + @ResponseBody + public void exportExcelLessonGradebook(HttpServletRequest request, HttpServletResponse response) throws Exception { + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (!securityService.isLessonMonitor(lessonID, getUser().getUserID(), "export lesson gradebook spreadsheet", + false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + } + + if (GradebookMonitoringController.log.isDebugEnabled()) { + GradebookMonitoringController.log.debug("Exporting to a spreadsheet lesson: " + lessonID); + } + Lesson lesson = lessonService.getLesson(lessonID); + String fileName = lesson.getLessonName().replaceAll(" ", "_") + ".xlsx"; + fileName = FileUtil.encodeFilenameForDownload(request, fileName); + + response.setContentType("application/x-download"); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + GradebookMonitoringController.log.debug("Exporting to a spreadsheet gradebook lesson: " + lessonID); + ServletOutputStream out = response.getOutputStream(); + + LinkedHashMap dataToExport = gradebookService.exportLessonGradebook(lesson); + + // set cookie that will tell JS script that export has been finished + String downloadTokenValue = WebUtil.readStrParam(request, "downloadTokenValue"); + Cookie fileDownloadTokenCookie = new Cookie("fileDownloadToken", downloadTokenValue); + fileDownloadTokenCookie.setPath("/"); + response.addCookie(fileDownloadTokenCookie); + + ExcelUtil.createExcel(out, dataToExport, gradebookService.getMessage("gradebook.export.dateheader"), true); + + } + + /** + * Exports Course Gradebook into excel. + */ + @RequestMapping("/exportExcelCourseGradebook") + @ResponseBody + public void exportExcelCourseGradebook(HttpServletRequest request, HttpServletResponse response) throws Exception { + Integer organisationID = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + UserDTO user = getUser(); + if (!securityService.hasOrgRole(organisationID, user.getUserID(), + new String[] { Role.GROUP_MANAGER, Role.GROUP_ADMIN }, "get course gradebook spreadsheet", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the organisation"); + } + + Organisation organisation = (Organisation) userService.findById(Organisation.class, organisationID); + if (GradebookMonitoringController.log.isDebugEnabled()) { + GradebookMonitoringController.log.debug("Exporting to a spreadsheet course: " + organisationID); + } + LinkedHashMap dataToExport = gradebookService.exportCourseGradebook(user.getUserID(), + organisationID); + + String fileName = organisation.getName().replaceAll(" ", "_") + ".xlsx"; + fileName = FileUtil.encodeFilenameForDownload(request, fileName); + + response.setContentType("application/x-download"); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + + // set cookie that will tell JS script that export has been finished + String downloadTokenValue = WebUtil.readStrParam(request, "downloadTokenValue"); + Cookie fileDownloadTokenCookie = new Cookie("fileDownloadToken", downloadTokenValue); + fileDownloadTokenCookie.setPath("/"); + response.addCookie(fileDownloadTokenCookie); + + // Code to generate file and write file contents to response + ServletOutputStream out = response.getOutputStream(); + ExcelUtil.createExcel(out, dataToExport, gradebookService.getMessage("gradebook.export.dateheader"), true); + + } + + /** + * Exports selected lessons Gradebook into excel. + */ + @RequestMapping("/exportExcelSelectedLessons") + @ResponseBody + public void exportExcelSelectedLessons(HttpServletRequest request, HttpServletResponse response) throws Exception { + Integer organisationID = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + UserDTO user = getUser(); + if (!securityService.isGroupMonitor(organisationID, user.getUserID(), + "export selected lessons gradebook spreadsheet", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the organisation"); + } + + boolean simplified = WebUtil.readBooleanParam(request, "simplified", false); + + Organisation organisation = (Organisation) userService.findById(Organisation.class, organisationID); + String[] lessonIds = request.getParameterValues(AttributeNames.PARAM_LESSON_ID); + if (GradebookMonitoringController.log.isDebugEnabled()) { + GradebookMonitoringController.log.debug("Exporting to a spreadsheet lessons " + Arrays.toString(lessonIds) + + " from course: " + organisationID); + } + LinkedHashMap dataToExport = gradebookService + .exportSelectedLessonsGradebook(user.getUserID(), organisationID, lessonIds, simplified); + + String fileName = organisation.getName().replaceAll(" ", "_") + ".xlsx"; + fileName = FileUtil.encodeFilenameForDownload(request, fileName); + + response.setContentType("application/x-download"); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + + // set cookie that will tell JS script that export has been finished + String downloadTokenValue = WebUtil.readStrParam(request, "downloadTokenValue"); + Cookie fileDownloadTokenCookie = new Cookie("fileDownloadToken", downloadTokenValue); + fileDownloadTokenCookie.setPath("/"); + response.addCookie(fileDownloadTokenCookie); + + // Code to generate file and write file contents to response + ServletOutputStream out = response.getOutputStream(); + ExcelUtil.createExcel(out, dataToExport, null, false); + + } + + /** + * Get the raw marks for display in a histogram. + */ + @RequestMapping("/getMarkChartData") + @ResponseBody + public String getMarkChartData(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + if (!securityService.isLessonMonitor(lessonID, getUser().getUserID(), "export lesson gradebook spreadsheet", + false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a monitor in the lesson"); + } + + List results = gradebookService.getMarksArray(lessonID); + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + if (results != null) { + responseJSON.set("data", JsonUtil.readArray(results)); + } else { + responseJSON.set("data", JsonUtil.readArray(new Float[0])); + } + + response.setContentType("application/json;charset=utf-8"); + return responseJSON.toString(); + + } + + private UserDTO getUser() { + HttpSession ss = SessionManager.getSession(); + return (UserDTO) ss.getAttribute(AttributeNames.USER); + } + +} \ No newline at end of file Index: lams_gradebook/web/WEB-INF/spring-servlet.xml =================================================================== diff -u --- lams_gradebook/web/WEB-INF/spring-servlet.xml (revision 0) +++ lams_gradebook/web/WEB-INF/spring-servlet.xml (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file Index: lams_gradebook/web/WEB-INF/tags/AuthoringButton.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/AuthoringButton.tag (.../AuthoringButton.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/AuthoringButton.tag (.../AuthoringButton.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -32,8 +32,8 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ attribute name="formID" required="true" rtexprvalue="true" %> <%@ attribute name="toolSignature" required="true" rtexprvalue="true" %> @@ -123,11 +123,11 @@ } \ No newline at end of file Index: lams_gradebook/web/WEB-INF/tags/AuthoringRatingAllStyleCriteria.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/AuthoringRatingAllStyleCriteria.tag (.../AuthoringRatingAllStyleCriteria.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/AuthoringRatingAllStyleCriteria.tag (.../AuthoringRatingAllStyleCriteria.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -8,7 +8,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> Index: lams_gradebook/web/WEB-INF/tags/AuthoringRatingCriteria.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/AuthoringRatingCriteria.tag (.../AuthoringRatingCriteria.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/AuthoringRatingCriteria.tag (.../AuthoringRatingCriteria.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -8,9 +8,9 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ attribute name="criterias" required="true" rtexprvalue="true" type="java.util.Collection" %> @@ -284,42 +284,42 @@ - - + + - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + - - + + - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + Index: lams_gradebook/web/WEB-INF/tags/CommentsAuthor.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/CommentsAuthor.tag (.../CommentsAuthor.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/CommentsAuthor.tag (.../CommentsAuthor.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -1,7 +1,7 @@ <%@ taglib uri="tags-core" prefix="c"%> -<%@ taglib uri="tags-html" prefix="html"%> <%@ taglib uri="tags-fmt" prefix="fmt"%> <%@ taglib uri="tags-lams" prefix="lams"%> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ attribute name="allowCommentsVariableName" required="false" rtexprvalue="true"%> <%@ attribute name="allowCommentLabelKey" required="false" rtexprvalue="true"%> @@ -42,23 +42,23 @@
-     -   +     +  
Index: lams_gradebook/web/WEB-INF/tags/Page.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -4,6 +4,7 @@ <%@ taglib uri="tags-lams" prefix="lams"%> <%@ attribute name="type" required="true" rtexprvalue="true"%> +<%@ attribute name="formID" required="false" rtexprvalue="true"%> <%@ attribute name="style" required="false" rtexprvalue="true"%> <%@ attribute name="title" required="false" rtexprvalue="true"%> <%@ attribute name="titleHelpURL" required="false" rtexprvalue="true"%> @@ -88,8 +89,8 @@ - - + + ${toolForm.toolSessionID} @@ -137,12 +138,12 @@ function restartLesson(){ if (confirm(restartLessonConfirmation)) { - window.location.href = LEARNING_URL + 'learner.do?method=restartLesson&lessonID=' + lessonId; + window.location.href = LEARNING_URL + 'learner/restartLesson.do?lessonID=' + lessonId; } } function viewNotebookEntries(){ - openPopUp(LEARNING_URL + "notebook.do?method=viewAll&lessonID=" + lessonId, + openPopUp(LEARNING_URL + "notebook/lessonID.do?lessonID=" + lessonId, "Notebook", 648,1152, "no"); @@ -244,9 +245,8 @@ if ( lessonId != "" || toolSessionId != "" ) { $.ajax({ - url : LEARNING_URL + 'learner.do', + url : LEARNING_URL + 'learner/getLessonDetails.do', data : { - 'method' : 'getLessonDetails', 'lessonID' : lessonId, 'toolSessionID' : toolSessionId, }, Index: lams_gradebook/web/WEB-INF/tags/Rating.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/Rating.tag (.../Rating.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/Rating.tag (.../Rating.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -8,7 +8,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> Index: lams_gradebook/web/WEB-INF/tags/StyledRating.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/StyledRating.tag (.../StyledRating.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/StyledRating.tag (.../StyledRating.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -8,7 +8,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> Index: lams_gradebook/web/WEB-INF/tags/TabBody.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/TabBody.tag (.../TabBody.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/TabBody.tag (.../TabBody.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -34,7 +34,6 @@ <%@ attribute name="titleKey" required="false" rtexprvalue="true"%> <%@ attribute name="page" required="false" rtexprvalue="true"%> <%@ taglib uri="tags-core" prefix="c"%> -<%@ taglib uri="tags-bean" prefix="bean"%> Index: lams_gradebook/web/WEB-INF/tags/TabBodyArea.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/TabBodyArea.tag (.../TabBodyArea.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/TabBodyArea.tag (.../TabBodyArea.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -30,7 +30,6 @@ %> <%@ taglib uri="tags-core" prefix="c"%> -<%@ taglib uri="tags-bean" prefix="bean"%>
Index: lams_gradebook/web/WEB-INF/tags/TextSearch.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -32,12 +32,11 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ taglib uri="tags-lams" prefix="lams" %> <%-- Required attributes --%> <%@ attribute name="sessionMapID" required="true" rtexprvalue="true" %> -<%@ attribute name="wrapInFormTag" required="true" rtexprvalue="true" %> <%-- Optional attributes --%> <%@ attribute name="action" required="false" rtexprvalue="true" %> @@ -53,10 +52,10 @@ <%-- Default value for message key --%> - + - + @@ -85,52 +84,40 @@ - -
- - -

- - - - - - - - - - - - - - - - - -
- - - -
- - - -
- - - -
- - - -
- - - - - - - - - + +

+ + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
\ No newline at end of file Index: lams_gradebook/web/WEB-INF/web.xml =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/WEB-INF/web.xml (.../web.xml) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/WEB-INF/web.xml (.../web.xml) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -96,27 +96,13 @@ - action - org.apache.struts.action.ActionServlet - - config - /WEB-INF/struts-config.xml - - - debug - 999 - - - detail - 2 - - - validate - true - + spring + + org.springframework.web.servlet.DispatcherServlet + 1 - + Connector net.fckeditor.connector.ConnectorServlet @@ -137,7 +123,7 @@ - action + spring *.do Index: lams_gradebook/web/errorContent.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/errorContent.jsp (.../errorContent.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/errorContent.jsp (.../errorContent.jsp) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -1,13 +1,37 @@ +<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> + +<%@ taglib uri="tags-lams" prefix="lams" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> - - - - -
-
-

-

-

-
-
+ + + + + <fmt:message><tiles:getAsString name="titleKey"/></fmt:message> + + + + + + + + + +
+
+ + + + +
+
+

+

+

+
+
+
+
+ +
+ Index: lams_gradebook/web/gradebookCourseLearner.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/gradebookCourseLearner.jsp (.../gradebookCourseLearner.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/gradebookCourseLearner.jsp (.../gradebookCourseLearner.jsp) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -2,7 +2,6 @@ <%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%> <%@ taglib uri="tags-lams" prefix="lams"%> -<%@ taglib uri="tags-html" prefix="html"%> <%@ taglib uri="tags-fmt" prefix="fmt"%> <%@ taglib uri="tags-core" prefix="c"%> @@ -26,7 +25,7 @@ autoencode:false, caption: "${organisationName}", datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getCourseGridData&view=lrnCourse&organisationID=${organisationID}", + url: "/gradebook/gradebook/getCourseGridData.do?view=lrnCourse&organisationID=${organisationID}", height: 'auto', width: $(window).width() - 100, shrinkToFit: false, @@ -75,7 +74,7 @@ iconSet: 'fontAwesome', autoencode:false, datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getActivityGridData&view=lrnActivity&lessonID=" + lessonID, + url: "/gradebook/gradebook/getActivityGridData.do?view=lrnActivity&lessonID=" + lessonID, height: "100%", autowidth:true, pager: subgrid_table_id + "_pager", Index: lams_gradebook/web/gradebookCourseMonitor.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/gradebookCourseMonitor.jsp (.../gradebookCourseMonitor.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/gradebookCourseMonitor.jsp (.../gradebookCourseMonitor.jsp) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -2,7 +2,6 @@ <%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%> <%@ taglib uri="tags-lams" prefix="lams"%> -<%@ taglib uri="tags-html" prefix="html"%> <%@ taglib uri="tags-fmt" prefix="fmt"%> <%@ taglib uri="tags-core" prefix="c"%> @@ -60,7 +59,7 @@ autoencode:false, caption: "", datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getCourseGridData&view=monCourse&organisationID=${organisationID}", + url: "/gradebook/gradebook/getCourseGridData.do?view=monCourse&organisationID=${organisationID}", height: "100%", width: jqgridWidth, shrinkToFit: false, @@ -102,11 +101,11 @@ iconSet: 'fontAwesome', autoencode:false, datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getUserGridData&view=monCourse&lessonID=" + lessonID, + url: "/gradebook/gradebook/getUserGridData.do?view=monCourse&lessonID=" + lessonID, height: "100%", autowidth:true, cellEdit:true, - cellurl: "/gradebook/gradebookMonitoring.do?dispatch=updateUserLessonGradebookData&lessonID=" + lessonID, + cellurl: "/gradebook/gradebookMonitoring/updateUserLessonGradebookData.do?lessonID=" + lessonID, sortorder: "asc", sortname: "rowName", pager: subgrid_table_id + "_pager", @@ -157,7 +156,7 @@ // update the lesson average mark if (cellname == "mark") { // Update the average activity mark - $.get("/gradebook/gradebook.do", {dispatch:"getAverageMarkForLesson", lessonID:lessonID}, function(xml) { + $.get("/gradebook/gradebook/getAverageMarkForLesson.do", {lessonID:lessonID}, function(xml) { if (xml!=null) { jQuery("#organisationGrid").setCell(row_id, "avgMark", xml, "", ""); } @@ -192,7 +191,7 @@ autoencode:false, caption: "", datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getUserGridData&view=listView&organisationID=${organisationID}", + url: "/gradebook/gradebook/getUserGridData.do?view=listView&organisationID=${organisationID}", height: "100%", width: jqgridWidth, shrinkToFit: false, @@ -226,7 +225,7 @@ iconSet: 'fontAwesome', autoencode:false, datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getCourseGridData&view=monUserView&organisationID=${organisationID}&userID=" + userID, + url: "/gradebook/gradebook/getCourseGridData.do?view=monUserView&organisationID=${organisationID}&userID=" + userID, height: "100%", autowidth:true, cellEdit:true, @@ -311,7 +310,7 @@ //modify cellurl setting to include lessonid var lessonID = jQuery("#"+subgrid_table_id).getRowData(rowid)["id"]; - $("#"+subgrid_table_id).setGridParam({cellurl: "/gradebook/gradebookMonitoring.do?dispatch=updateUserLessonGradebookData&lessonID=" + lessonID + "&id=" + userID}); + $("#"+subgrid_table_id).setGridParam({cellurl: "/gradebook/gradebookMonitoring/updateUserLessonGradebookData.do?lessonID=" + lessonID + "&id=" + userID}); }, afterSaveCell: function(rowid, cellname,value, iRow, iCol) { @@ -350,7 +349,7 @@ $("#export-course-button").click(function() { var areaToBlock = "export-link-area"; - var exportExcelUrl = "/gradebookMonitoring.do?dispatch=exportExcelCourseGradebook&organisationID=${organisationID}"; + var exportExcelUrl = "/gradebookMonitoring/exportExcelCourseGradebook.do?organisationID=${organisationID}"; blockExportButton(areaToBlock, exportExcelUrl, languageLabelWait); return false; @@ -369,7 +368,7 @@ var areaToBlock = "select-lessons-area"; var simplified = jQuery("#export-selected-simplified").prop('checked'); simplified = "&simplified="+simplified; - var exportExcelUrl = "/gradebookMonitoring.do?dispatch=exportExcelSelectedLessons"+simplified+"&organisationID=${organisationID}" + lessonIds; + var exportExcelUrl = "/gradebookMonitoring/exportExcelSelectedLessons"+simplified+".do?organisationID=${organisationID}" + lessonIds; blockExportButton(areaToBlock, exportExcelUrl, languageLabelWait); } Index: lams_gradebook/web/gradebookMonitor.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/gradebookMonitor.jsp (.../gradebookMonitor.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/gradebookMonitor.jsp (.../gradebookMonitor.jsp) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -2,7 +2,6 @@ <%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> <%@ taglib uri="tags-lams" prefix="lams" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-fmt" prefix="fmt"%> <%@ taglib uri="tags-core" prefix="c"%> @@ -45,7 +44,7 @@ if ( ! graphLoaded ) { $("#markChartBusy").css("display", "block"); drawHistogram('markChartDiv', - '/gradebook/gradebookMonitoring.do?dispatch=getMarkChartData&lessonID=${lessonDetails.lessonID}', + '/gradebook/gradebookMonitoring/getMarkChartData.do?lessonID=${lessonDetails.lessonID}', '', ''); graphLoaded = true; $("#markChartBusy").css("display", "none"); @@ -84,7 +83,7 @@ } if (conf) { - $.get("/gradebook/gradebookMonitoring.do", {dispatch:"toggleReleaseMarks", lessonID:"${lessonDetails.lessonID}"}, function(xml) { + $.get("/gradebook/gradebookMonitoring/toggleReleaseMarks.do", {lessonID:"${lessonDetails.lessonID}"}, function(xml) { var str = new String(xml) if (str.indexOf("success") != -1) { @@ -151,7 +150,7 @@ autoencode:false, caption: "", datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getUserGridData&view=monUserView&lessonID=${lessonDetails.lessonID}", + url: "/gradebook/gradebook/getUserGridData.do?view=monUserView&lessonID=${lessonDetails.lessonID}", height: "100%", width: jqgridWidth, shrinkToFit: false, @@ -162,7 +161,7 @@ pager: 'userViewPager', rowList:[10,20,30,40,50,100], rowNum:10, - cellurl: "/gradebook/gradebookMonitoring.do?dispatch=updateUserLessonGradebookData&lessonID=${lessonDetails.lessonID}", + cellurl: "/gradebook/gradebookMonitoring/updateUserLessonGradebookData.do?lessonID=${lessonDetails.lessonID}", colNames:["", "", "", @@ -199,14 +198,14 @@ iconSet: 'fontAwesome', autoencode:false, datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getActivityGridData&lessonID=${lessonDetails.lessonID}&view=monUserView&userID=" + userID, + url: "/gradebook/gradebook/getActivityGridData.do?lessonID=${lessonDetails.lessonID}&view=monUserView&userID=" + userID, height: "100%", autowidth:true, cellEdit:true, pager: subgrid_table_id + "_pager", rowList:[10,20,30,40,50,100], rowNum:10, - cellurl: "/gradebook/gradebookMonitoring.do?dispatch=updateUserActivityGradebookData&lessonID=${lessonDetails.lessonID}&view=monUserView&userID=" + userID, + cellurl: "/gradebook/gradebookMonitoring/updateUserActivityGradebookData.do?lessonID=${lessonDetails.lessonID}&view=monUserView&userID=" + userID, colNames: [ '', '', @@ -291,7 +290,7 @@ } // Update the aggregated lesson mark - $.get("/gradebook/gradebook.do", {dispatch:"getLessonMarkAggregate", lessonID:"${lessonDetails.lessonID}", userID:row_id}, function(xml) { + $.get("/gradebook/gradebook/getLessonMarkAggregate.do", {lessonID:"${lessonDetails.lessonID}", userID:row_id}, function(xml) { if (xml!=null) { jQuery("#userView").setCell(row_id, "mark", xml, "", ""); } @@ -324,7 +323,7 @@ autoencode:false, caption: "", datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getActivityGridData&view=monActivityView&lessonID=${lessonDetails.lessonID}", + url: "/gradebook/gradebook/getActivityGridData.do?view=monActivityView&lessonID=${lessonDetails.lessonID}", height: "100%", width: jqgridWidth, shrinkToFit: false, @@ -367,11 +366,11 @@ iconSet: 'fontAwesome', autoencode:false, datatype: "xml", - url: "/gradebook/gradebook.do?dispatch=getUserGridData&view=monActivityView&lessonID=${lessonDetails.lessonID}&activityID=" + activityID + "&groupId=" + groupID, + url: "/gradebook/gradebook/getUserGridData.do?view=monActivityView&lessonID=${lessonDetails.lessonID}&activityID=" + activityID + "&groupId=" + groupID, height: "100%", autowidth:true, cellEdit:true, - cellurl: "/gradebook/gradebookMonitoring.do?dispatch=updateUserActivityGradebookData&lessonID=${lessonDetails.lessonID}&view=monActivityView&activityID=" + activityID, + cellurl: "/gradebook/gradebookMonitoring/updateUserActivityGradebookData.do?lessonID=${lessonDetails.lessonID}&view=monActivityView&activityID=" + activityID, sortorder: "asc", sortname: "fullName", pager: subgrid_table_id + "_pager", @@ -460,7 +459,7 @@ } // Update the average activity mark - $.get("/gradebook/gradebook.do", {dispatch:"getActivityMarkAverage", activityID:row_id}, function(xml) { + $.get("/gradebook/gradebook/getActivityMarkAverage.do", {activityID:row_id}, function(xml) { if (xml!=null) { jQuery("#activityView").setCell(row_id, "avgMark", xml, "", ""); } @@ -487,7 +486,7 @@ $("#export-grades-button").click(function() { var areaToBlock = "export-link-area"; - var exportExcelUrl = "/gradebookMonitoring.do?dispatch=exportExcelLessonGradebook&lessonID=${lessonDetails.lessonID}"; + var exportExcelUrl = "/gradebookMonitoring/exportExcelLessonGradebook.do?lessonID=${lessonDetails.lessonID}"; var languageLabelWait = ""; // if exportSpan is hidden then icon only mode, use small font. blockExportButton(areaToBlock, exportExcelUrl, languageLabelWait, $("#exportSpan:hidden").length > 0); Index: lams_gradebook/web/msgContent.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/msgContent.jsp (.../msgContent.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/msgContent.jsp (.../msgContent.jsp) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -1,12 +1,35 @@ +<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> + +<%@ taglib uri="tags-lams" prefix="lams" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> - - - - -
-
-

-

-
-
+ + + + + <fmt:message><tiles:getAsString name="titleKey"/></fmt:message> + + + + + + + + + +
+
+ + + + +
+
+

+

+
+
+
+
+ +
Index: lams_gradebook/web/template.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_gradebook/web/template.jsp (.../template.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_gradebook/web/template.jsp (.../template.jsp) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -1,7 +1,5 @@ <%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> -<%@ taglib uri="tags-tiles" prefix="tiles" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> @@ -11,7 +9,7 @@ <fmt:message><tiles:getAsString name="titleKey"/></fmt:message> - + Index: lams_learning/.externalToolBuilders/SASS_lams_learning.launch =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_learning/.externalToolBuilders/SASS_lams_learning.launch (.../SASS_lams_learning.launch) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_learning/.externalToolBuilders/SASS_lams_learning.launch (.../SASS_lams_learning.launch) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -5,6 +5,12 @@ + + + + + + Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/ActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/BranchingActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/ChooseActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/DisplayActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/DisplayOptionsActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/DisplayParallelActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/DisplayToolActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/GateAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/GroupingAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LoadToolActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/NotebookAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 refers to a dead (removed) revision in file `lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/SequenceActivityAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/ActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/ActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/ActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,47 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.web.action.LamsAction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Base class for all activity action classes. Each subclass should call + * super.execute() to set up the progress data in the ActivityForm. + */ +@Controller +@RequestMapping("/activity") +public abstract class ActivityController{ + + public static final String RELEASED_LESSONS_REQUEST_ATTRIBUTE = "releasedLessons"; + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/BranchingActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/BranchingActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/BranchingActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,223 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.web.bean.ActivityURL; +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.learningdesign.BranchingActivity; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +/** + * Action class to display an OptionsActivity. + * + * @author daveg + * + * XDoclet definition: + * + * + * + * + * + * + */ +@Controller +@RequestMapping("/branching") +public class BranchingActivityController { + + private static Logger log = Logger.getLogger(BranchingActivityController.class); + + /** Input parameter. Boolean value */ + public static final String PARAM_FORCE_GROUPING = "force"; + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + @Autowired + private WebApplicationContext applicationContext; + + /** + * Gets an options activity from the request (attribute) and forwards to the display JSP. + */ + @RequestMapping("/performBranching") + public String performBranching(@ModelAttribute("BranchingForm") DynaActionForm branchForm, + HttpServletRequest request, HttpServletResponse response) { + + ActivityMapping actionMappings = LearningWebUtil + .getActivityMapping(this.applicationContext.getServletContext()); + + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + Integer learnerId = LearningWebUtil.getUserId(); + boolean forceGroup = WebUtil.readBooleanParam(request, BranchingActivityController.PARAM_FORCE_GROUPING, false); + + String forward = null; + + if (activity == null) { + learnerProgress = learnerService.joinLesson(learnerId, learnerProgress.getLesson().getLessonId()); + forward = actionMappings.getActivityForward(activity, learnerProgress, true); + + } else if (!(activity instanceof BranchingActivity)) { + log.error("activity not BranchingActivity " + activity.getActivityId()); + forward = "error"; + + } else { + + BranchingActivity branchingActivity = (BranchingActivity) activity; + SequenceActivity branch = learnerService.determineBranch(learnerProgress.getLesson(), branchingActivity, + learnerId); + + branchForm.set("activityID", activity.getActivityId()); + branchForm.set("progressID", learnerProgress.getLearnerProgressId()); + branchForm.set("showFinishButton", Boolean.TRUE); + branchForm.set("title", activity.getTitle()); + + if (learnerProgress.getLesson().isPreviewLesson()) { + + // The preview version gives you a choice of branches + // If a "normal" branch can be determined based on the group, tool marks, etc then it is marked as the default branch + + branchForm.set("previewLesson", Boolean.TRUE); + forward = "branching/preview"; + + List activityURLs = new ArrayList<>(); + Iterator i = branchingActivity.getActivities().iterator(); + int completedCount = 0; + while (i.hasNext()) { + Activity nextBranch = (Activity) i.next(); + ActivityURL activityURL = LearningWebUtil.getActivityURL(actionMappings, learnerProgress, + nextBranch, (branch != null) && branch.equals(nextBranch), false); + if (activityURL.isComplete()) { + completedCount++; + } + activityURLs.add(activityURL); + } + branchForm.set("activityURLs", activityURLs); + + } else if (branch == null) { + + // show the learner waiting page + branchForm.set("previewLesson", Boolean.FALSE); + forward = "branching/wait"; + branchForm.set("showNextButton", Boolean.TRUE); + + if (branchingActivity.isChosenBranchingActivity()) { + branchForm.set("type", BranchingActivity.CHOSEN_TYPE); + } else if (branchingActivity.isGroupBranchingActivity()) { + branchForm.set("type", BranchingActivity.GROUP_BASED_TYPE); + } else if (branchingActivity.isToolBranchingActivity()) { + branchForm.set("type", BranchingActivity.TOOL_BASED_TYPE); + } + // lessonId needed for the progress bar + request.setAttribute(AttributeNames.PARAM_LESSON_ID, learnerProgress.getLesson().getLessonId()); + } else { + // forward to the sequence activity. + if (log.isDebugEnabled()) { + log.debug("Branching: selecting the branch " + branch + " for user " + learnerId); + } + + // Set the branch as the current part of the sequence and display it + learnerProgress = learnerService.chooseActivity(learnerId, learnerProgress.getLesson().getLessonId(), + branch, true); + forward = actionMappings.getActivityForward(branch, learnerProgress, true); + } + } + + return forward; + } + + /** + * We are in the preview lesson and the author has selected a particular branch. Force it to take that branch. + */ + @RequestMapping("/forceBranching") + public String forceBranching(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) { + + ActivityMapping actionMappings = LearningWebUtil + .getActivityMapping(this.applicationContext.getServletContext()); + + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + Integer learnerId = LearningWebUtil.getUserId(); + String forward = null; + + if (activity == null) { + learnerProgress = learnerService.joinLesson(learnerId, learnerProgress.getLesson().getLessonId()); + forward = actionMappings.getActivityForward(activity, learnerProgress, true); + + } else if (!(activity instanceof BranchingActivity)) { + log.error("activity not BranchingActivity " + activity.getActivityId()); + forward = "error"; + + } else { + + BranchingActivity branchingActivity = (BranchingActivity) activity; + Long branchId = WebUtil.readLongParam(request, "branchID", false); + + SequenceActivity branch = learnerService.selectBranch(learnerProgress.getLesson(), branchingActivity, + learnerId, branchId); + + if (branch == null) { + log.error("branch id from request is not valid. Activity id " + activity.getActivityId() + " branch id " + + branchId); + forward = "error"; + } + + // forward to the sequence activity. + if (log.isDebugEnabled()) { + log.debug("Branching: selecting the branch " + branch + " for user " + learnerId); + } + + // Set the branch as the current part of the sequence and display it + learnerProgress = learnerService.chooseActivity(learnerId, learnerProgress.getLesson().getLessonId(), + branch, true); + forward = actionMappings.getActivityForward(branch, learnerProgress, true); + } + + return forward; + } +} Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/ChooseActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/ChooseActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/ChooseActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,103 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.learning.web.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.util.TokenProcessor; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +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.LearnerProgress; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.web.action.LamsAction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +/** + * @author daveg + * + * XDoclet definition: + * + * + * + */ +@Controller +public class ChooseActivityController extends ActivityController{ + + protected static String className = "ChooseActivity"; + + private static Logger log = Logger.getLogger(ChooseActivityController.class); + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + @Autowired + private WebApplicationContext applicationContext; + + /** + * Gets an activity from the request (attribute) and forwards onto the required jsp (SingleActivity or + * ParallelActivity). + */ + @RequestMapping("/ChooseActivity") + public String execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) { + ActivityMapping actionMappings = LearningWebUtil.getActivityMapping(this.applicationContext.getServletContext()); + + // check token + if (!TokenProcessor.getInstance().isTokenValid(request, true)) { + // didn't come here from options page + log.info("No valid token in request"); + return mapping.findForward(ActivityMapping.DOUBLE_SUBMIT_ERROR); + } + + // Get learner and lesson details. + Integer learnerId = LearningWebUtil.getUserId(); + LearnerProgress progress = LearningWebUtil.getLearnerProgress(request, learnerService); + Lesson lesson = progress.getLesson(); + + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + + if (activity != null) { + progress = learnerService.chooseActivity(learnerId, lesson.getLessonId(), activity, false); + } else { + // Something has gone wrong - maybe due to Live Edit. Need to recalculate their current location. + progress = learnerService.joinLesson(learnerId, lesson.getLessonId()); + } + + ActionForward forward = actionMappings.getActivityForward(activity, progress, true); + return forward; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/CompleteActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/CompleteActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/CompleteActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,134 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.integration.service.IntegrationService; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceException; +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.LearnerProgress; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * @author daveg + * + * XDoclet definition: + * + * + * + */ +@Controller +public class CompleteActivityController extends ActivityController { + + private static Logger log = Logger.getLogger(CompleteActivityController.class); + + protected static String className = "CompleteActivity"; + private static IntegrationService integrationService = null; + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + @Autowired + private WebApplicationContext applicationContext; + + /** + * Sets the current activity as complete and uses the progress engine to find the next activity (may be null). + * + * Called when completing an optional activity, or triggered by completeToolSession (via a tool call). The activity + * to be marked as complete must + * + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/CompleteActivity") + public String execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + ActivityMapping actionMappings = LearningWebUtil.getActivityMapping(this.applicationContext.getServletContext()); + + Integer learnerId = LearningWebUtil.getUserId(); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + + // This must get the learner progress from the progress id, not cached from the request, + // otherwise we may be using an old version of a lesson while a teacher is starting a + // live edit, and then the lock flag can't be checked correctly. + LearnerProgress progress = learnerService + .getProgressById(WebUtil.readLongParam(request, AttributeNames.PARAM_LEARNER_PROGRESS_ID, true)); + if (!progress.getUser().getUserId().equals(learnerId)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Current learner does not own the given progress"); + log.error("Learner " + learnerId + " tried to complete an activity for progress " + + progress.getLearnerProgressId() + " which does not belong to him"); + return null; + } + + // if user has already completed the lesson - we need to let integrations servers know to come and pick up + // updated marks (as it won't happen at lessoncomplete.jsp page) + if (progress.isComplete()) { + String lessonFinishCallbackUrl = getIntegrationService().getLessonFinishCallbackUrl(progress.getUser(), + progress.getLesson()); + if (lessonFinishCallbackUrl != null) { + request.setAttribute("lessonFinishUrl", lessonFinishCallbackUrl); + } + if (progress.getLesson().getAllowLearnerRestart()) { + request.setAttribute("lessonID", progress.getLesson().getLessonId()); + } + } + + ActionForward forward = null; + // Set activity as complete + try { + forward = LearningWebUtil.completeActivity(request, response, actionMappings, progress, activity, learnerId, + learnerService, false); + } catch (LearnerServiceException e) { + return mapping.findForward("error"); + } + return forward; + } + + private IntegrationService getIntegrationService() { + if (CompleteActivityController.integrationService == null) { + CompleteActivityController.integrationService = (IntegrationService) WebApplicationContextUtils + .getRequiredWebApplicationContext(applicationContext.getServletContext()).getBean("integrationService"); + } + return CompleteActivityController.integrationService; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,117 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.learning.web.controller; + +import java.io.UnsupportedEncodingException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; +import org.lamsfoundation.lams.learning.web.util.ActivityMapping; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Action class to display an activity. This is used when UI calls starts of the learning process. It is needed to put + * the learner progress and the activity in the request, on which LoadToolActivityAction relies. If you try to go + * straight to LoadToolActivityAction then the data won't be in the request. + * + * Request values: lessonID (mandatory), InitialDisplay (optional - Set to "true" for normal display, set to "false" + * when you want it to assume it is inside parallel frameset. Defaults to true). + * + * XDoclet definition: + * + * + * + * + * + * + * + * + * + * + * + * + */ +@Controller +public class DisplayActivityController extends ActivityController { + + //--------------------------------------------------------------------- + // Instance variables + //--------------------------------------------------------------------- + private static Logger log = Logger.getLogger(DisplayActivityController.class); + + public static final String PARAM_INITIAL_DISPLAY = "initialDisplay"; + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + /** + * Gets an activity from the request (attribute) and forwards onto a display action using the ActionMappings class. + * If no activity is in request then use the current activity in learnerProgress. + * + * @throws UnsupportedEncodingException + */ + @RequestMapping("/DisplayActivity") + public String execute( HttpServletRequest request) throws UnsupportedEncodingException { + + // UI can only send the lessonID as that is all it has... + Integer learnerId = LearningWebUtil.getUserId(); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID, true); + // hack until UI changes its url - current sending progressId + if (lessonId == null) { + lessonId = WebUtil.readLongParam(request, "progressId"); + } + LearnerProgress learnerProgress = learnerService.getProgress(learnerId, lessonId); + + // Normally this is used to display the initial page, so initialDisplay=true. But if called from the + // special handling for completed activities (ie close window) then we need to set it to false. + boolean displayParallelFrames = WebUtil.readBooleanParam(request, DisplayActivityController.PARAM_INITIAL_DISPLAY, + true); + + ActivityMapping actionMappings = LearnerServiceProxy.getActivityMapping(getServlet().getServletContext()); + ActionForward forward = actionMappings.getProgressForward(learnerProgress, false, displayParallelFrames, + request, learnerService); + + if (DisplayActivityController.log.isDebugEnabled()) { + DisplayActivityController.log.debug(forward); + } + + return forward; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayOptionsActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayOptionsActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayOptionsActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,142 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.learning.web.controller; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.util.TokenProcessor; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.web.bean.ActivityURL; +import org.lamsfoundation.lams.learning.web.form.OptionsActivityForm; +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.learningdesign.OptionsActivity; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.web.action.LamsAction; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +/** + * Action class to display an OptionsActivity. + * + * @author daveg + * + * XDoclet definition: + * + * + * + * + * + * + */ +@Controller +public class DisplayOptionsActivityController extends ActivityController { + + private static Logger log = Logger.getLogger(DisplayOptionsActivityController.class); + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + @Autowired + private WebApplicationContext applicationContext; + + /** + * Gets an options activity from the request (attribute) and forwards to the display JSP. + */ + @SuppressWarnings("unchecked") + @RequestMapping("/DisplayOptionsActivity") + public ActionForward execute(@ModelAttribute OptionsActivityForm form,HttpServletRequest request, + HttpServletResponse response) { + + ActivityMapping actionMappings = LearningWebUtil.getActivityMapping(this.getServlet().getServletContext()); + + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + if (!(activity instanceof OptionsActivity)) { + log.error("activity not OptionsActivity " + activity.getActivityId()); + return mapping.findForward(ActivityMapping.ERROR); + } + + OptionsActivity optionsActivity = (OptionsActivity) activity; + + form.setActivityID(activity.getActivityId()); + + List activityURLs = new ArrayList(); + Set subActivities = optionsActivity.getActivities(); + Iterator i = subActivities.iterator(); + int completedCount = 0; + while (i.hasNext()) { + ActivityURL activityURL = LearningWebUtil.getActivityURL(actionMappings, learnerProgress, i.next(), false, + false); + if (activityURL.isComplete()) { + completedCount++; + } + activityURLs.add(activityURL); + } + form.setActivityURLs(activityURLs); + + if (optionsActivity.getMinNumberOfOptionsNotNull().intValue() <= completedCount) { + form.setFinished(true); + } + + if (completedCount >= optionsActivity.getMaxNumberOfOptionsNotNull().intValue()) { + form.setMaxActivitiesReached(true); + } + + form.setMinimum(optionsActivity.getMinNumberOfOptionsNotNull().intValue()); + form.setMaximum(optionsActivity.getMaxNumberOfOptionsNotNull().intValue()); + form.setDescription(optionsActivity.getDescription()); + form.setTitle(optionsActivity.getTitle()); + form.setLessonID(learnerProgress.getLesson().getLessonId()); + form.setProgressID(learnerProgress.getLearnerProgressId()); + + TokenProcessor.getInstance().saveToken(request); + + LearningWebUtil.putActivityPositionInRequest(form.getActivityID(), request, applicationContext.getServletContext()); + + // lessonId needed for the progress bar + request.setAttribute(AttributeNames.PARAM_LESSON_ID, learnerProgress.getLesson().getLessonId()); + + String forward = "displayOptions"; + return mapping.findForward(forward); + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayParallelActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayParallelActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayParallelActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,113 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.learning.web.controller; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; +import org.lamsfoundation.lams.learning.web.bean.ActivityURL; +import org.lamsfoundation.lams.learning.web.form.ActivityForm; +import org.lamsfoundation.lams.learning.web.util.ActivityMapping; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.learning.web.util.ParallelActivityMappingStrategy; +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.learningdesign.ParallelActivity; +import org.lamsfoundation.lams.web.action.LamsAction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Action class to display a ParallelActivity. + * + * XDoclet definition: + * + * @author daveg + * + * + * + * + */ +@Controller +public class DisplayParallelActivityController extends ActivityController { + + private static Logger log = Logger.getLogger(DisplayParallelActivityController.class); + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + /** + * Gets a parallel activity from the request (attribute) and forwards to the display JSP. + */ + @RequestMapping("/DisplayParallelActivity") + public String execute(@ModelAttribute ActivityForm form,HttpServletRequest request, + HttpServletResponse response) { + + + ActivityMapping actionMappings = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); + + actionMappings.setActivityMappingStrategy(new ParallelActivityMappingStrategy()); + + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + if (!(activity instanceof ParallelActivity)) { + log.error("activity not ParallelActivity " + activity.getActivityId()); + return mapping.findForward(ActivityMapping.ERROR); + } + + ParallelActivity parallelActivity = (ParallelActivity) activity; + + form.setActivityID(activity.getActivityId()); + + List activityURLs = new ArrayList(); + + for (Iterator i = parallelActivity.getActivities().iterator(); i.hasNext();) { + Activity subActivity = (Activity) i.next(); + ActivityURL activityURL = new ActivityURL(); + String url = actionMappings.getActivityURL(subActivity); + activityURL.setUrl(url); + activityURLs.add(activityURL); + } + if (activityURLs.size() == 0) { + log.error("No sub-activity URLs for activity " + activity.getActivityId()); + return mapping.findForward(ActivityMapping.ERROR); + } + form.setActivityURLs(activityURLs); + + return mapping.findForward("displayParallel"); + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayToolActivityController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayToolActivityController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/DisplayToolActivityController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,92 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.learning.web.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +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.learningdesign.ToolActivity; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.web.action.LamsAction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Action class to forward the user to a Tool. + * + * @author daveg + * + * XDoclet definition: + * + * + * + */ +@Controller +public class DisplayToolActivityController extends ActivityController { + + private static Logger log = Logger.getLogger(DisplayToolActivityController.class); + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + /** + * Gets a tool activity from the request (attribute) and uses a redirect to forward the user to the tool. + */ + @RequestMapping("//DisplayToolActivity") + public String execute(HttpServletRequest request, HttpServletResponse response) { + //ActivityForm form = (ActivityForm)actionForm; + ActivityMapping actionMappings = LearningWebUtil.getActivityMapping(this.getServlet().getServletContext()); + + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + + if (!(activity instanceof ToolActivity)) { + log.error("activity not ToolActivity"); + return mapping.findForward(ActivityMapping.ERROR); + } + + ToolActivity toolActivity = (ToolActivity) activity; + + String url = actionMappings.getLearnerToolURL(learnerProgress.getLesson(), toolActivity, + learnerProgress.getUser()); + try { + response.sendRedirect(url); + } catch (java.io.IOException e) { + return mapping.findForward(ActivityMapping.ERROR); + } + return null; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/GateController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/GateController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/GateController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,238 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceException; +import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; +import org.lamsfoundation.lams.learning.web.bean.GateActivityDTO; +import org.lamsfoundation.lams.learning.web.form.GateForm; +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.learningdesign.GateActivity; +import org.lamsfoundation.lams.learningdesign.ScheduleGateActivity; +import org.lamsfoundation.lams.learningdesign.strategy.ScheduleGateActivityStrategy; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + *

+ * The action servlet that deals with gate activity. This class allows the learner to knock gate when they reach the + * gate. The knocking process will be triggered by the lams progress engine in the first place. The learner can also + * trigger the knocking process by clicking on the button on the waiting page. + *

+ * + *

+ * Learner will progress to the next activity if the gate is open. Otherwise, the learner should see the waiting page. + *

+ * + *

+ * Has a special override key - if the parameter force is set and the lesson is a preview lesson, then the gate will be + * opened straight away. This allows the author to see gate shut initially but override it and open it rather than being + * held up by the gate. + *

+ * + * @author Jacky Fang + * @since 2005-4-7 + * @version 1.1 + * + * + * + * + * + * + * + * + * + */ +@Controller +@RequestMapping("/gate") +public class GateController{ + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + // --------------------------------------------------------------------- + // Instance variables + // --------------------------------------------------------------------- + // private static Logger log = Logger.getLogger(GateAction.class); + + // --------------------------------------------------------------------- + // Class level constants - Struts forward + // --------------------------------------------------------------------- + private static final String VIEW_PERMISSION_GATE = "permissionGate"; + private static final String VIEW_SCHEDULE_GATE = "scheduleGate"; + private static final String VIEW_SYNCH_GATE = "synchGate"; + private static final String VIEW_CONDITION_GATE = "conditionGate"; + + /** Input parameter. Boolean value */ + public static final String PARAM_FORCE_GATE_OPEN = "force"; + + // --------------------------------------------------------------------- + // Struts Dispatch Method + // --------------------------------------------------------------------- + /** + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + @RequestMapping("") + public ActionForward knockGate(@ModelAttribute GateForm gateForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + boolean forceGate = WebUtil.readBooleanParam(request, GateController.PARAM_FORCE_GATE_OPEN, false); + Long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + // initialize service object + Activity activity = learnerService.getActivity(activityId); + ActivityMapping actionMappings = LearningWebUtil.getActivityMapping(this.getServlet().getServletContext()); + + User learner = LearningWebUtil.getUser(learnerService); + Lesson lesson = learnerService.getLesson(lessonId); + + LearnerProgress learnerProgress = learnerService.getProgress(learner.getUserId(), lessonId); + + if (activity != null) { + // knock the gate + GateActivityDTO gateDTO = learnerService.knockGate(activityId, learner, forceGate); + + if (gateDTO == null) { + throw new LearnerServiceException("Gate missing. gate id [" + activityId + "]"); + } + + // if the gate is closed, ask the learner to wait ( updating the cached learner progress on the way ) + if (!gateDTO.getAllowToPass()) { + ActionForward forward = findViewByGateType(mapping, gateForm, gateDTO, lesson); + return forward; + } + } + + // gate is open, so let the learner go to the next activity ( updating the cached learner progress on the way ) + return LearningWebUtil.completeActivity(request, response, actionMappings, learnerProgress, activity, + learner.getUserId(), learnerService, true); + + } + + // --------------------------------------------------------------------- + // Helper methods + // --------------------------------------------------------------------- + /** + * Dispatch view the according to the gate type. + * + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send + * the end-user. + * @param gateForm + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param permissionGate + * the gate activity object + * @param totalNumActiveLearners + * total number of active learners in the lesson (may not all be logged in) + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. + */ + @RequestMapping("/findViewByGateType") + private String findViewByGateType(@ModelAttribute GateForm gateForm, GateActivityDTO gateDTO, + Lesson lesson) { + gateForm.setTotalLearners(gateDTO.getExpectedLearnerCount()); + gateForm.setWaitingLearners(gateDTO.getWaitingLearnerCount()); + gateForm.setPreviewLesson(lesson.isPreviewLesson()); + gateForm.setMonitorCanOpenGate(true); + GateActivity gate = gateDTO.getGate(); + gateForm.setActivityID(gate.getActivityId()); + gateForm.setLessonID(lesson.getLessonId()); + gateForm.setGate(gate); + if (gate.isSynchGate()) { + return mapping.findForward(GateController.VIEW_SYNCH_GATE); + } else if (gate.isScheduleGate()) { + ScheduleGateActivity scheduleGate = (ScheduleGateActivity) gate; + if (Boolean.TRUE.equals(scheduleGate.getGateActivityCompletionBased())) { + // so it is in seconds + gateForm.set("startOffset", scheduleGate.getGateStartTimeOffset() * 60); + + User learner = LearningWebUtil.getUser(learnerService); + Date reachTime = ScheduleGateActivityStrategy.getPreviousActivityCompletionDate(scheduleGate, learner); + gateForm.setReachDate(reachTime); + + Calendar startingTime = new GregorianCalendar(TimeZone.getDefault()); + startingTime.setTime(reachTime); + startingTime.add(Calendar.MINUTE, scheduleGate.getGateStartTimeOffset().intValue()); + gateForm.setStartingTime(startingTime.getTime()); + long diff = startingTime.getTimeInMillis() - new Date().getTime(); + long remainTime = diff / 1000; + gateForm.setRemainTime(remainTime);(remainTime); + gateForm.setEndingTime(null); + } else { + gateForm.setStartOffset(null); + gateForm.setReachDate(null); + Calendar startingTime = new GregorianCalendar(TimeZone.getDefault()); + startingTime.setTime(lesson.getStartDateTime()); + startingTime.add(Calendar.MINUTE, scheduleGate.getGateStartTimeOffset().intValue()); + gateForm.setStartingTime(startingTime.getTime()); + long diff = startingTime.getTimeInMillis() - new Date().getTime(); + long remainTime = diff / 1000; + gateForm.setRemainTime(remainTime); + gateForm.setEndingTime(null); + } + return mapping.findForward(GateController.VIEW_SCHEDULE_GATE); + } else if (gate.isConditionGate()) { + gateForm.setMonitorCanOpenGate(false); + return mapping.findForward(GateController.VIEW_CONDITION_GATE); + } else if (gate.isPermissionGate() || gate.isSystemGate()) { + return mapping.findForward(GateController.VIEW_PERMISSION_GATE); + } else { + throw new LearnerServiceException("Invalid gate activity. " + "gate id [" + gate.getActivityId() + + "] - the type [" + gate.getActivityTypeId() + "] is not a gate type"); + } + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/GroupingController.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/GroupingController.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/GroupingController.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,287 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.io.IOException; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.apache.struts.action.RedirectingActionForward; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; +import org.lamsfoundation.lams.learning.web.form.GroupingForm; +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.learningdesign.Group; +import org.lamsfoundation.lams.learningdesign.Grouping; +import org.lamsfoundation.lams.learningdesign.GroupingActivity; +import org.lamsfoundation.lams.learningdesign.LearnerChoiceGrouping; +import org.lamsfoundation.lams.learningdesign.dto.GroupDTO; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.usermanagement.dto.UserBasicDTO; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +/** + * + *

+ * The action servlet that triggers the system driven grouping (random grouping) and allows the learner to view the + * result of the grouping. + *

+ * + *

+ * Has a special override key - if the parameter force is set and the lesson is a preview lesson, any chosen grouping + * will be overridden. + *

+ * + * @author Jacky Fang + * + */ +@Controller +@RequestMapping("/grouping") +public class GroupingController { + + /** Input parameter. Boolean value */ + public static final String PARAM_FORCE_GROUPING = "force"; + + // --------------------------------------------------------------------- + // Instance variables + // --------------------------------------------------------------------- + private static Logger log = Logger.getLogger(GroupingController.class); + + @Autowired + @Qualifier("learnerService") + private ICoreLearnerService learnerService; + + @Autowired + private WebApplicationContext applicationContext; + // --------------------------------------------------------------------- + // Class level constants - Session Attributes + // --------------------------------------------------------------------- + public static final String GROUPS = "groups"; + public static final String FINISHED_BUTTON = "finishedButton"; + public static final String LOCAL_FILES = "localFiles"; + public static final String TITLE = "title"; + public static final String MAX_LEARNERS_PER_GROUP = "maxLearnersPerGroup"; + public static final String VIEW_STUDENTS_BEFORE_SELECTION = "viewStudentsBeforeSelection"; + + // --------------------------------------------------------------------- + // Class level constants - Struts forward + // --------------------------------------------------------------------- + public static final String VIEW_GROUP = "viewGroup"; + public static final String WAIT_GROUP = "waitGroup"; + public static final String SHOW_GROUP = "showGroup"; + public static final String CHOOSE_GROUP = "chooseGroup"; + + // --------------------------------------------------------------------- + // Struts Dispatch Method + // --------------------------------------------------------------------- + /** + * Perform the grouping for the users who are currently running the lesson. If force is set to true, then we should + * be in preview mode, and we want to override the chosen grouping to make it group straight away. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/performGrouping") + public String performGrouping(@ModelAttribute GroupingForm groupForm,HttpServletRequest request) throws IOException, ServletException { + + boolean forceGroup = WebUtil.readBooleanParam(request, GroupingController.PARAM_FORCE_GROUPING, false); + + // initialize service object + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + if (!(activity instanceof GroupingActivity)) { + log.error("activity not GroupingActivity"); + return "error"; + } + Long lessonId = learnerProgress.getLesson().getLessonId(); + boolean groupingDone = learnerService.performGrouping(lessonId, activity.getActivityId(), + LearningWebUtil.getUserId(), forceGroup); + + groupForm.setPreviewLesson(learnerProgress.getLesson().isPreviewLesson()); + groupForm.setTitle(activity.getTitle()); + groupForm.setActivityID(activity.getActivityId()); + + request.setAttribute(AttributeNames.PARAM_LESSON_ID, lessonId); + if (groupingDone) { + request.setAttribute(GroupingController.FINISHED_BUTTON, Boolean.TRUE); + return "redirect: grouping/viewGroup.do"; + } + // forward to group choosing page + if (((GroupingActivity) activity).getCreateGrouping().isLearnerChoiceGrouping()) { + Long groupingId = ((GroupingActivity) activity).getCreateGrouping().getGroupingId(); + Integer maxNumberOfLeaernersPerGroup = learnerService.calculateMaxNumberOfLearnersPerGroup(lessonId, + groupingId); + + LearnerChoiceGrouping grouping = (LearnerChoiceGrouping) learnerService.getGrouping(groupingId); + prepareGroupData(request); + request.setAttribute(GroupingController.MAX_LEARNERS_PER_GROUP, maxNumberOfLeaernersPerGroup); + request.setAttribute(GroupingController.LOCAL_FILES, Boolean.FALSE); + request.setAttribute(GroupingController.VIEW_STUDENTS_BEFORE_SELECTION, + grouping.getViewStudentsBeforeSelection()); + return "grouping/choose"; + } + return "grouping/wait"; + } + + /** + * Load up the grouping information and forward to the jsp page to display all the groups and members. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/viewGroup") + public String viewGrouping(HttpServletRequest request) throws IOException, ServletException { + return viewGrouping(request,null); + } + + @RequestMapping("/viewGroup") + public String viewGrouping(HttpServletRequest request, LearnerProgress learnerProgress) throws IOException, ServletException { + prepareGroupData(request); + request.setAttribute(GroupingController.LOCAL_FILES, Boolean.FALSE); + ToolAccessMode mode = WebUtil.readToolAccessModeParam(request, AttributeNames.PARAM_MODE, true); + request.setAttribute(GroupingController.FINISHED_BUTTON, new Boolean((mode == null) || !mode.isTeacher())); + + long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + LearningWebUtil.putActivityPositionInRequest(activityId, request, applicationContext.getServletContext()); + + // make sure the lesson id is always in the request for the progress bar. + if (request.getAttribute(AttributeNames.PARAM_LESSON_ID) == null) { + if (learnerProgress == null) { + learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + } + request.setAttribute(AttributeNames.PARAM_LESSON_ID, learnerProgress.getLesson().getLessonId()); + } + return "grouping/show"; + } + + /** + * Complete the current tool activity and forward to the url of next activity in the learning design. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward completeActivity(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // initialize service object + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + LearnerProgress progress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity groupingActivity = LearningWebUtil.getActivityFromRequest(request, learnerService); + Integer learnerId = LearningWebUtil.getUserId(); + + // so manually resume the progress. The completeActivity code can cope with a missing activity. + return LearningWebUtil.completeActivity(request, response, + LearningWebUtil.getActivityMapping(this.getServlet().getServletContext()), progress, groupingActivity, + learnerId, learnerService, true); + } + + /** + * Inserts into the request most of the data required by JSP page. This method is common for several pages. + * + * @param request + */ + @SuppressWarnings("unchecked") + private void prepareGroupData(HttpServletRequest request) { + + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + + SortedSet groups = new TreeSet(GroupDTO.GROUP_NAME_COMPARATOR); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + + Grouping grouping = ((GroupingActivity) activity).getCreateGrouping(); + if (grouping != null) { + for (Group group : grouping.getGroups()) { + GroupDTO groupDTO = new GroupDTO(group, true); + groupDTO.getUserList().sort(UserBasicDTO.USER_BASIC_DTO_COMPARATOR); + groups.add(groupDTO); + } + } + + request.setAttribute(GroupingController.GROUPS, groups); + request.setAttribute(GroupingController.TITLE, activity.getTitle()); + request.setAttribute(AttributeNames.PARAM_ACTIVITY_ID, activity.getActivityId()); + } + + /** + * Responds to a learner's group choice. Might forward back to group choice page if the chosen group was full. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward learnerChooseGroup(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + Long groupId = WebUtil.readLongParam(request, "groupId"); + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Long lessonId = learnerProgress.getLesson().getLessonId(); + learnerService.learnerChooseGroup(lessonId, activity.getActivityId(), groupId, LearningWebUtil.getUserId()); + + String redirectURL = "/grouping.do"; + redirectURL = WebUtil.appendParameterToURL(redirectURL, "method", "performGrouping"); + redirectURL = WebUtil.appendParameterToURL(redirectURL, "activityID", activity.getActivityId().toString()); + + return new RedirectingActionForward(redirectURL); + } + +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LearnerAction.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LearnerAction.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LearnerAction.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,454 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +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; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.gradebook.service.IGradebookService; +import org.lamsfoundation.lams.learning.presence.PresenceWebsocketServer; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; +import org.lamsfoundation.lams.learning.web.bean.ActivityURL; +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.lesson.service.ILessonService; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; +import org.lamsfoundation.lams.tool.ToolSession; +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.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * + *

+ * The action servlet that interacts with learner to start a lams learner module, join a user to the lesson and allows a + * user to exit a lesson. + *

+ * + *

+ * It is also responsible for the interaction between lams server and UI. UI will call method implemented in this class + * to get progress data or trigger a lams server calculation here + *

+ * + * Note:It needs to extend the LamsDispatchAction which has been customized to accomodate struts + * features to solve duplicate submission problem. + * + * @author Jacky Fang + * @since 3/03/2005 + * @version 1.1 + */ +public class LearnerAction extends LamsDispatchAction { + // --------------------------------------------------------------------- + // Instance variables + // --------------------------------------------------------------------- + private static Logger log = Logger.getLogger(LearnerAction.class); + + private static final String[] MONITOR_MESSAGE_KEYS = new String[] { + "label.learner.progress.activity.current.tooltip", "label.learner.progress.activity.completed.tooltip", + "label.learner.progress.activity.attempted.tooltip", "label.learner.progress.activity.tostart.tooltip", + "label.learner.progress.activity.support.tooltip" }; + + private static final String[] LEARNER_MESSAGE_KEYS = new String[] { "message.learner.progress.restart.confirm", + "message.lesson.restart.button", "label.learner.progress.notebook", "button.exit", + "label.learner.progress.support", "label.my.progress" }; + + // --------------------------------------------------------------------- + // Class level constants - Struts forward + // --------------------------------------------------------------------- + + private ActionForward redirectToURL(ActionMapping mapping, HttpServletResponse response, String url) + throws IOException, ServletException { + if (url != null) { + String fullURL = WebUtil.convertToFullURL(url); + response.sendRedirect(response.encodeRedirectURL(fullURL)); + } else { + throw new ServletException("Tried to redirect to url but url is null"); + } + return null; + } + + /** + *

+ * The structs dispatch action that joins a learner into a lesson. This call is used for a user to start a lesson. + *

+ * + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send + * the end-user. + * + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. + * + * @throws IOException + * @throws ServletException + */ + public ActionForward joinLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // initialize service object + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + Integer learner = null; + try { + + // get user and lesson based on request. + learner = LearningWebUtil.getUserId(); + long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + // security check + Lesson lesson = learnerService.getLesson(lessonID); + User user = (User) LearnerServiceProxy.getUserManagementService(getServlet().getServletContext()) + .findById(User.class, learner); + if ((lesson.getLessonClass() == null) || !lesson.getLessonClass().getLearners().contains(user)) { + request.setAttribute("messageKey", + "User " + user.getLogin() + " is not a learner in the requested lesson."); + return mapping.findForward("message"); + } + // check lesson's state if its suitable for learner's access + if (!lesson.isLessonAccessibleForLearner()) { + request.setAttribute("messageKey", "Lesson is inaccessible"); + return mapping.findForward("message"); + } + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("The learner [" + learner + "] is joining the lesson [" + lessonID + "]"); + } + + // join user to the lesson on the server + LearnerProgress learnerProgress = learnerService.joinLesson(learner, lessonID); + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("The learner [" + learner + "] joined lesson. The" + "progress data is:" + + learnerProgress.toString()); + } + + ActivityMapping activityMapping = LearnerServiceProxy + .getActivityMapping(this.getServlet().getServletContext()); + String url = "learning/" + activityMapping.getDisplayActivityAction(lessonID); + + redirectToURL(mapping, response, url); + + } catch (Exception e) { + LearnerAction.log.error("An error occurred while learner " + learner + " attempting to join the lesson.", + e); + return mapping.findForward(ActivityMapping.ERROR); + } + + return null; + } + + /** + * 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()); + + IUserManagementService userManagementService = LearnerServiceProxy + .getUserManagementService(getServlet().getServletContext()); + userManagementService.save(learnerProgressArchive); + + IGradebookService gradebookService = LearnerServiceProxy.getGradebookService(getServlet().getServletContext()); + gradebookService.archiveLearnerMarks(lessonID, userID); + gradebookService.removeLearnerFromLesson(lessonID, userID); + + IMonitoringService monitoringService = LearnerServiceProxy + .getMonitoringService(getServlet().getServletContext()); + monitoringService.removeLearnerContent(lessonID, userID); + // remove learner progress + ILessonService lessonService = LearnerServiceProxy.getLessonService(getServlet().getServletContext()); + lessonService.removeLearnerProgress(lessonID, userID); + + // display Learner interface with updated data + return joinLesson(mapping, form, request, response); + } + + /** + * Produces necessary data for learner progress bar. + */ + @SuppressWarnings("unchecked") + public ActionForward getLearnerProgress(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException { + Integer learnerId = WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, true); + Integer monitorId = null; + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + Integer userId = user != null ? user.getUserID() : null; + if (learnerId == null) { + // get progress for current user + learnerId = userId; + } else { + // monitor mode; get progress for user given in the parameter + monitorId = userId; + } + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID, true); + if (lessonId == null) { + // depending on when this is called, there may only be a toolSessionId known, not the lessonId. + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + ToolSession toolSession = LearnerServiceProxy.getLamsToolService(getServlet().getServletContext()) + .getToolSession(toolSessionId); + lessonId = toolSession.getLesson().getLessonId(); + } + + responseJSON.set("messages", getProgressBarMessages()); + + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + Object[] ret = learnerService.getStructuredActivityURLs(learnerId, lessonId); + if (ret == null) { + response.setStatus(HttpServletResponse.SC_NO_CONTENT); + return null; + } + + responseJSON.put("currentActivityId", (Long) ret[1]); + responseJSON.put("isPreview", (boolean) ret[2]); + for (ActivityURL activity : (List) ret[0]) { + if (activity.getFloating()) { + // these are support activities + for (ActivityURL childActivity : activity.getChildActivities()) { + responseJSON.withArray("support") + .add(activityProgressToJSON(childActivity, null, lessonId, learnerId, monitorId)); + } + } else { + responseJSON.withArray("activities") + .add(activityProgressToJSON(activity, (Long) ret[1], lessonId, learnerId, monitorId)); + } + } + + response.setContentType("application/json;charset=utf-8"); + response.getWriter().print(responseJSON.toString()); + + return null; + } + + public ActionForward getPresenceChatActiveUserCount(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) throws IOException { + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + int count = PresenceWebsocketServer.getActiveUserCount(lessonId); + response.setContentType("text/plain;charset=utf-8"); + response.getWriter().print(count); + return null; + } + + /** + * Forces a move to a destination Activity in the learning sequence, redirecting to the new page rather. + */ + public ActionForward forceMoveRedirect(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + + Long fromActivityId = WebUtil.readLongParam(request, AttributeNames.PARAM_CURRENT_ACTIVITY_ID, true); + Long toActivityId = WebUtil.readLongParam(request, AttributeNames.PARAM_DEST_ACTIVITY_ID, true); + + Activity fromActivity = null; + Activity toActivity = null; + + if (fromActivityId != null) { + fromActivity = learnerService.getActivity(fromActivityId); + } + + if (toActivityId != null) { + toActivity = learnerService.getActivity(toActivityId); + } + + Integer learnerId = LearningWebUtil.getUserId(); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + learnerService.moveToActivity(learnerId, lessonId, fromActivity, toActivity); + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Force move for learner " + learnerId + " lesson " + lessonId + ". "); + } + + String url = null; + ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); + if (!toActivity.isFloating()) { + url = "/learning" + activityMapping.getDisplayActivityAction(lessonId); + } else { + url = activityMapping.getActivityURL(toActivity); + } + + return redirectToURL(mapping, response, url); + } + + /** + * Converts an activity in learner progress to a JSON object. + */ + private ObjectNode activityProgressToJSON(ActivityURL activity, Long currentActivityId, Long lessonId, + Integer learnerId, Integer monitorId) throws IOException { + ObjectNode activityJSON = JsonNodeFactory.instance.objectNode(); + activityJSON.put("id", activity.getActivityId()); + activityJSON.put("name", activity.getTitle()); + activityJSON.put("status", activity.getActivityId().equals(currentActivityId) ? 0 : activity.getStatus()); + + // URL in learner mode + String url = activity.getUrl(); + if ((url != null) && (monitorId != null)) { + // URL in monitor mode + url = Configuration.get(ConfigurationKeys.SERVER_URL) + + "monitoring/monitoring.do?method=getLearnerActivityURL&lessonID=" + lessonId + "&activityID=" + + activity.getActivityId() + "&userID=" + learnerId; + } + + if (url != null) { + if (url.startsWith("learner.do")) { + url = "learning/" + url; + } + String serverUrl = Configuration.get(ConfigurationKeys.SERVER_URL); + if (!url.startsWith(serverUrl)) { + // monitor mode URLs should be prepended with server URL + url = serverUrl + url; + } + activityJSON.put("url", url); + } + + String actType = activity.getType().toLowerCase(); + String type = "a"; + if (actType.contains("gate")) { + type = "g"; + } else if (actType.contains("options")) { + type = "o"; + } else if (actType.contains("branching")) { + type = "b"; + } + activityJSON.put("type", type); + + if (activity.getChildActivities() != null) { + for (ActivityURL childActivity : activity.getChildActivities()) { + activityJSON.withArray("childActivities") + .add(activityProgressToJSON(childActivity, currentActivityId, lessonId, learnerId, monitorId)); + } + } + + return activityJSON; + } + + private ObjectNode getProgressBarMessages() { + ObjectNode progressBarMessages = JsonNodeFactory.instance.objectNode(); + MessageService messageService = LearnerServiceProxy + .getMonitoringMessageService(getServlet().getServletContext()); + for (String key : MONITOR_MESSAGE_KEYS) { + String value = messageService.getMessage(key); + progressBarMessages.put(key, value); + } + messageService = LearnerServiceProxy.getMessageService(getServlet().getServletContext()); + for (String key : LEARNER_MESSAGE_KEYS) { + String value = messageService.getMessage(key); + progressBarMessages.put(key, value); + } + return progressBarMessages; + } + + /** + * Gets the lesson details based on lesson id or the current tool session + */ + public ActionForward getLessonDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException { + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + Lesson lesson = null; + + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID, true); + if (lessonID != null) { + lesson = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()).getLesson(lessonID); + + } else { + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + ToolSession toolSession = LearnerServiceProxy.getLamsToolService(getServlet().getServletContext()) + .getToolSession(toolSessionId); + lesson = toolSession.getLesson(); + } + + responseJSON.put(AttributeNames.PARAM_LESSON_ID, lesson.getLessonId()); + responseJSON.put(AttributeNames.PARAM_TITLE, lesson.getLessonName()); + responseJSON.put("allowRestart", lesson.getAllowLearnerRestart()); + responseJSON.put(AttributeNames.PARAM_PRESENCE_ENABLED, lesson.getLearnerPresenceAvailable()); + responseJSON.put(AttributeNames.PARAM_PRESENCE_IM_ENABLED, lesson.getLearnerImAvailable()); + + response.setContentType("application/json;charset=utf-8"); + response.getWriter().print(responseJSON.toString()); + + return null; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LessonCompleteActivityAction.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LessonCompleteActivityAction.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LessonCompleteActivityAction.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,97 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.io.UnsupportedEncodingException; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.integration.service.IntegrationService; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.lesson.service.ILessonService; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * Action class run when the learner finishes a lesson. + */ +public class LessonCompleteActivityAction extends ActivityController { + + private static IntegrationService integrationService = null; + private static ILessonService lessonService = null; + + /** + * Gets an activity from the request (attribute) and forwards onto a display action using the ActionMappings class. + * If no activity is in request then use the current activity in learnerProgress. + */ + @Override + public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) throws UnsupportedEncodingException { + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, getLearnerService()); + Lesson lesson = learnerProgress.getLesson(); + Set releasedLessons = getLessonService().getReleasedSucceedingLessons(lesson.getLessonId(), + learnerProgress.getUser().getUserId()); + if (!releasedLessons.isEmpty()) { + StringBuilder releasedLessonNames = new StringBuilder(); + for (Lesson releasedLesson : releasedLessons) { + releasedLessonNames.append(releasedLesson.getLessonName()).append(", "); + } + releasedLessonNames.delete(releasedLessonNames.length() - 2, releasedLessonNames.length()); + request.setAttribute(ActivityController.RELEASED_LESSONS_REQUEST_ATTRIBUTE, releasedLessonNames.toString()); + } + + //checks for lessonFinishUrl parameter + String lessonFinishCallbackUrl = getIntegrationService().getLessonFinishCallbackUrl(learnerProgress.getUser(), + lesson); + if (lessonFinishCallbackUrl != null) { + request.setAttribute("lessonFinishUrl", lessonFinishCallbackUrl); + } + request.setAttribute("lessonID", lesson.getLessonId()); + request.setAttribute("gradebookOnComplete", lesson.getGradebookOnComplete()); + + return mapping.findForward("lessonComplete"); + } + + private IntegrationService getIntegrationService() { + if (LessonCompleteActivityAction.integrationService == null) { + LessonCompleteActivityAction.integrationService = (IntegrationService) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()).getBean("integrationService"); + } + return LessonCompleteActivityAction.integrationService; + } + + private ILessonService getLessonService() { + if (LessonCompleteActivityAction.lessonService == null) { + LessonCompleteActivityAction.lessonService = (ILessonService) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()).getBean("lessonService"); + } + return LessonCompleteActivityAction.lessonService; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LoadToolActivityAction.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LoadToolActivityAction.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LoadToolActivityAction.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,133 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.util.Map; +import java.util.TreeMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; +import org.lamsfoundation.lams.learning.web.bean.ActivityURL; +import org.lamsfoundation.lams.learning.web.form.ActivityForm; +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.LearnerProgress; +import org.lamsfoundation.lams.tool.exception.RequiredGroupMissingException; +import org.lamsfoundation.lams.web.action.LamsAction; + +/** + * Action class to forward the user to a Tool using an intermediate loading page. Can handle regular tools + grouping + * and gates (system tools). Displays the activity that is in the request. This allows it to show any arbitrary + * activity, not just the current activity. + * + * XDoclet definition: + * + * + * + * + * + * + */ +public class LoadToolActivityAction extends ActivityController { + + public static final String PARAM_ACTIVITY_URL = "activityURL"; + public static final String PARAM_IS_BRANCHING = "isBranching"; + + private static final Map toolSessionCreationLocks = new TreeMap(); + + /** + * Gets an activity from the request (attribute) and forwards onto a loading page. + */ + @Override + public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) { + + ActivityForm form = (ActivityForm) actionForm; + ActivityMapping actionMappings = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); + + ICoreLearnerService learnerService = getLearnerService(); + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + + /* + * Synchronise calls to the same activity and attempt to create a session, if it does not exist. + * Even though the method creating sessions in LamsCoreToolService is synchronised, + * subsequent reads from DB are (probably) dirty, + * i.e. they show that session does not exist while it is already there, + * created by another, isolated transaction. + * Reattempting session creation from within transaction not only is broken (because of the dirty reads) + * but also does not make sense, because if the session already exists, + * there is no point in repeating a failed attempt to create it. + * + * The synchronisation code below prevents threads from creating sessions at the same time. + * + * + * Object toolSessionCreationLock = null; + * synchronized (LoadToolActivityAction.toolSessionCreationLocks) { + * toolSessionCreationLock = LoadToolActivityAction.toolSessionCreationLocks.get(activityID); + * if (toolSessionCreationLock == null) { + * toolSessionCreationLock = activityID; + * LoadToolActivityAction.toolSessionCreationLocks.put(activityID, toolSessionCreationLock); + * } + * } + * synchronized (toolSessionCreationLock) { + */ + try { + learnerService.createToolSessionsIfNecessary(activity, learnerProgress); + + /* + * } catch (UnexpectedRollbackException e) { + * LamsAction.log.warn("Got exception while trying to create a tool session, but carrying on.", e); + */ + } catch (RequiredGroupMissingException e) { + + //got here when activity requires existing grouping but no group for user exists yet + LamsAction.log.warn(e.getMessage()); + request.setAttribute("messageKey", e.getMessage()); + return mapping.findForward("message"); + } + + form.setActivityID(activity.getActivityId()); + + String mappingName = "displayTool"; + if (activity.isToolActivity() || activity.isSystemToolActivity()) { + + String url = actionMappings.getLearnerToolURL(learnerProgress.getLesson(), activity, + learnerProgress.getUser()); + form.addActivityURL(new ActivityURL(activity.getActivityId(), url)); + + } else { + LamsAction.log.error(LamsAction.className + ": activity not ToolActivity"); + return mapping.findForward(ActivityMapping.ERROR); + } + return mapping.findForward(mappingName); + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/NotebookAction.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/NotebookAction.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/NotebookAction.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,276 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.io.IOException; +import java.util.List; +import java.util.TreeMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.exception.UserAccessDeniedException; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * @author M Seaton + */ +public class NotebookAction extends LamsDispatchAction { + // --------------------------------------------------------------------- + // Instance variables + // --------------------------------------------------------------------- + private static final String VIEW_ALL = "viewAll"; + private static final String VIEW_SINGLE = "viewSingle"; + private static final String VIEW_JOURNALS = "viewJournals"; + + public ICoreNotebookService getNotebookService() { + WebApplicationContext webContext = WebApplicationContextUtils + .getRequiredWebApplicationContext(this.getServlet().getServletContext()); + return (ICoreNotebookService) webContext.getBean(CoreNotebookConstants.NOTEBOOK_SERVICE_BEAN_NAME); + } + + /** + * View all notebook entries + */ + public ActionForward viewAll(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + // initialize service object + ICoreNotebookService notebookService = getNotebookService(); + + DynaActionForm notebookForm = (DynaActionForm) actionForm; + + // getting requested object according to coming parameters + Integer learnerID = LearningWebUtil.getUserId(); + + // lessonID + Long lessonID = (Long) notebookForm.get("currentLessonID"); + if (lessonID == null || lessonID == 0) { + lessonID = (Long) notebookForm.get(AttributeNames.PARAM_LESSON_ID); + } + + // get all notebook entries for the learner + + TreeMap> entries = notebookService.getEntryByLesson(learnerID, + CoreNotebookConstants.SCRATCH_PAD); + + request.getSession().setAttribute("entries", entries.values()); + request.setAttribute("lessonID", lessonID); + + return mapping.findForward(NotebookAction.VIEW_ALL); + + } + + /** + * View all journals entries from a lesson call + */ + public ActionForward viewAllJournals(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + + DynaActionForm notebookForm = (DynaActionForm) actionForm; + + // getting requested object according to coming parameters + Integer userID = LearningWebUtil.getUserId(); + User user = (User) LearnerServiceProxy.getUserManagementService(getServlet().getServletContext()) + .findById(User.class, userID); + + // lesson service + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + Long lessonID = (Long) notebookForm.get(AttributeNames.PARAM_LESSON_ID); + Lesson lesson = learnerService.getLesson(lessonID); + + if ( ! hasStaffAccessToJournals(user, lesson) ) { + throw new UserAccessDeniedException( + "User " + userID + " may not retrieve journal entries for lesson " + lessonID); + } + + // List of Journal entries + List journals = getJournals(lesson.getLessonId()); + request.getSession().setAttribute("journals", journals); + request.setAttribute(AttributeNames.PARAM_LESSON_ID, lessonID); + + return mapping.findForward(NotebookAction.VIEW_JOURNALS); + } + + // check user has permission to access all the journals for a lesson + private boolean hasStaffAccessToJournals(User user, Lesson lesson) { + + if (lesson == null) { + return false; + } + + // lesson owner okay + if ((lesson.getUser() != null) && lesson.getUser().getUserId().equals(user.getUserId())) { + return true; + } + + // staff member okay + if ((lesson.getLessonClass() != null) && lesson.getLessonClass().isStaffMember(user)) { + return true; + } + + return false; + } + + /** + * + * @param lessonID + * Lesson to get the journals from. + * @return List of Journal entries + */ + private List getJournals(Long lessonID) { + // initialize service object + ICoreNotebookService notebookService = getNotebookService(); + + if (lessonID == null) { + return null; + } + + return notebookService.getEntry(lessonID, CoreNotebookConstants.SCRATCH_PAD, CoreNotebookConstants.JOURNAL_SIG); + + } + + /** + * View single notebook entry + */ + public ActionForward viewEntry(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + // initialize service object + ICoreNotebookService notebookService = getNotebookService(); + + DynaActionForm notebookForm = (DynaActionForm) actionForm; + Long uid = (Long) notebookForm.get("uid"); + Long currentLessonID = (Long) notebookForm.get("currentLessonID"); + String mode = WebUtil.readStrParam(request, "mode", true); + + NotebookEntry entry = notebookService.getEntry(uid); + + // getting requested object according to coming parameters + Integer userID = LearningWebUtil.getUserId(); + User user = (User) LearnerServiceProxy.getUserManagementService(getServlet().getServletContext()) + .findById(User.class, userID); + + if ( entry.getUser() != null && ! entry.getUser().getUserId().equals(user.getUserId()) ) { + // wants to look at someone else's entry - check they are a teacher + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + Lesson lesson = learnerService.getLesson(currentLessonID); + if ( ! hasStaffAccessToJournals(user, lesson) ) { + throw new UserAccessDeniedException( + "User " + userID + " may not retrieve journal entries for lesson " + currentLessonID); + } + } + + if (mode != null) { + request.setAttribute("mode", mode); + } + + if (entry != null) { + request.setAttribute("entry", entry); + } + + if (currentLessonID != null) { + request.setAttribute("currentLessonID", currentLessonID); + } + + return mapping.findForward(NotebookAction.VIEW_SINGLE); + } + + /** + * + */ + public ActionForward processNewEntry(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + // initialize service object + ICoreNotebookService notebookService = getNotebookService(); + + DynaActionForm notebookForm = (DynaActionForm) actionForm; + Long id = (Long) notebookForm.get(AttributeNames.PARAM_LESSON_ID); + String title = (String) notebookForm.get("title"); + String entry = (String) notebookForm.get("entry"); + String signature = (String) notebookForm.get("signature"); + Integer userID = LearningWebUtil.getUserId(); + + notebookService.createNotebookEntry(id, CoreNotebookConstants.SCRATCH_PAD, signature, userID, title, entry); + + boolean skipViewAll = WebUtil.readBooleanParam(request, "skipViewAll", false); + return skipViewAll ? null : viewAll(mapping, actionForm, request, response); + } + + /** + * + */ + public ActionForward updateEntry(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + // initialize service object + ICoreNotebookService notebookService = getNotebookService(); + + // get form data + DynaActionForm notebookForm = (DynaActionForm) actionForm; + Long uid = (Long) notebookForm.get("uid"); + String title = (String) notebookForm.get("title"); + String entry = (String) notebookForm.get("entry"); + String signature = (String) notebookForm.get("signature"); + + // get existing entry to edit + NotebookEntry entryObj = notebookService.getEntry(uid); + + // check entry is being edited by it's owner + Integer userID = LearningWebUtil.getUserId(); + if (userID != entryObj.getUser().getUserId()) { + // throw exception + } + + // update entry + entryObj.setTitle(title); + entryObj.setEntry(entry); + entryObj.setExternalSignature(signature); + + notebookService.updateEntry(entryObj); + + return viewAll(mapping, actionForm, request, response); + + } + +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/SequenceActivityAction.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/SequenceActivityAction.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/SequenceActivityAction.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,93 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.learning.web.controller; + +import java.io.UnsupportedEncodingException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.service.LearnerServiceException; +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.learningdesign.NullActivity; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.web.action.LamsAction; + +/** + * Action class to display a sequence activity. + * + * Normally this will display the first activity inside a sequence activity. If there are no activities within the + * sequence activity then it will display an "empty" message. + * + * + * + */ +public class SequenceActivityAction extends ActivityController { + + /** + * Gets an sequence activity from the request (attribute) and forwards to either the first activity in the sequence + * activity or the "empty" JSP. + * + * @throws UnsupportedEncodingException + * @throws LearnerServiceException + */ + @Override + public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, + HttpServletResponse response) throws LearnerServiceException, UnsupportedEncodingException { + + ActivityMapping actionMappings = LearningWebUtil.getActivityMapping(this.getServlet().getServletContext()); + Integer learnerId = LearningWebUtil.getUserId(); + + ICoreLearnerService learnerService = getLearnerService(); + LearnerProgress learnerProgress = LearningWebUtil.getLearnerProgress(request, learnerService); + Activity activity = LearningWebUtil.getActivityFromRequest(request, learnerService); + if (!(activity instanceof SequenceActivity)) { + LamsAction.log.error(LamsAction.className + ": activity not SequenceActivity " + activity.getActivityId()); + return mapping.findForward(ActivityMapping.ERROR); + } + + ActionForward forward = null; + SequenceActivity sequenceActivity = (SequenceActivity) activity; + Activity firstActivityInSequence = sequenceActivity.getNextActivityByParent(new NullActivity()); + + if ((firstActivityInSequence != null) && !firstActivityInSequence.isNull()) { + // Set the first activity as the current activity and display it + learnerProgress = learnerService.chooseActivity(learnerId, learnerProgress.getLesson().getLessonId(), + firstActivityInSequence, true); + forward = actionMappings.getActivityForward(firstActivityInSequence, learnerProgress, true); + return forward; + } else { + // No activities exist in the sequence, so go to the next activity. + return LearningWebUtil.completeActivity(request, response, actionMappings, learnerProgress, activity, + learnerId, learnerService, true); + } + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/BranchingForm.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/BranchingForm.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/BranchingForm.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,109 @@ +package org.lamsfoundation.lams.learning.web.form; + +import java.util.List; + +public class BranchingForm { + + private Long activityID; + private Long progressID; + private Long previewLesson; + private boolean showNextButton; + private boolean showFinishButton; + private String title; + private String type; + private List activityURLs; + +// used for updating the the progress bar + private Long lessonID; + private Integer version; + private String progressSummary; + + public Long getActivityID() { + return activityID; + } + + public void setActivityID(Long activityID) { + this.activityID = activityID; + } + + public Long getProgressID() { + return progressID; + } + + public void setProgressID(Long progressID) { + this.progressID = progressID; + } + + public Long getPreviewLesson() { + return previewLesson; + } + + public void setPreviewLesson(Long previewLesson) { + this.previewLesson = previewLesson; + } + + public boolean isShowNextButton() { + return showNextButton; + } + + public void setShowNextButton(boolean showNextButton) { + this.showNextButton = showNextButton; + } + + public boolean isShowFinishButton() { + return showFinishButton; + } + + public void setShowFinishButton(boolean showFinishButton) { + this.showFinishButton = showFinishButton; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getActivityURLs() { + return activityURLs; + } + + public void setActivityURLs(List activityURLs) { + this.activityURLs = activityURLs; + } + + public Long getLessonID() { + return lessonID; + } + + public void setLessonID(Long lessonID) { + this.lessonID = lessonID; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getProgressSummary() { + return progressSummary; + } + + public void setProgressSummary(String progressSummary) { + this.progressSummary = progressSummary; + } + +} Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/GateForm.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/GateForm.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/GateForm.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,138 @@ +package org.lamsfoundation.lams.learning.web.form; + +import java.util.Date; + +import org.lamsfoundation.lams.learningdesign.GateActivity; + +public class GateForm { + + private GateActivity gate; + private Long activityID; + private Long lessonID; + private Integer waitingLearners; + private Integer totalLearners; + private Date startingTime; + private Date endingTime; + private Date reachDate; + private Long remainTime; + private Long startOffset; + private Boolean previewLesson; + +// used for updating the the progress bar + private Integer version; + private String progressSummary; + private Boolean monitorCanOpenGate; + + public GateActivity getGate() { + return gate; + } + + public void setGate(GateActivity gate) { + this.gate = gate; + } + + public Long getActivityID() { + return activityID; + } + + public void setActivityID(Long activityID) { + this.activityID = activityID; + } + + public Long getLessonID() { + return lessonID; + } + + public void setLessonID(Long lessonID) { + this.lessonID = lessonID; + } + + public Integer getWaitingLearners() { + return waitingLearners; + } + + public void setWaitingLearners(Integer waitingLearners) { + this.waitingLearners = waitingLearners; + } + + public Integer getTotalLearners() { + return totalLearners; + } + + public void setTotalLearners(Integer totalLearners) { + this.totalLearners = totalLearners; + } + + public Date getStartingTime() { + return startingTime; + } + + public void setStartingTime(Date startingTime) { + this.startingTime = startingTime; + } + + public Date getEndingTime() { + return endingTime; + } + + public void setEndingTime(Date endingTime) { + this.endingTime = endingTime; + } + + public Date getReachDate() { + return reachDate; + } + + public void setReachDate(Date reachDate) { + this.reachDate = reachDate; + } + + public Long getRemainTime() { + return remainTime; + } + + public void setRemainTime(Long remainTime) { + this.remainTime = remainTime; + } + + public Long getStartOffset() { + return startOffset; + } + + public void setStartOffset(Long startOffset) { + this.startOffset = startOffset; + } + + public Boolean getPreviewLesson() { + return previewLesson; + } + + public void setPreviewLesson(Boolean previewLesson) { + this.previewLesson = previewLesson; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getProgressSummary() { + return progressSummary; + } + + public void setProgressSummary(String progressSummary) { + this.progressSummary = progressSummary; + } + + public Boolean getMonitorCanOpenGate() { + return monitorCanOpenGate; + } + + public void setMonitorCanOpenGate(Boolean monitorCanOpenGate) { + this.monitorCanOpenGate = monitorCanOpenGate; + } + +} Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/GroupingForm.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/GroupingForm.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/form/GroupingForm.java (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,62 @@ +package org.lamsfoundation.lams.learning.web.form; + +public class GroupingForm { + + private String title; + private Boolean previewLesson; + private Long activityID; + +// used for updating the the progress bar + private Long lessonID; + private Integer version; + private String progressSummary; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Boolean getPreviewLesson() { + return previewLesson; + } + + public void setPreviewLesson(Boolean previewLesson) { + this.previewLesson = previewLesson; + } + + public Long getActivityID() { + return activityID; + } + + public void setActivityID(Long activityID) { + this.activityID = activityID; + } + + public Long getLessonID() { + return lessonID; + } + + public void setLessonID(Long lessonID) { + this.lessonID = lessonID; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getProgressSummary() { + return progressSummary; + } + + public void setProgressSummary(String progressSummary) { + this.progressSummary = progressSummary; + } + +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/ActivityMapping.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/ActivityMapping.java (.../ActivityMapping.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/ActivityMapping.java (.../ActivityMapping.java) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -30,11 +30,9 @@ import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionForward; -import org.apache.struts.action.ForwardingActionForward; -import org.apache.struts.action.RedirectingActionForward; import org.lamsfoundation.lams.learning.service.ICoreLearnerService; import org.lamsfoundation.lams.learning.service.LearnerServiceException; -import org.lamsfoundation.lams.learning.web.action.DisplayActivityAction; +import org.lamsfoundation.lams.learning.web.controller.DisplayActivityController; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.lesson.LearnerProgress; import org.lamsfoundation.lams.lesson.Lesson; @@ -78,26 +76,26 @@ * @param progress, * the LearnerProgress associated with the Activity and learner */ - public ActionForward getActivityForward(Activity activity, LearnerProgress progress, boolean redirect) { - ActionForward actionForward = null; + public String getActivityForward(Activity activity, LearnerProgress progress, boolean redirect) { + String forward = null; - String strutsAction = this.activityMappingStrategy.getActivityAction(activity); - strutsAction = WebUtil.appendParameterToURL(strutsAction, AttributeNames.PARAM_LEARNER_PROGRESS_ID, + String action = this.activityMappingStrategy.getActivityAction(activity); + action = WebUtil.appendParameterToURL(action, AttributeNames.PARAM_LEARNER_PROGRESS_ID, progress.getLearnerProgressId().toString()); - if ( activity != null ) { - strutsAction = WebUtil.appendParameterToURL(strutsAction, AttributeNames.PARAM_ACTIVITY_ID, + if (activity != null) { + action = WebUtil.appendParameterToURL(action, AttributeNames.PARAM_ACTIVITY_ID, activity.getActivityId().toString()); } if ((activity != null) && activity.isToolActivity()) { // always use redirect false for a ToolActivity as ToolDisplayActivity // does it's own redirect - actionForward = strutsActionToForward(strutsAction, activity, false); + forward = actionToForward(action, activity, false); } else { - actionForward = strutsActionToForward(strutsAction, activity, redirect); + forward = actionToForward(action, activity, redirect); } - return actionForward; + return forward; } /** @@ -114,40 +112,40 @@ * @return * @throws UnsupportedEncodingException */ - public ActionForward getProgressForward(LearnerProgress progress, boolean redirect, boolean displayParallelFrames, + public String getProgressForward(LearnerProgress progress, boolean redirect, boolean displayParallelFrames, HttpServletRequest request, ICoreLearnerService learnerService) throws UnsupportedEncodingException { - ActionForward actionForward = null; + String forward = null; if (progress.isComplete()) { // If lesson complete forward to lesson complete action. This action will // cause a client request to clear ALL frames. Need to append the progress // id as getting to the end from an activity can't have the progress in the request // and there isn't an activity from which we can determine the lesson and hence // the progress. - String strutsAction = this.getActivityMappingStrategy().getLessonCompleteAction(); - strutsAction = WebUtil.appendParameterToURL(strutsAction, AttributeNames.PARAM_LEARNER_PROGRESS_ID, + String action = this.getActivityMappingStrategy().getLessonCompleteAction(); + action = WebUtil.appendParameterToURL(action, AttributeNames.PARAM_LEARNER_PROGRESS_ID, progress.getLearnerProgressId().toString()); - strutsAction = ActivityMapping.strutsActionToURL(strutsAction, null, true); - actionForward = this.getClearFramesForward(strutsAction, progress.getLearnerProgressId().toString()); + action = ActivityMapping.actionToURL(action, null, true); + forward = this.getClearFramesForward(action, progress.getLearnerProgressId().toString()); } else { if (!displayParallelFrames && (progress.getParallelWaiting() == LearnerProgress.PARALLEL_WAITING)) { // processing the screen WITHIN parallel activity frames. // progress is waiting, goto waiting page - String strutsAction = this.getActivityMappingStrategy().getWaitingAction(); - actionForward = this.strutsActionToForward(strutsAction, null, redirect); + String action = this.getActivityMappingStrategy().getWaitingAction(); + forward = this.actionToForward(action, null, redirect); } else { // display next activity if (progress.getParallelWaiting() == LearnerProgress.PARALLEL_WAITING_COMPLETE) { // if previous activity was a parallel activity then we need to // clear frames. String activityURL = this.getActivityURL(progress.getNextActivity()); - actionForward = this.getClearFramesForward(activityURL, progress.getLearnerProgressId().toString()); + forward = this.getClearFramesForward(activityURL, progress.getLearnerProgressId().toString()); } else { - actionForward = getActivityForward(progress.getNextActivity(), progress, redirect); + forward = getActivityForward(progress.getNextActivity(), progress, redirect); } } } - return actionForward; + return forward; } /** @@ -160,18 +158,17 @@ * @return actionForward to which to forward * @throws UnsupportedEncodingException */ - private ActionForward getClearFramesForward(String activityURL, String progressId) - throws UnsupportedEncodingException { + private String getClearFramesForward(String activityURL, String progressId) throws UnsupportedEncodingException { String encodedURL = URLEncoder.encode(activityURL, "UTF-8"); - ActionForward actionForward = null; + String forward = null; - String strutsAction = "/requestDisplay.do?url=" + encodedURL; - strutsAction = WebUtil.appendParameterToURL(strutsAction, AttributeNames.PARAM_LEARNER_PROGRESS_ID, progressId); + String action = "/requestDisplay.do?url=" + encodedURL; + action = WebUtil.appendParameterToURL(action, AttributeNames.PARAM_LEARNER_PROGRESS_ID, progressId); - actionForward = strutsActionToForward(strutsAction, null, false); - return actionForward; + forward = actionToForward(action, null, false); + return forward; } @@ -185,8 +182,8 @@ * the LearnerProgress associated with the Activity and learner */ public String getActivityURL(Activity activity) { - String strutsAction = this.activityMappingStrategy.getActivityAction(activity); - return ActivityMapping.strutsActionToURL(strutsAction, activity, true); + String action = this.activityMappingStrategy.getActivityAction(activity); + return ActivityMapping.actionToURL(action, activity, true); } /** @@ -220,8 +217,8 @@ * @param useContext, * if true prepends the server and context to the URL. */ - public static String strutsActionToURL(String strutsAction, Activity activity, boolean useContext) { - String url = strutsAction; + public static String actionToURL(String action, Activity activity, boolean useContext) { + String url = action; if (activity != null && !url.contains(AttributeNames.PARAM_ACTIVITY_ID)) { url = WebUtil.appendParameterToURL(url, AttributeNames.PARAM_ACTIVITY_ID, @@ -246,19 +243,12 @@ * should the action be a client redirect * @return */ - protected ActionForward strutsActionToForward(String strutsAction, Activity activity, boolean redirect) { - ActionForward actionForward; + protected String actionToForward(String action, Activity activity, boolean redirect) { if (redirect) { - String activityURL = ActivityMapping.strutsActionToURL(strutsAction, activity, false); - actionForward = new RedirectingActionForward(activityURL); - actionForward.setName(WebUtil.getStrutsForwardNameFromPath(strutsAction)); - } else { - actionForward = new ForwardingActionForward(strutsAction); - actionForward.setName(WebUtil.getStrutsForwardNameFromPath(strutsAction)); - + String activityURL = ActivityMapping.actionToURL(action, activity, false); + return "redirect:" + WebUtil.getStrutsForwardNameFromPath(activityURL); } - - return actionForward; + return "forward:" + WebUtil.getStrutsForwardNameFromPath(action); } /** @@ -312,16 +302,15 @@ * the window name. so prepare the urls for (2), (3) and (4) then call the close window screen and it will sort it * out. */ - public ActionForward getCloseForward(Activity justCompletedActivity, Long lessonId) - throws UnsupportedEncodingException { + public String getCloseForward(Activity justCompletedActivity, Long lessonId) throws UnsupportedEncodingException { String closeWindowURLAction = activityMappingStrategy.getCloseWindowAction(); // Always calculate the url for the "normal" next case as we won't know till we reach the close window if we need it. String action = getDisplayActivityAction(lessonId); - action = ActivityMapping.strutsActionToURL(action, null, true); - action = WebUtil.appendParameterToURL(action, DisplayActivityAction.PARAM_INITIAL_DISPLAY, "false"); + action = ActivityMapping.actionToURL(action, null, true); + action = WebUtil.appendParameterToURL(action, DisplayActivityController.PARAM_INITIAL_DISPLAY, "false"); action = URLEncoder.encode(action, "UTF-8"); if (!justCompletedActivity.isFloating()) { @@ -332,20 +321,20 @@ if ((justCompletedActivity.getParentActivity() != null) && justCompletedActivity.getParentActivity().isParallelActivity()) { action = getActivityMappingStrategy().getWaitingAction(); - action = ActivityMapping.strutsActionToURL(action, null, true); + action = ActivityMapping.actionToURL(action, null, true); action = URLEncoder.encode(action, "UTF-8"); closeWindowURLAction = WebUtil.appendParameterToURL(closeWindowURLAction, "waitURL", action); } - return strutsActionToForward(closeWindowURLAction, null, false); + return actionToForward(closeWindowURLAction, null, false); } public String getProgressBrokenURL() { - return ActivityMapping.strutsActionToURL(activityMappingStrategy.getProgressBrokenAction(), null, true); + return ActivityMapping.actionToURL(activityMappingStrategy.getProgressBrokenAction(), null, true); } public String getCompleteActivityURL(Long activityId, Long progressId) { - String url = ActivityMapping.strutsActionToURL(activityMappingStrategy.getCompleteActivityAction(), null, true); + String url = ActivityMapping.actionToURL(activityMappingStrategy.getCompleteActivityAction(), null, true); if (activityId != null) { url = WebUtil.appendParameterToURL(url, AttributeNames.PARAM_ACTIVITY_ID, activityId.toString()); } Index: lams_learning/web/WEB-INF/spring-servlet.xml =================================================================== diff -u --- lams_learning/web/WEB-INF/spring-servlet.xml (revision 0) +++ lams_learning/web/WEB-INF/spring-servlet.xml (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file Index: lams_learning/web/WEB-INF/tags/Page.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_learning/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_learning/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -4,6 +4,7 @@ <%@ taglib uri="tags-lams" prefix="lams"%> <%@ attribute name="type" required="true" rtexprvalue="true"%> +<%@ attribute name="formID" required="false" rtexprvalue="true"%> <%@ attribute name="style" required="false" rtexprvalue="true"%> <%@ attribute name="title" required="false" rtexprvalue="true"%> <%@ attribute name="titleHelpURL" required="false" rtexprvalue="true"%> @@ -88,8 +89,8 @@
- - + + ${toolForm.toolSessionID} Index: lams_learning/web/WEB-INF/tags/TextSearch.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_learning/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_learning/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -32,12 +32,11 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ taglib uri="tags-lams" prefix="lams" %> <%-- Required attributes --%> <%@ attribute name="sessionMapID" required="true" rtexprvalue="true" %> -<%@ attribute name="wrapInFormTag" required="true" rtexprvalue="true" %> <%-- Optional attributes --%> <%@ attribute name="action" required="false" rtexprvalue="true" %> @@ -53,10 +52,10 @@ <%-- Default value for message key --%> - + - + @@ -85,52 +84,40 @@ - -
- - -

- - - - - - - - - - - - - - - - - -
- - - -
- - - -
- - - -
- - - -
- - - - - - - - - + +

+ + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
\ No newline at end of file Index: lams_learning/web/WEB-INF/web.xml =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_learning/web/WEB-INF/web.xml (.../web.xml) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_learning/web/WEB-INF/web.xml (.../web.xml) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -75,24 +75,10 @@ - action - org.apache.struts.action.ActionServlet - - config - /WEB-INF/struts-config.xml - - - debug - 999 - - - detail - 2 - - - validate - true - + spring + + org.springframework.web.servlet.DispatcherServlet + 1 @@ -124,7 +110,7 @@ - action + spring *.do Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java (.../GroupingAJAXAction.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java (.../GroupingAJAXAction.java) (revision 6f37a4eb8b2023d6e6dffceffa91ebdbf74c54f5) @@ -43,7 +43,7 @@ import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; -import org.lamsfoundation.lams.learning.web.action.GroupingAction; +import org.lamsfoundation.lams.learning.web.controller.GroupingController; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.Group; import org.lamsfoundation.lams.learningdesign.GroupComparator; @@ -164,7 +164,7 @@ group.setUsers(sortedUsers); } - request.setAttribute(GroupingAction.GROUPS, groups); + request.setAttribute(GroupingController.GROUPS, groups); // go to a view only screen for random grouping return mapping.findForward(GroupingAJAXAction.VIEW_GROUPS_SCREEN); } @@ -204,7 +204,7 @@ } } - request.setAttribute(GroupingAction.GROUPS, groups); + request.setAttribute(GroupingController.GROUPS, groups); request.setAttribute("isCourseGrouping", true); // flag to page it is a course grouping so use the field names for OrganisationGroup return mapping.findForward(GroupingAJAXAction.VIEW_GROUPS_SCREEN); }