Index: assignment-bundles/resources/assignment_es.properties =================================================================== --- assignment-bundles/resources/assignment_es.properties (revision 123296) +++ assignment-bundles/resources/assignment_es.properties (working copy) @@ -577,4 +577,9 @@ send.submission.releasereturn.email.options=Opciones de correo de env\u00EDos de Devoluci\u00F3n de tareas: send.submission.releasereturn.email.none=No enviar una notificaci\u00F3n por correo al alumno cuando se corrija la tarea y el alumno pueda realizar reenv\u00EDos send.submission.releasereturn.email=Enviar una notificaci\u00F3n por correo al alumno cuando se corrija la tarea y el alumno pueda realizar reenv\u00EDos -attempty = No se permite subir adjuntos vac\u00EDos: ''{0}''. \ No newline at end of file +attempty = No se permite subir adjuntos vac\u00EDos: ''{0}''. +#Samoo S.L. grade by group +gen.assign.gra.group=Calificaci\u00F3n por grupos +grouplist.show.students=Mostrar alumnos del grupo +grouplist.hide.students=Esconder alumnos del grupo +gradingsub.groupcomment=Utilice el \u00E1rea de texto para introducir un comentario adicional a todos los env\u00EDos del grupo. Index: assignment-bundles/resources/assignment.properties =================================================================== --- assignment-bundles/resources/assignment.properties (revision 123296) +++ assignment-bundles/resources/assignment.properties (working copy) @@ -846,3 +846,9 @@ send.submission.releasereturn.email.options=Released Resubmission Notification Email Options: send.submission.releasereturn.email.none=Do not send notification email to student when the grade is released and resubmission is available send.submission.releasereturn.email=Send notification email to student when the grade is released and resubmission is available + +#Samoo S.L. grade by group +gen.assign.gra.group=Grade by group +grouplist.show.students=Show students in group +grouplist.hide.students=Hide students in group +gradingsub.groupcomment=Use the box below to enter additional summary comments to all submissions group. \ No newline at end of file Index: assignment-tool/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java =================================================================== --- assignment-tool/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java (revision 123296) +++ assignment-tool/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java (working copy) @@ -559,6 +559,9 @@ /** **************************** instructor's view student submission ***************** */ // the show/hide table based on member id private static final String STUDENT_LIST_SHOW_TABLE = "STUDENT_LIST_SHOW_TABLE"; + + // the show/hide table based on group id + private static final String GROUP_LIST_SHOW_TABLE = "GROUP_LIST_SHOW_TABLE"; /** **************************** student view grade submission id *********** */ private static final String VIEW_GRADE_SUBMISSION_ID = "view_grade_submission_id"; @@ -629,6 +632,12 @@ /** The student view of assignment submission report */ private static final String MODE_STUDENT_VIEW = "stuvie"; // set in velocity template + + /** The assignment student groups view*/ + private static final String MODE_INSTRUCTOR_LIST_ASSIGNMENT_GROUPS = "Assignment.mode_instructor_list_assignment_groups"; + + /** The assignment grade group submission view*/ + private static final String MODE_INSTRUCTOR_GRADE_GROUP_SUBMISSIONS = "Assignment.mode_instructor_grade_group_submissions"; /** The option view */ private static final String MODE_OPTIONS= "options"; // set in velocity template @@ -691,6 +700,12 @@ /** The options page */ private static final String TEMPLATE_OPTIONS = "_options"; + /** The assignment groups page */ + private static final String TEMPLATE_INSTRUCTOR_LIST_ASSIGNMENT_GROUPS = "_instructor_list_assignment_groups"; + + /** The assignment groups page */ + private static final String TEMPLATE_INSTRUCTOR_GRADE_GROUP_SUBMISSIONS = "_instructor_grading_group_submissions"; + /** The opening mark comment */ private static final String COMMENT_OPEN = "{{"; @@ -1082,6 +1097,16 @@ template = build_options_context(portlet, context, data, state); } } + else if (MODE_INSTRUCTOR_LIST_ASSIGNMENT_GROUPS.equals(mode)) + { + // build the context for the instructor's assignment groups view + template = build_instructor_view_assignment_groups(portlet, context, data, state); + } + else if (MODE_INSTRUCTOR_GRADE_GROUP_SUBMISSIONS.equals(mode)) + { + // build the context for the instructor's assignment groups view + template = build_instructor_view_grade_group_submissions(portlet, context, data, state); + } if (template == null) @@ -14354,4 +14379,625 @@ String lOptions = ServerConfigurationService.getString("assignment.letterGradeOptions", "A+,A,A-,B+,B,B-,C+,C,C-,D+,D,D-,E,F"); context.put("letterGradeOptions", StringUtils.split(lOptions, ",")); } + + /** + * Samoo S.L. + * + * Action is to show student groups of the assigment + * @param data + * + */ + public void doView_assignment_groups(RunData data){ + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + ParameterParser params = data.getParameters(); + + //add to the state the assignment id + String assignmentId = StringUtils.trimToNull(params.getString("assignmentId")); + state.setAttribute("assignmentId", assignmentId); + + // get current site + Site site = null; + String siteId = ToolManager.getCurrentPlacement().getContext(); + try { + site = SiteService.getSite(siteId); + } catch (IdUnusedException e) { + M_log.error(this + ":doView_assignment_groups Cannot find site with id " + siteId, e); + } + //add to the state the current site + state.setAttribute("site", site); + + state.setAttribute(STATE_MODE, MODE_INSTRUCTOR_LIST_ASSIGNMENT_GROUPS); + } + + /** + * Samoo S.L. + * build the instructor view of assignment groups + */ + protected String build_instructor_view_assignment_groups(VelocityPortlet portlet, Context context, RunData data, + SessionState state) + { + //get from the state the assignment id + String assignmentId = (String) state.getAttribute("assignmentId"); + context.put("assignmentId", assignmentId); + context.put("groupListShowSet", state.getAttribute(GROUP_LIST_SHOW_TABLE)); + //get from the state the current site + Site site = (Site) state.getAttribute("site"); + + Assignment a = getAssignment(assignmentId, "build_instructor_view_assignment_groups", state); + + //get assignment group ids + Collection assignmentGroupIds = a.getGroups(); + + //create group list + List assignmentGroups = new ArrayList(assignmentGroupIds.size()); + + for (String groupId : assignmentGroupIds) { + assignmentGroups.add(site.getGroup(groupId)); + } + //sort groups and add to the context + context.put("assignmentGroups", new SortedIterator(assignmentGroups.iterator(), new AssignmentComparator(state, SORTED_BY_GROUP_TITLE, Boolean.TRUE.toString()))); + + //create users for group map. . + HashMap groupUsersMap = new HashMap(assignmentGroupIds.size()); + + //sort group students and add to the context + for (Group group : assignmentGroups) { + List groupUsers = new ArrayList(); + for (Member member : group.getMembers()) { + try { + if(!AuthzGroupService.isAllowed(member.getUserId(),AssignmentService.SECURE_ADD_ASSIGNMENT_SUBMISSION,SiteService.siteReference(site.getId()))) continue; + groupUsers.add(UserDirectoryService.getUser(member.getUserId())); + } catch (UserNotDefinedException e) { + M_log.error(this + ":build_instructor_view_assignment_groups Cannot find user with id " + member.getUserId(), e); + } + } + groupUsersMap.put(group.getId(), new SortedIterator(groupUsers.iterator(), new UserComparator())); + } + + context.put("groupUsersMap", groupUsersMap); + + String template = (String) getContext(data).get("template"); + return template + TEMPLATE_INSTRUCTOR_LIST_ASSIGNMENT_GROUPS; + } + + /** + * Action is to show the group student list + */ + public void doShow_group_students(RunData data) + { + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + Set t = (Set) state.getAttribute(GROUP_LIST_SHOW_TABLE); + ParameterParser params = data.getParameters(); + + String id = params.getString("groupId"); + // add the group id into the table + t.add(id); + + state.setAttribute(GROUP_LIST_SHOW_TABLE, t); + + } // doShow_group_students + + /** + * Action is to hide the group the student list + */ + public void doHide_group_students(RunData data) + { + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + Set t = (Set) state.getAttribute(GROUP_LIST_SHOW_TABLE); + ParameterParser params = data.getParameters(); + + String id = params.getString("groupId"); + // remove the group id from the table + t.remove(id); + + state.setAttribute(GROUP_LIST_SHOW_TABLE, t); + + } // doHide_group_students + + /** + * Samoo S.L. + * + * Action is to show the group grade submission screen + * @param data + */ + public void doGrade_group_submissions(RunData data) + { + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + ParameterParser params = data.getParameters(); + + String assignmentId = StringUtils.trimToNull(params.getString("assignmentId")); + String groupId = StringUtils.trimToNull(params.getString("groupId")); + + state.setAttribute(GRADE_SUBMISSION_ASSIGNMENT_ID, assignmentId); + state.setAttribute("groupId", groupId); + + // initialize the resubmission params + assignment_resubmission_option_into_state( getAssignment(assignmentId, "doGrade_group_submissions", state), null, state); + + state.setAttribute(STATE_MODE, MODE_INSTRUCTOR_GRADE_GROUP_SUBMISSIONS); + } + + /** + * Samoo S.L. + * build the instructor view for assignment submission group grading + */ + protected String build_instructor_view_grade_group_submissions(VelocityPortlet portlet, Context context, RunData data, + SessionState state) + { + //assignment + String assignmentId = (String) state.getAttribute(GRADE_SUBMISSION_ASSIGNMENT_ID); + context.put(GRADE_SUBMISSION_ASSIGNMENT_ID, assignmentId); + Assignment assignment = getAssignment(assignmentId, "build_instructor_view_grade_group_submissions", state); + context.put("assignment", assignment); + context.put("assignment_expand_flag", state.getAttribute(GRADE_SUBMISSION_ASSIGNMENT_EXPAND_FLAG)); + String groupId = (String) state.getAttribute("groupId"); + context.put("groupId", groupId); + context.put("contentTypeImageService", state.getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE)); + Site site = (Site) state.getAttribute("site"); + + //get a user list for the group + Group group = site.getGroup(groupId); + Set groupMembers = group.getMembers(); + context.put("groupName", group.getTitle()); + List groupUsers = new ArrayList(groupMembers.size()); + for (Member member : groupMembers) { + try { + if(!AuthzGroupService.isAllowed(member.getUserId(),AssignmentService.SECURE_ADD_ASSIGNMENT_SUBMISSION,SiteService.siteReference(site.getId()))) continue; + groupUsers.add(UserDirectoryService.getUser(member.getUserId())); + } catch (UserNotDefinedException e) { + M_log.error(this + ":build_instructor_view_grade_group_submissions Cannot find user with id " + member.getUserId(), e); + } + } + //set the user list + context.put("students", new SortedIterator(groupUsers.iterator(), new UserComparator())); + + //set submission type + context.put("submissionType", assignment.getContent().getTypeOfSubmission()); + // is this a non-electronic submission type of assignment + context.put("nonElectronic", (assignment!=null && assignment.getContent().getTypeOfSubmission() == Assignment.NON_ELECTRONIC_ASSIGNMENT_SUBMISSION)?Boolean.TRUE:Boolean.FALSE); + + //map user with submissions + HashMap userSubmissionsMap = new HashMap(groupUsers.size()); + for (User user : groupUsers) { + userSubmissionsMap.put(user.getId(), getSubmission(assignmentId, user, "build_instructor_view_grade_group_submissions", state)); + } + state.setAttribute("userSubmissions", userSubmissionsMap); + context.put("userSubmissions", userSubmissionsMap); + + //set grading informations + boolean allowToGrade=true; + String associateGradebookAssignment = StringUtils.trimToNull(assignment.getProperties().getProperty(AssignmentService.PROP_ASSIGNMENT_ASSOCIATE_GRADEBOOK_ASSIGNMENT)); + if (associateGradebookAssignment != null) + { + GradebookService g = (GradebookService) ComponentManager.get("org.sakaiproject.service.gradebook.GradebookService"); + String gradebookUid = ToolManager.getInstance().getCurrentPlacement().getContext(); + if (g != null && g.isGradebookDefined(gradebookUid)) + { + if (!g.currentUserHasGradingPerm(gradebookUid)) + { + context.put("notAllowedToGradeWarning", rb.getString("not_allowed_to_grade_in_gradebook")); + allowToGrade=false; + } + } + } + context.put("allowToGrade", Boolean.valueOf(allowToGrade)); + + // grading option + context.put("withGrade", state.getAttribute(WITH_GRADES)); + context.put("name_grade", GRADE_SUBMISSION_GRADE); + + //set the feedback comment text area name + context.put("name_feedback_comment", GRADE_SUBMISSION_FEEDBACK_COMMENT); + + // put the re-submission info into context + putTimePropertiesInContext(context, state, "Resubmit", ALLOW_RESUBMIT_CLOSEMONTH, ALLOW_RESUBMIT_CLOSEDAY, ALLOW_RESUBMIT_CLOSEYEAR, ALLOW_RESUBMIT_CLOSEHOUR, ALLOW_RESUBMIT_CLOSEMIN, ALLOW_RESUBMIT_CLOSEAMPM); + assignment_resubmission_option_into_context(context, state); + + String template = (String) getContext(data).get("template"); + return template + TEMPLATE_INSTRUCTOR_GRADE_GROUP_SUBMISSIONS ; + } + + /** + * Samoo S.L. + * assignment group grading + */ + public void doSubmissionGroupGrading_form(RunData data) + { + ParameterParser params = data.getParameters(); + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + + String option = (String) params.getString("option"); + if (option != null) + { + if ("returngrade".equals(option)) + { + // return grading for all users of the group + doReturn_grade_submission_group(data); + } + else if ("savegrade".equals(option)) + { + // save grading for all users of the group + doSave_grade_submission_group(data); + } + else if ("cancelgrade".equals(option)) + { + // cancel grading + doCancel_grade_submission_group(data); + } + else if ("hide_instruction".equals(option)) + { + // hide the assignment instruction + state.setAttribute(GRADE_SUBMISSION_ASSIGNMENT_EXPAND_FLAG, Boolean.valueOf(false)); + } + else if ("show_instruction".equals(option)) + { + // show the assignment instruction + state.setAttribute(GRADE_SUBMISSION_ASSIGNMENT_EXPAND_FLAG, Boolean.valueOf(true)); + } + + } + } + + /** + * Samoo S.L. + * Action is to save the grade to submission group + */ + public void doSave_grade_submission_group(RunData data) + { + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + + //get current assignment info + String contextString = (String) state.getAttribute(STATE_CONTEXT_STRING); + String assignmentId = (String) state.getAttribute("assignmentId"); + Assignment assignment = getAssignment(assignmentId, "doSave_grade_submission_group", state); + + //iterate over each student of the group + HashMap userSubmissionsMap = (HashMap) state.getAttribute("userSubmissions"); + for (String userId : userSubmissionsMap.keySet()) { + AssignmentSubmission submission = userSubmissionsMap.get(userId); + + //check if the submission is valid + try{ + //20130116 - daniel.merino - Sustituyo este codigo por el que esta vigente en 2.9.0 + //enableSecurityAdvisor(); + SecurityAdvisor sa = new SecurityAdvisor() { + public SecurityAdvice isAllowed(String userId, String function, String reference) + { + return function.equals(m_contentHostingService.AUTH_RESOURCE_ADD)?SecurityAdvice.ALLOWED:SecurityAdvice.PASS; + } + }; + m_securityService.pushAdvisor(sa); + + AssignmentSubmissionEdit edit = null; + //check user submission existence + if(submission == null){ + //creating submission for the student of the group + edit = AssignmentService.addSubmission(contextString , assignment.getId(), userId); + }else{ + //check if the submission is a fake created by other page + if(submission.getStatus().equals(rb.get("listsub.nosub"))){ + edit = AssignmentService.editSubmission(submission.getReference()); + } + } + //set default submission parameters and commit the student submission + if(edit!=null){ + edit.setSubmitted(false); + edit.setAssignment(assignment); + AssignmentService.commitEdit(edit); + } + submission = AssignmentService.getSubmission(assignment.getId(), UserDirectoryService.getUser(userId)); + //20130116 - daniel.merino - Sustituyo este codigo por el que esta vigente en 2.9.0 + //disableSecurityAdvisor(); + m_securityService.popAdvisor(sa); + + //the user submission is valid, configure it from the form parameters + readGradeGroupForm(userId, submission, data, state, "save"); + + String groupGrade = (String) state.getAttribute(GRADE_SUBMISSION_GRADE); + + if (state.getAttribute(STATE_MESSAGE) == null) + { + state.setAttribute(GRADE_SUBMISSION_SUBMISSION_ID, submission.getReference()); + state.setAttribute(GRADE_SUBMISSION_ASSIGNMENT_ID, assignmentId); + grade_submission_option(data, "save"); + state.removeAttribute(GRADE_SUBMISSION_SUBMISSION_ID); + state.removeAttribute(GRADE_SUBMISSION_FEEDBACK_COMMENT); + state.removeAttribute(GRADE_SUBMISSION_FEEDBACK_TEXT); + } + } + catch (PermissionException e) + { + addAlert(state, rb.getString("youarenot13")); + M_log.warn(this + ":doSave_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + catch (IdUnusedException e){ + M_log.warn(this + ":doSave_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + catch (InUseException e) { + M_log.warn(this + ":doSave_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + catch (UserNotDefinedException e) { + M_log.warn(this + ":doSave_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + }//for + //reset state variables + state.removeAttribute(GRADE_SUBMISSION_GRADE); + state.removeAttribute(ATTACHMENTS); + state.setAttribute(STATE_MODE, MODE_LIST_ASSIGNMENTS); + } // doSave_grade_submission_group + + /** + * Samoo S.L. + * Action is to return submission with or without grade + */ + public void doReturn_grade_submission_group(RunData data) + { + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + + //get current assignment info + String contextString = (String) state.getAttribute(STATE_CONTEXT_STRING); + String assignmentId = (String) state.getAttribute("assignmentId"); + Assignment assignment = getAssignment(assignmentId, "doReturn_grade_submission_group", state); + + //iterate over each student of the group + HashMap userSubmissionsMap = (HashMap) state.getAttribute("userSubmissions"); + for (String userId : userSubmissionsMap.keySet()) { + AssignmentSubmission submission = userSubmissionsMap.get(userId); + + //check if the submission is valid + try{ + //20130116 - daniel.merino - Sustituyo este codigo por el que esta vigente en 2.9.0 + //enableSecurityAdvisor(); + SecurityAdvisor sa = new SecurityAdvisor() { + public SecurityAdvice isAllowed(String userId, String function, String reference) + { + return function.equals(m_contentHostingService.AUTH_RESOURCE_ADD)?SecurityAdvice.ALLOWED:SecurityAdvice.PASS; + } + }; + m_securityService.pushAdvisor(sa); + AssignmentSubmissionEdit edit = null; + //check user submission existence + if(submission == null){ + //creating submission for the student of the group + edit = AssignmentService.addSubmission(contextString , assignment.getId(), userId); + }else{ + //check if the submission is a fake created by other page + if(submission.getStatus().equals(rb.get("listsub.nosub"))){ + edit = AssignmentService.editSubmission(submission.getReference()); + } + } + //set default submission parameters and commit the student submission + if(edit!=null){ + edit.setSubmitted(true); + edit.setAssignment(assignment); + AssignmentService.commitEdit(edit); + } + submission = AssignmentService.getSubmission(assignment.getId(), UserDirectoryService.getUser(userId)); + //20130116 - daniel.merino - Sustituyo este codigo por el que esta vigente en 2.9.0 + //disableSecurityAdvisor(); + m_securityService.popAdvisor(sa); + + //the user submission is valid, configure it from the form parameters + readGradeGroupForm(userId, submission, data, state, "return"); + + String groupGrade = (String) state.getAttribute(GRADE_SUBMISSION_GRADE); + + if (state.getAttribute(STATE_MESSAGE) == null) + { + state.setAttribute(GRADE_SUBMISSION_SUBMISSION_ID, submission.getReference()); + state.setAttribute(GRADE_SUBMISSION_ASSIGNMENT_ID, assignmentId); + grade_submission_option(data, "return"); + state.removeAttribute(GRADE_SUBMISSION_SUBMISSION_ID); + state.removeAttribute(GRADE_SUBMISSION_FEEDBACK_COMMENT); + state.removeAttribute(GRADE_SUBMISSION_FEEDBACK_TEXT); + } + } + catch (PermissionException e) + { + addAlert(state, rb.getString("youarenot13")); + M_log.warn(this + ":doReturn_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + catch (IdUnusedException e){ + M_log.warn(this + ":doReturn_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + catch (InUseException e) { + M_log.warn(this + ":doReturn_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + catch (UserNotDefinedException e) { + M_log.warn(this + ":doReturn_grade_submission_group " + e.getClass()+ " " + e.getMessage()); + } + }//for + //reset state variables + state.removeAttribute(GRADE_SUBMISSION_GRADE); + state.removeAttribute(ATTACHMENTS); + state.setAttribute(STATE_MODE, MODE_LIST_ASSIGNMENTS); + } // doReturn_grade_submission_group + + /** + * Samoo S.L. + * Action is to cancel the grade submission group process + */ + public void doCancel_grade_submission_group(RunData data) + { + // put submission information into state + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + + state.setAttribute(STATE_MODE, MODE_INSTRUCTOR_GRADE_GROUP_SUBMISSIONS); + } // doCancel_grade_submission + + /** + * Samoo S.L. + * read grade information form and see if any grading information has been changed + * @param data + * @param state + * @param gradeOption + * @return + */ + public boolean readGradeGroupForm(String userId, AssignmentSubmission submission, RunData data, SessionState state, String gradeOption) + { + // whether user has changed anything from previous grading information + boolean hasChange = false; + + ParameterParser params = data.getParameters(); + + // security check for allowing grading submission or not + if (AssignmentService.allowGradeSubmission(submission.getReference())) + { + int typeOfGrade = -1; + boolean withGrade = state.getAttribute(WITH_GRADES) != null ? ((Boolean) state.getAttribute(WITH_GRADES)).booleanValue() + : false; + + boolean checkForFormattingErrors = true; // so that grading isn't held up by formatting errors + String feedbackComment = processFormattedTextFromBrowser(state, params.getCleanString(GRADE_SUBMISSION_FEEDBACK_COMMENT), + checkForFormattingErrors); + + // comment value changed? + if (feedbackComment != null) + { + //add new text line comment to the old one + hasChange = true; + if(StringUtils.trimToNull(submission.getFeedbackComment())!= null){ + feedbackComment = submission.getFeedbackComment() + "
" + feedbackComment; + } + state.setAttribute(GRADE_SUBMISSION_FEEDBACK_COMMENT, feedbackComment); + } + + + String feedbackText = processAssignmentFeedbackFromBrowser(state, params.getCleanString(userId + "_name_feedback_text")); + + // feedbackText value changed? + hasChange = !hasChange && submission != null ? valueDiffFromStateAttribute(state, feedbackText, submission.getFeedbackText()):hasChange; + if (feedbackText != null) + { + state.setAttribute(GRADE_SUBMISSION_FEEDBACK_TEXT, feedbackText); + } + + String g = StringUtil.trimToNull(params.getCleanString(GRADE_SUBMISSION_GRADE)); + + if (submission != null) + { + Assignment a = submission.getAssignment(); + typeOfGrade = a.getContent().getTypeOfGrade(); + + if (withGrade) + { + // any change in grade. Do not check for ungraded assignment type + if (!hasChange && typeOfGrade != Assignment.UNGRADED_GRADE_TYPE) + { + if (typeOfGrade == Assignment.SCORE_GRADE_TYPE) + { + hasChange = valueDiffFromStateAttribute(state, scalePointGrade(state, g), submission.getGrade()); + } + else + { + hasChange = valueDiffFromStateAttribute(state, g, submission.getGrade()); + } + } + if (g != null) + { + state.setAttribute(GRADE_SUBMISSION_GRADE, g); + } + else + { + state.removeAttribute(GRADE_SUBMISSION_GRADE); + } + + // for points grading, one have to enter number as the points + String grade = (String) state.getAttribute(GRADE_SUBMISSION_GRADE); + + // do grade validation only for Assignment with Grade tool + if (typeOfGrade == Assignment.SCORE_GRADE_TYPE) + { + if ((grade != null)) + { + // the preview grade process might already scaled up the grade by 10 + if (!((String) state.getAttribute(STATE_MODE)).equals(MODE_INSTRUCTOR_PREVIEW_GRADE_SUBMISSION)) + { + validPointGrade(state, grade); + + if (state.getAttribute(STATE_MESSAGE) == null) + { + int maxGrade = a.getContent().getMaxGradePoint(); + try + { + if (Integer.parseInt(scalePointGrade(state, grade)) > maxGrade) + { + if (state.getAttribute(GRADE_GREATER_THAN_MAX_ALERT) == null) + { + // alert user first when he enters grade bigger than max scale + addAlert(state, rb.getString("grad2")); + state.setAttribute(GRADE_GREATER_THAN_MAX_ALERT, Boolean.TRUE); + } + else + { + // remove the alert once user confirms he wants to give student higher grade + state.removeAttribute(GRADE_GREATER_THAN_MAX_ALERT); + } + } + } + catch (NumberFormatException e) + { + alertInvalidPoint(state, grade); + M_log.warn(this + ":readGradeForm " + e.getMessage()); + } + } + + state.setAttribute(GRADE_SUBMISSION_GRADE, grade); + } + } + } + + // if ungraded and grade type is not "ungraded" type + if ((grade == null || "ungraded".equals(grade)) && (typeOfGrade != Assignment.UNGRADED_GRADE_TYPE) && "release".equals(gradeOption)) + { + addAlert(state, rb.getString("plespethe2")); + } + } + + // allow resubmit number and due time + if (params.getString("allowResToggle") != null && params.getString(AssignmentSubmission.ALLOW_RESUBMIT_NUMBER) != null) + { + // read in allowResubmit params + readAllowResubmitParams(params, state, submission); + } + else + { + state.removeAttribute(AssignmentSubmission.ALLOW_RESUBMIT_CLOSETIME); + state.removeAttribute(AssignmentSubmission.ALLOW_RESUBMIT_NUMBER); + + if (!"read".equals(gradeOption)) + { + resetAllowResubmitParams(state); + } + } + // record whether the resubmission options has been changed or not + hasChange = hasChange || change_resubmit_option(state, submission); + } + + if (state.getAttribute(STATE_MESSAGE) == null) + { + String grade = (String) state.getAttribute(GRADE_SUBMISSION_GRADE); + grade = (typeOfGrade == Assignment.SCORE_GRADE_TYPE)?scalePointGrade(state, grade):grade; + state.setAttribute(GRADE_SUBMISSION_GRADE, grade); + } + } + else + { + // generate alert + addAlert(state, rb.getFormattedMessage("not_allowed_to_grade_submission", new Object[]{submission.getId()})); + } + + return hasChange; + }//readGradeGroupForm + + /** + * Samoo S.L. + * the UserComparator utility class + */ + private class UserComparator implements Comparator + { + public int compare(Object o1, Object o2) { + return ((User)o1).getDisplayName().compareTo(((User)o2).getDisplayName()); + } + } } Index: assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_assignment_groups.vm =================================================================== --- assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_assignment_groups.vm (revision 0) +++ assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_assignment_groups.vm (revision 0) @@ -0,0 +1,99 @@ +## Assignments - Instructor group selection for submission grading + +
+ #if ($allowAddAssignment || ($withGrade && $!allowGradeSubmission)) + ## for user who cannot create assignment nor grade submission, no need to show "Assignment List" link at all since there is really no other toolbar choices + + #end + + + + + + + + #foreach($aGroup in $assignmentGroups) + + + + + + #if ($groupListShowSet.contains($aGroup.Id)) + #foreach($user in $groupUsersMap.get($aGroup.Id)) + + + + + #end + #end + + #end +
+ $tlang.getString("group") + + $tlang.getString("gen.student") +
+   +
+   + + $user.getDisplayName() +
+
Index: assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_group_submissions.vm =================================================================== --- assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_group_submissions.vm (revision 0) +++ assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_group_submissions.vm (revision 0) @@ -0,0 +1,370 @@ +## Assignments - Instructor group selection for submission grading + + +
+ #if ($allowAddAssignment || ($withGrade && $!allowGradeSubmission)) + ## for user who cannot create assignment nor grade submission, no need to show "Assignment List" link at all since there is really no other toolbar choices + + #end + + + ## the form +
+ + + + + + + + ## show or hide assignment instruction and attachment + #if ($assignment_expand_flag) +

