Index: lams_central/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== diff -u -r5491463bab18676cd7fa0b47ea36e66e0f809cad -ra0bea10c9022cc2146b3067858932029ca721683 --- lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 5491463bab18676cd7fa0b47ea36e66e0f809cad) +++ lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision a0bea10c9022cc2146b3067858932029ca721683) @@ -752,4 +752,8 @@ label.search.for.courses =Search for courses +label.save.as.course.grouping =Save as a Course Grouping +label.enter.course.grouping.name =Please enter name for the new course grouping +label.course.groups.name.not.unique =Course grouping with such name already exists. Please enter another one. + #======= End labels: Exported 744 labels for en AU ===== Index: lams_central/web/css/orgGroup.css =================================================================== diff -u -rb07b3de82e183f1351bb22c32d269b5077e82457 -ra0bea10c9022cc2146b3067858932029ca721683 --- lams_central/web/css/orgGroup.css (.../orgGroup.css) (revision b07b3de82e183f1351bb22c32d269b5077e82457) +++ lams_central/web/css/orgGroup.css (.../orgGroup.css) (revision a0bea10c9022cc2146b3067858932029ca721683) @@ -121,3 +121,14 @@ background-color: #5c9ccc !important; color: white !important; } + +#save-course-grouping-container { + display: inline-block; + width: 100%; + margin-bottom: -7px; +} +.dialogContainer { + display: none; + -webkit-overflow-scrolling: touch !important; + overflow: auto; +} Index: lams_central/web/includes/javascript/orgGroup.js =================================================================== diff -u -r2d50303390a6ea1ec157a3a1390ecf3833c0339c -ra0bea10c9022cc2146b3067858932029ca721683 --- lams_central/web/includes/javascript/orgGroup.js (.../orgGroup.js) (revision 2d50303390a6ea1ec157a3a1390ecf3833c0339c) +++ lams_central/web/includes/javascript/orgGroup.js (.../orgGroup.js) (revision a0bea10c9022cc2146b3067858932029ca721683) @@ -481,4 +481,114 @@ $('.removeGroupButton', container).remove(); // $('input', container).attr('readonly', 'readonly'); $('div.draggableUser', container).off('click').draggable('disable'); -} \ No newline at end of file +} + +/** + * *************** Save as a course grouping dialog *************** + */ + +//open save as a course grouping dialog +function saveAsCourseGrouping() { + $('#saveAsCourseGroupingDialog').modal('show'); +} + +$(document).ready(function(){ + + // sets up dialog for editing class + var saveAsCourseGroupingDialog = showDialog('saveAsCourseGroupingDialog',{ + 'autoOpen' : false, + 'width' : 510, + 'title' : LABELS.SAVE_AS_COURSE_GROUPING_LABEL, + 'resizable' : true, + 'open' : function(){ + //focus name text field + setTimeout( + function() { + $('#dialog-course-grouping-name').focus(); + }, + 700 + ); + }, + 'close' : function(){ + //reset dialog to its initial state + resetSaveGroupingDialog(); + $('#dialog-course-grouping-name', this).val(""); + } + }, false); + + $('.modal-body', saveAsCourseGroupingDialog).empty().append($('#save-course-grouping-dialog-contents').show()); + + //save button handler + $('#dialog-save-button', saveAsCourseGroupingDialog).click(function() { + var dialog = $('#saveAsCourseGroupingDialog'), + name = $('#dialog-course-grouping-name', dialog).val(); + + //name can't be blank + if (!name || /^\s*$/.test(name)) { + $('#dialog-course-grouping-name', dialog).addClass("alert-danger"); + $("#span-tooltip", dialog).addClass("alert-danger").text(LABELS.NAME_BLANK_LABEL); + return; + } + + //name should be unique + $.ajax({ + dataType : 'json', + url : LAMS_URL + 'monitoring/grouping.do', + cache : false, + async : false, + data : { + 'method' : 'checkGroupingNameUnique', + 'organisationID' : organisationId, + 'name' : name + }, + success : function(response) { + if (response.isGroupingNameUnique) { + $.ajax({ + dataType : 'json', + url : LAMS_URL + 'monitoring/grouping.do', + cache : false, + async : false, + data : { + 'method' : 'saveAsCourseGrouping', + 'organisationID' : organisationId, + 'activityID' : groupingActivityId, + 'name' : name + }, + success : function(response) { + $('#saveAsCourseGroupingDialog').modal('hide'); + alert(LABELS.SAVED_SUCCESSFULLY_LABEL); + } + }); + + } else { + $('#dialog-course-grouping-name', dialog).addClass("alert-danger"); + $("#span-tooltip", dialog).addClass("alert-danger").text(LABELS.NAME_NOT_UNIQUE_LABEL); + } + } + }); + }); + + //close button handler + $('#dialog-close-button', saveAsCourseGroupingDialog).click(function(){ + $('#saveAsCourseGroupingDialog').modal('hide'); + }); + + // ability to save a grouping on pressing the Enter key in the name input field + $('#dialog-course-grouping-name', saveAsCourseGroupingDialog).on('keyup', function (e) { + //remove alert class if it was applied + if ($("#span-tooltip", saveAsCourseGroupingDialog).hasClass("alert-danger")) { + resetSaveGroupingDialog(); + } + + if (e.keyCode == 13) { + $('#dialog-save-button', saveAsCourseGroupingDialog).trigger( "click" ); + } + }); + + //reset dialog to its initial state + function resetSaveGroupingDialog() { + $("#span-tooltip", saveAsCourseGroupingDialog).removeClass("alert-danger").text(LABELS.ENTER_COURSE_GROUPING_NAME_LABEL); + $('#dialog-course-grouping-name', saveAsCourseGroupingDialog).removeClass("alert alert-danger"); + } + +}); \ No newline at end of file Index: lams_central/web/orgGroup.jsp =================================================================== diff -u -r2d50303390a6ea1ec157a3a1390ecf3833c0339c -ra0bea10c9022cc2146b3067858932029ca721683 --- lams_central/web/orgGroup.jsp (.../orgGroup.jsp) (revision 2d50303390a6ea1ec157a3a1390ecf3833c0339c) +++ lams_central/web/orgGroup.jsp (.../orgGroup.jsp) (revision a0bea10c9022cc2146b3067858932029ca721683) @@ -44,12 +44,31 @@ GROUP_LOCK_LABEL : decoderDiv.html('').text(), - TRANSFER_LOCKED_LABEL : decoderDiv.html('').text() + TRANSFER_LOCKED_LABEL : decoderDiv.html('').text(), + + SAVE_AS_COURSE_GROUPING_LABEL : decoderDiv.html('').text(), + + NAME_BLANK_LABEL : decoderDiv.html('').text(), + + NAME_NOT_UNIQUE_LABEL : decoderDiv.html('').text(), + + ENTER_COURSE_GROUPING_NAME_LABEL : decoderDiv.html('').text(), + + SAVED_SUCCESSFULLY_LABEL : decoderDiv.html('').text() }; + +
+ +
+
+
@@ -125,5 +144,26 @@
+ + +
+ + + + +
+ +
+ +
+ + +
+
+ \ No newline at end of file Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java =================================================================== diff -u -r51f0b0d75529c154910d175aad7d0f26acdf0597 -ra0bea10c9022cc2146b3067858932029ca721683 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java (.../GroupingAJAXAction.java) (revision 51f0b0d75529c154910d175aad7d0f26acdf0597) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/GroupingAJAXAction.java (.../GroupingAJAXAction.java) (revision a0bea10c9022cc2146b3067858932029ca721683) @@ -25,14 +25,19 @@ import java.io.IOException; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import org.apache.commons.lang.StringUtils; import org.apache.struts.action.ActionForm; @@ -49,11 +54,20 @@ import org.lamsfoundation.lams.lesson.service.LessonServiceException; import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.monitoring.service.MonitoringServiceProxy; +import org.lamsfoundation.lams.security.ISecurityService; +import org.lamsfoundation.lams.usermanagement.OrganisationGroup; +import org.lamsfoundation.lams.usermanagement.OrganisationGrouping; +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.usermanagement.util.FirstNameAlphabeticComparator; 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 org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; /** * The action servlet that provides the support for the @@ -78,6 +92,8 @@ public static final String PARAM_MAY_DELETE = "mayDelete"; public static final String PARAM_USED_FOR_BRANCHING = "usedForBranching"; public static final String PARAM_VIEW_MODE = "viewMode"; + + private static ISecurityService securityService; /** * Start the process of doing the chosen grouping @@ -148,29 +164,6 @@ } /** - * Remove a list of users from a group. Designed to respond to an AJAX call. - * - * Input parameters: activityID, name: group name, members: comma separated list of users - * - * Output format: no data returned - just the header - */ - public ActionForward removeMembers(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException, LessonServiceException { - - Long activityID = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); - Long groupID = WebUtil.readLongParam(request, AttributeNames.PARAM_GROUP_ID); - String members = WebUtil.readStrParam(request, GroupingAJAXAction.PARAM_MEMBERS, true); - if (members != null) { - String[] membersSplit = members.split(","); - IMonitoringService monitoringService = MonitoringServiceProxy - .getMonitoringService(getServlet().getServletContext()); - monitoringService.removeUsersFromGroup(activityID, groupID, membersSplit); - } - writeAJAXOKResponse(response); - return null; - } - - /** * Moves users between groups, removing them from previous group and creating a new one, if needed. */ public ActionForward addMembers(ActionMapping mapping, ActionForm form, HttpServletRequest request, @@ -259,7 +252,60 @@ response.getWriter().write(responseJSON.toString()); return null; } + + /** + * Stores lesson grouping as a course grouping. + */ + public ActionForward saveAsCourseGrouping(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + IMonitoringService monitoringService = MonitoringServiceProxy + .getMonitoringService(getServlet().getServletContext()); + IUserManagementService userManagementService = MonitoringServiceProxy + .getUserManagementService(getServlet().getServletContext()); + HttpSession ss = SessionManager.getSession(); + Integer userId = ((UserDTO) ss.getAttribute(AttributeNames.USER)).getUserID(); + Integer organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + String newGroupingName = request.getParameter("name"); + + // check if user is allowed to view and edit groupings + if (!getSecurityService().hasOrgRole(organisationId, userId, + new String[] { Role.GROUP_ADMIN, Role.GROUP_MANAGER, Role.MONITOR, Role.AUTHOR }, + "view organisation groupings", false)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a participant in the organisation"); + return null; + } + Long activityID = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + Activity activity = monitoringService.getActivityById(activityID); + Grouping grouping = activity.isChosenBranchingActivity() ? activity.getGrouping() + : ((GroupingActivity) activity).getCreateGrouping(); + + // iterate over groups + List orgGroups = new LinkedList(); + for (Group group : grouping.getGroups()) { + OrganisationGroup orgGroup = new OrganisationGroup(); + //groupId and GroupingId will be set during userManagementService.saveOrganisationGrouping() call + orgGroup.setName(group.getGroupName()); + HashSet users = new HashSet(); + users.addAll(group.getUsers()); + orgGroup.setUsers(users); + + orgGroups.add(orgGroup); + } + + OrganisationGrouping orgGrouping = new OrganisationGrouping(); + orgGrouping.setOrganisationId(organisationId); + orgGrouping.setName(newGroupingName); + + userManagementService.saveOrganisationGrouping(orgGrouping, orgGroups); + + response.setContentType("application/json;charset=utf-8"); + JSONObject responseJSON = new JSONObject(); + responseJSON.put("result", true); + response.getWriter().write(responseJSON.toString()); + return null; + } + /** * Renames the group. */ @@ -277,7 +323,32 @@ } return null; } + + /** + * Checks if a course grouping name is unique inside of this organisation and thus whether the new group can be named using it + */ + public ActionForward checkGroupingNameUnique(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + IUserManagementService userManagementService = MonitoringServiceProxy.getUserManagementService(getServlet().getServletContext()); + + Integer organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + String newGroupingName = request.getParameter("name"); + // Checks if a course grouping name is unique inside of this group and thus new group can have it + HashMap properties = new HashMap(); + properties.put("organisationId", organisationId); + properties.put("name", newGroupingName); + List orgGroupings = userManagementService.findByProperties(OrganisationGrouping.class, + properties); + boolean isGroupingNameUnique = orgGroupings.isEmpty(); + + JSONObject responseJSON = new JSONObject(); + responseJSON.put("isGroupingNameUnique", isGroupingNameUnique); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write(responseJSON.toString()); + return null; + } + /** * Checks if a group can be removed and performs it. */ @@ -311,4 +382,13 @@ response.getWriter().write(responseJSON.toString()); return null; } + + private ISecurityService getSecurityService() { + if (securityService == null) { + WebApplicationContext ctx = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + securityService = (ISecurityService) ctx.getBean("securityService"); + } + return securityService; + } }