+ + $tlang.getString( + $tlang.getString("gen.assinf") +

+ #else +

+ + $tlang.getString( + $tlang.getString("gen.assinf") +

+ #end + + #if ($assignment_expand_flag) + #if ($assignment.getContent().getInstructions().length()>0) +
$validator.escapeHtmlFormattedText($assignment.getContent().getInstructions())
+ #else + #end + ## attachments of assignment +

$tlang.getString("gen.addres2")

+ #set ($size = 0) + #set ($attachments = $assignment.getContent().Attachments) + #set ($props = false) + #foreach ($attachment in $attachments) + #set ($props = $attachment.Properties) + #if ($!props) + #set ($size = $size + 1) + #end + #end + #if ($size == 0) +

$tlang.getString("gen.noatt")

+ #else +
    + #foreach ($attachment in $attachments) + #set ($props = false) + #set ($props = $attachment.Properties) + #if ($!props) +
  • + #if ($props.getBooleanProperty($props.NamePropIsCollection)) + $tlang.getString( + #else + $tlang.getString( + #end + $validator.escapeHtml($props.getPropertyFormatted($props.NamePropDisplayName)) + #if (!$props.getBooleanProperty($props.NamePropIsCollection)) + ($props.getPropertyFormatted($props.NamePropContentLength)) + #end +
  • + #end + #end +
+ #end + #end ## show the assignment content + + ##show user group submissions +

+ $validator.escapeHtml($groupName) +

+ ## for each student show the feedback text and attachments + #foreach ($student in $students) +
+ #set ($submission = 'null') + #set ($submission = $userSubmissions.get($student.getId())) + +

$student.getDisplayName()

+

$tlang.getString("gen.subm")

+ #if ($submissionType == 4) + ## if this is non-electronic submission +

$tlang.getString("nonelec_instruction2")

+ #elseif ($submissionType!=2) + ## if there is a text + #set ($user_name_feedback_text = "") + #set ($value_feedback_text = "") + #if ($submission) + #set ($user_name_feedback_text = "${student.getId()}_name_feedback_text") + #if($submission.getFeedbackText() && $submission.getFeedbackText().trim().length() > 0) + #set ($value_feedback_text = $submission.getFeedbackText()) + #else + #set ($value_feedback_text = $submission.getSubmittedText()) + #end + #end + + #if($submission && ($submission.submitted || !$alertGradeDraft) && $value_feedback_text.trim().length() >0 ) +

$tlang.getString("gradingsub.belisthe")

+
+ + #chef_setupformattedtextarea($user_name_feedback_text) +
+ #else +

$tlang.getString("gradingsub.nosubmittedtext")

+ #end + #end + ## submitted attachment + + #if ($submissionType!=1 && $submissionType!=4) ## do not show attach messages if no attach are allowed... +

$tlang.getString("gen.stuatt")

+ #set ($size = 0) + #if ($submission && ($!submission.submitted || !$alertGradeDraft)) + #set ($props = false) + #foreach ($attachment in $submission.SubmittedAttachments) + #set ($props = $attachment.Properties) + #if ($!props) + #set ($size = $size + 1) + #end + #end + #end + #if ($size == 0) +

$tlang.getString("gen.noattsubmitted")

+ #else +
    + #foreach ($attachment in $submission.SubmittedAttachments) + #set ($props = false) + #set ($props = $attachment.Properties) + #if ($!props) +
  • + #if ($props.getBooleanProperty($props.NamePropIsCollection)) + $tlang.getString( + #else + $tlang.getString( + #end + $validator.escapeHtml($props.getPropertyFormatted($props.NamePropDisplayName)) + #if (!$props.getBooleanProperty($props.NamePropIsCollection)) + ($props.getPropertyFormatted($props.NamePropContentLength)) + #end +
  • + #end + #end +
+ #end + #end +
+ #end + + ##instructor comments +

+ $tlang.getString("gen.instrcomment") +

+

+ $tlang.getString("gradingsub.groupcomment") +

+
+ + #chef_setupformattedtextarea($name_feedback_comment) +
+ + ##grading +#* +*# + #if ($withGrade) +
+ #if ($allowToGrade) + #set ($gradeType = $assignment.getContent().TypeOfGrade) + #if ($gradeType == 1) +

+ + + $tlang.getString("gen.nograd") +

+ #elseif ($gradeType == 2) +

+ + +

+ #elseif ($gradeType == 3) +

+ + ($tlang.getString("grade.max") $assignment.getContent().getMaxGradePointDisplay()) +

+ #elseif ($gradeType == 4) +

+ + +

+ #elseif ($gradeType == 5) +

+ +

+ #end + #else + ## if not allowed to grade, show the current grade instead + +
$!notAllowedToGradeWarning
+ + $!value_grade + #end +
+ #end + #if ($nonElectronic) + ## hidden value for non-electronic submission + + #else + ##show it only for those assignments not of type non-electronic submission + #if($!value_allowResubmitNumber && $submissionType != 4) + #set($resubmitStyle="display:block") + #else + #set($resubmitStyle="display:none") + #end + + +        + + +     + + ## only show date selection when allowed to resubmit +   + #chef_dateselectionwidget($name_ResubmitYear $name_ResubmitMonth $name_ResubmitDay $!value_year_from $!value_year_to $value_ResubmitYear $value_ResubmitMonth $value_ResubmitDay $dateFormat "") + $tlang.getString("gen.at") + + + + + #end + + + +
+ +
Index: assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm =================================================================== --- assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm (revision 123296) +++ assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm (working copy) @@ -371,7 +371,12 @@ #if (!$assignment.draft && $!service.allowGradeSubmission($assignment.getReference()))#if($prevAction) | #end #set ($gradeScale = $assignment.getContent().getTypeOfGrade()) ## show "view submissions" link for ungraded type of assignment - #if ($withGrade && $gradeScale != 1)$!tlang.getString("gen.assign.gra")#else$!tlang.getString("viewsubmissions")#end : $validator.escapeHtml($validator.limit($!assignment.getTitle(), 64))#end + #if ($withGrade && $gradeScale != 1)$!tlang.getString("gen.gra")#else$!tlang.getString("viewsubmissions")#end + ## show "view group submissions" link for ungraded type of assignment Samoo S.L. + #if($prevAction && $assignment.getGroups().size() > 0) | + $!tlang.getString("gen.assign.gra.group") + #end + #end #else #if ($!allowAddAssignment)