Index: assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentSubmission.java =================================================================== --- assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentSubmission.java (revision 109227) +++ assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentSubmission.java (working copy) @@ -62,6 +62,17 @@ public String getAssignmentId(); /** + * Submitter ID is the Sakai Group ID or User ID that created the submission. + * @return The GROUP or USER id who submitted this assignement + */ + public String getSubmitterId(); + /** + * Used to record submission history for group submissions. + * @return The LIST of submission log entries. + */ + public List getSubmissionLog(); + + /** * Access the list of Users who submitted this response to the Assignment. * * @return Array of user objects. Index: assignment-api/api/src/java/org/sakaiproject/assignment/api/Assignment.java =================================================================== --- assignment-api/api/src/java/org/sakaiproject/assignment/api/Assignment.java (revision 109227) +++ assignment-api/api/src/java/org/sakaiproject/assignment/api/Assignment.java (working copy) @@ -118,6 +118,13 @@ public static final String ASSIGNMENT_RELEASEGRADE_NOTIFICATION_EACH = "assignment_releasegrade_notification_each"; /** + * Access if this is a group submission type of this Assignment. + * + * @return The Assignment's AssignmentContent. + */ + public boolean isGroup(); + + /** * Access the AssignmentContent of this Assignment. * * @return The Assignment's AssignmentContent. @@ -153,6 +160,20 @@ public Time getDueTime(); /** + * Access the time at which the assignment is visible; may be null. + * + * @return The Time at which the Assignment is visible, or null if unspecified. + */ + public Time getVisibleTime(); + + /** + * Access the time at which the assignment is visible; (String) + * + * @return The Time at which the Assignment is visible + */ + public String getVisibleTimeString(); + + /** * Access the time at which the assignment is due; (String) * * @return The Time at which the Assignment is due,or "" if unspecified Index: assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java =================================================================== --- assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java (revision 109227) +++ assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java (working copy) @@ -34,6 +34,7 @@ import org.sakaiproject.exception.PermissionException; import org.sakaiproject.user.api.User; import org.w3c.dom.Element; +import org.sakaiproject.site.api.Group; /** *

@@ -688,6 +689,21 @@ public AssignmentSubmission getSubmission(String assignmentId, User person); /** + * Access a User or Group's AssignmentSubmission to a particular Assignment. + * + * @param assignmentId - + * The id of the assignment. + * @param submitterId - + * The string id of the person or group who's Submission you would like. + * @return AssignmentSubmission The user's submission for that Assignment, or null if one does not exist. + * @throws IdUnusedException + * if the assignmentId does not correspond to an existing Assignment. + * @throws PermissionException + * if the current user is not allowed to read this. + */ + public AssignmentSubmission getSubmission(String assignmentReference, String submitterId); + + /** * Access a User's AssignmentSubmission inside a list of AssignmentSubmission object. * * @param - submissions @@ -708,6 +724,11 @@ public List getSubmissions(Assignment assignment); /** + * Return a sorted list of users representing a group. + */ + public List getSortedGroupUsers(Group g); + + /** * Get the number of submissions which has been submitted. * * @param assignmentRef - @@ -815,6 +836,7 @@ */ public boolean canSubmit(String context, Assignment a); + public Collection getSubmitterGroupList(String searchFilterOnly, String allOrOneGroup, String searchString, String aRef, String contextString); /** * get appropriate submitter id list with group choice and site id * @param searchFilterOnly If true, return only those ids that matches the group filter and search criteria Index: assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentSubmissionEdit.java =================================================================== --- assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentSubmissionEdit.java (revision 109227) +++ assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentSubmissionEdit.java (working copy) @@ -60,6 +60,22 @@ public void addSubmitter(User submitter); /** + * String id of User or Group + * + * @param id - + * User or group id of submitter. + */ + public void setSubmitterId(String id); + /** + * String entry for submission log. + * + * @param entry - + * String log entry for group submission + */ + public void addSubmissionLogEntry(String entry); + + + /** * Remove an User from the submitter list * * @param submitter - Index: assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentEdit.java =================================================================== --- assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentEdit.java (revision 109227) +++ assignment-api/api/src/java/org/sakaiproject/assignment/api/AssignmentEdit.java (working copy) @@ -37,6 +37,15 @@ public interface AssignmentEdit extends Assignment, Edit { /** + * Set if this a group submission type of Assignment. + * + * @param boolean - + * is a group submission assignment. + */ + public void setGroup(boolean group); + + + /** * Set the reference of the AssignmentContent of this Assignment. * * @param String - @@ -69,6 +78,14 @@ public void setDueTime(Time dueTime); /** + * Set the time at which the assignment is visible; may be null. + * + * @param visibleTime - + * The Time at which the Assignment is visible. + */ + public void setVisibleTime(Time visibleTime); + + /** * Set the drop dead time after which responses to this assignment are considered late; may be null. * * @param dropDeadTime - Index: assignment-api/api/src/java/org/sakaiproject/assignment/cover/AssignmentService.java =================================================================== --- assignment-api/api/src/java/org/sakaiproject/assignment/cover/AssignmentService.java (revision 109227) +++ assignment-api/api/src/java/org/sakaiproject/assignment/cover/AssignmentService.java (working copy) @@ -25,7 +25,8 @@ import java.util.List; import java.util.Set; import java.util.ArrayList; - +import java.util.Collection; +import org.sakaiproject.site.api.Group; import org.sakaiproject.component.cover.ComponentManager; /** @@ -581,6 +582,17 @@ } public static org.sakaiproject.assignment.api.AssignmentSubmission getSubmission( + java.lang.String param0, java.lang.String param1) + throws org.sakaiproject.exception.IdUnusedException, + org.sakaiproject.exception.PermissionException { + org.sakaiproject.assignment.api.AssignmentService service = getInstance(); + if (service == null) + return null; + + return service.getSubmission(param0, param1); + } + + public static org.sakaiproject.assignment.api.AssignmentSubmission getSubmission( java.util.List param0, org.sakaiproject.user.api.User param1) { org.sakaiproject.assignment.api.AssignmentService service = getInstance(); if (service == null) @@ -751,6 +763,14 @@ return service.getAllowGroupAssignments(); } + public static List getSortedGroupUsers(Group _g) { + org.sakaiproject.assignment.api.AssignmentService service = getInstance(); + if (service == null) + return new java.util.ArrayList(); + + return service.getSortedGroupUsers(_g); + } + public static boolean getAllowGroupAssignmentsInGradebook() { org.sakaiproject.assignment.api.AssignmentService service = getInstance(); if (service == null) @@ -766,7 +786,11 @@ return service.canSubmit(param0, param1); } - + public static Collection getSubmitterGroupList(String param0, String param1, String param2, String param3, String param4) { + org.sakaiproject.assignment.api.AssignmentService service = getInstance(); + if (service == null) return null; + return service.getSubmitterGroupList(param0, param1, param2, param3, param4); + } public static List getSubmitterIdList(String param0, String param1, String param2, String param3, String param4) { org.sakaiproject.assignment.api.AssignmentService service = getInstance(); if (service == null) Index: assignment-bundles/assignment.properties =================================================================== --- assignment-bundles/resources/assignment.properties (revision 109227) +++ assignment-bundles/resources/assignment.properties (working copy) @@ -16,6 +16,10 @@ areyousur_single = Are you sure you want to delete this assignment? +areyousur = Are you sure you want to delete + +assig2 = assignment. + assig3 = Assignment due date should be set after the open date. assig4 = Assignment due date set to be in the past. Please make a correction or click on the original button again to proceed. @@ -29,9 +33,14 @@ cannotfin1 = Can not add the due date to schedule. cannotfin_assignment = Can not find the assignment ''{0}''. - +cannotfin2 = Can not find the assignment cannotfin_assignmentContent = Can not find the assignment content ''{0}''. +cannotfin3 = Can not find the assignment. + +cannotfin4 = Can not find the assignment content. + +cannotfin5 = Can not find the assignment submission. cannotfin_site = Can not find site with id = ''{0}''. cannotfin_submission = Can not find the assignment submission with id = ''{0}''. cannotfin_submission_1 = Can not find the assignment submission for assignment reference =''{0}'' and user id=''{1}''. @@ -54,6 +63,8 @@ delete_assig.delanass = Delete an assignment... delete_assig.delass = Delete assignments... +delete_assig.theass = these assignments? +delete_assig.thiass = this assignment? downall = Download All @@ -102,6 +113,19 @@ gen.gra = Grade gen.gra2 = Grade: gen.grading = Grading +gen.group = Group +group.issubmit = Are submissions for a group? +gen.groupassignment = Group Submission +gen.userassignment = Individual Submission +gen.section.info = Section (do not use for group submissions) +group.submission.not.found = Submission's Group Not Found +group.select.represent = Select the group you are representing. +group.user.multiple.warning = The following users are in more than one group eligible to submit to this assignment: +group.must.member = You must be a member of at least one group to submit! +group.already.submitted = Group has already submitted! +group.user.multiple.error = At least one user is in more than one group. Please see below. +gen.history = History +gen.visible.date = Visible Date gen.checked = Checked gen.commented = Commented gen.regra = Re-grade @@ -176,11 +200,13 @@ gen.status = Status gen.stuatt = Submitted Attachments gen.student = Student +gen.students = Students gen.stunam = Student Name gen.stusub = Student Submissions gen.stuvie = Student View gen.stuvieof = Student view of the assignment -gen.stuwonsee = Students will not see this assignment until the open date. +gen.stucantdo = Students can not save or submit the assignment until the open date. +gen.stuwonsee = Students will not see this assignment until the viewable date. gen.subm = Assignment Submission gen.submission = Submission gen.resubmission = Resubmission @@ -240,6 +266,7 @@ inlinatt = Inline and Attachments +isnotval = is not valid. # months (used in chef_dateselectionwidget macro in VM_chef_library.vm) jan = JAN @@ -373,6 +400,8 @@ stuviewsubm.submitreminder=Don't forget to save or submit feedbackcomment = Feedback Comment +submiss = submission. + # Taggable tag.emptylist = There are no tags to display. tag.tags = Tags @@ -382,6 +411,12 @@ theassiid_hasnotbee = The assignment id ''{0}'' has not been used. +theassi = the assignment + +theassicon = The assignment content is being edited by another user. + +theassiid = The assignment id + theisno = There is no such assignment. theisnostudent = There is no student. @@ -448,6 +483,7 @@ list.itemsper = items... update = Update subasstudent = Submit as Student +submissionsfor = Submissions for alert.globalNavi = If you choose to exit without clicking any action button at the bottom of this page, you will lose your work. Please choose one of these buttons or navigate to your chosen page and abandon your work in this page. viewassign = View Assignment subexampleassign = Submit Example Assignment @@ -685,7 +721,9 @@ allowResubmission.show = Show Settings for Allowing Resubmissions allowResubmission.hide = Hide Settings for Allowing Resubmissions allowResubmission.label = Select User(s) and Allow Resubmission +allowResubmission.groups.label = Select Group(s) and Allow Resubmission allowResubmission.instruction = Select user(s) and apply the resubmission settings. +allowResubmission.groups.instruction = Select group(s) and apply the resubmission settings. allowResubmission.nouser = Please choose at least one user for setting the resubmission choices. ## single file upload Index: assignment-tool/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java =================================================================== --- assignment-tool/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java (revision 109227) +++ assignment-tool/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java (working copy) @@ -192,6 +192,8 @@ private static final String ATTACHMENTS = "Assignment.attachments"; private static final String ATTACHMENTS_FOR = "Assignment.attachments_for"; + /** The property name associated with Groups that are Sections **/ + private static final String GROUP_SECTION_PROPERTY = "sections_category"; /** The content type image lookup service in the State. */ private static final String STATE_CONTENT_TYPE_IMAGE_SERVICE = "Assignment.content_type_image_service"; @@ -425,6 +427,8 @@ // assignment order for default view private static final String NEW_ASSIGNMENT_ORDER = "new_assignment_order"; + private static final String NEW_ASSIGNMENT_GROUP_SUBMIT = "new_assignment_group_submit"; + // open date private static final String NEW_ASSIGNMENT_OPENMONTH = "new_assignment_openmonth"; @@ -438,6 +442,20 @@ private static final String NEW_ASSIGNMENT_OPENAMPM = "new_assignment_openampm"; + // visible date + private static final String NEW_ASSIGNMENT_VISIBLEMONTH = "new_assignment_visiblemonth"; + + private static final String NEW_ASSIGNMENT_VISIBLEDAY = "new_assignment_visibleday"; + + private static final String NEW_ASSIGNMENT_VISIBLEYEAR = "new_assignment_visibleyear"; + + private static final String NEW_ASSIGNMENT_VISIBLEHOUR = "new_assignment_visiblehour"; + + private static final String NEW_ASSIGNMENT_VISIBLEMIN = "new_assignment_visiblemin"; + + private static final String NEW_ASSIGNMENT_VISIBLEAMPM = "new_assignment_visibleampm"; + + // due date private static final String NEW_ASSIGNMENT_DUEMONTH = "new_assignment_duemonth"; @@ -498,6 +516,9 @@ private static final String NEW_ASSIGNMENT_GROUPS = "new_assignment_groups"; + private static final String VIEW_SUBMISSION_GROUP = "view_submission_group"; + private static final String VIEW_SUBMISSION_ORIGINAL_GROUP = "view_submission_original_group"; + private static final String NEW_ASSIGNMENT_PAST_CLOSE_DATE = "new_assignment_past_close_date"; /*************************** assignment model answer attributes *************************/ @@ -874,6 +895,8 @@ } else if (MODE_STUDENT_VIEW_SUBMISSION_CONFIRMATION.equals(mode)) { + context.put("site",s); + // build the context for showing one assignment submission confirmation template = build_student_view_submission_confirmation_context(portlet, context, data, state); } @@ -884,6 +907,8 @@ } else if (MODE_STUDENT_VIEW_GRADE.equals(mode) || MODE_STUDENT_VIEW_GRADE_PRIVATE.equals(mode)) { + context.put("site",s); + // disable auto-updates while leaving the list view justDelivered(state); @@ -926,6 +951,7 @@ } else if (MODE_INSTRUCTOR_GRADE_SUBMISSION.equals(mode)) { + context.put("site",s); if (allowGradeSubmission != null && ((Boolean) allowGradeSubmission).booleanValue()) { // if allowed for grading, disable auto-updates while leaving the list view @@ -950,6 +976,7 @@ } else if (MODE_INSTRUCTOR_VIEW_ASSIGNMENT.equals(mode)) { + context.put("site",s); // disable auto-updates while leaving the list view justDelivered(state); @@ -966,6 +993,7 @@ } else if (MODE_INSTRUCTOR_REPORT_SUBMISSIONS.equals(mode)) { + context.put("site",s); if ( allowGradeSubmission != null && ((Boolean) allowGradeSubmission).booleanValue()) { // if allowed for grading, build the context for the instructor's view of report submissions @@ -990,6 +1018,8 @@ } else if (MODE_INSTRUCTOR_REORDER_ASSIGNMENT.equals(mode)) { + context.put("site",s); + // disable auto-updates while leaving the list view justDelivered(state); @@ -1195,6 +1225,34 @@ } /** + * local function for getting assignment submission object for a group id (or is that submitter id instead of group id) + */ + private AssignmentSubmission getSubmission(String assignmentRef, String group_id, String callingFunctionName, SessionState state) + { + AssignmentSubmission rv = null; + try + { + + rv = AssignmentService.getSubmission(assignmentRef, group_id); + } + catch (IdUnusedException e) + { + M_log.warn(this + ":build_student_view_submission " + e.getMessage() + " " + assignmentRef + " " + group_id); + if (state != null) + addAlert(state, rb.getFormattedMessage("cannotfin_submission_1", new Object[]{assignmentRef, group_id})); + + } + catch (PermissionException e) + { + M_log.warn(this + ":" + callingFunctionName + " " + e.getMessage() + " " + assignmentRef + " " + group_id); + if (state != null) + addAlert(state, rb.getFormattedMessage("youarenot_viewSubmission_1", new Object[]{assignmentRef, group_id})); + } + + return rv; + } + + /** * build the student view of showing an assignment submission */ protected String build_student_view_submission_context(VelocityPortlet portlet, Context context, RunData data, @@ -1204,11 +1262,11 @@ context.put("context", contextString); User user = (User) state.getAttribute(STATE_USER); + M_log.debug(this + " BUILD SUBMISSION FORM WITH USER " + user.getId() + " NAME " + user.getDisplayName()); String currentAssignmentReference = (String) state.getAttribute(VIEW_SUBMISSION_ASSIGNMENT_REFERENCE); + Assignment assignment = getAssignment(currentAssignmentReference, "build_student_view_submission_context", state); AssignmentSubmission s = null; - Assignment assignment = getAssignment(currentAssignmentReference, "build_student_view_submission_context", state); - if (assignment != null) { context.put("assignment", assignment); @@ -1220,7 +1278,12 @@ s = getSubmission(assignment.getReference(), user, "build_student_view_submission_context", state); if (s != null) { + M_log.debug(this + " BUILD SUBMISSION FORM HAS SUBMISSION FOR USER " + s.getSubmitterId() + " NAME " + user.getDisplayName()); context.put("submission", s); + if (assignment.isGroup()) { + context.put("selectedGroup", s.getSubmitterId()); + context.put("originalGroup", s.getSubmitterId()); + } ResourceProperties p = s.getProperties(); if (p.getProperty(ResourceProperties.PROP_SUBMISSION_PREVIOUS_FEEDBACK_TEXT) != null) { @@ -1237,10 +1300,39 @@ context.put("prevFeedbackAttachments", getPrevFeedbackAttachments(p)); } + if (assignment.isGroup()) { + context.put("submitterId", s.getSubmitterId() ); + } + // put the resubmit information into context assignment_resubmission_option_into_context(context, state); } + if (assignment.isGroup()) { + context.put("assignmentService", AssignmentService.getInstance()); + // get current site + Collection groups = null; + Site st = null; + try { + st = SiteService.getSite((String) state.getAttribute(STATE_CONTEXT_STRING)); + context.put("site", st); + groups = getGroupsWithUser(user.getId(), assignment, st); + context.put("group_size", String.valueOf(groups.size())); + context.put("groups", new SortedIterator(groups.iterator(), new AssignmentComparator(state, SORTED_BY_GROUP_TITLE, Boolean.TRUE.toString() ))); + if (state.getAttribute(VIEW_SUBMISSION_GROUP) != null){ + context.put("selectedGroup", (String)state.getAttribute(VIEW_SUBMISSION_GROUP)); + M_log.debug(this + ":buildStudentViewSubmissionContext: VIEW_SUBMISSION_GROUP " + (String)state.getAttribute(VIEW_SUBMISSION_GROUP)); + } + if (state.getAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP) != null){ + context.put("originalGroup", (String)state.getAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP)); + M_log.debug(this + ":buildStudentViewSubmissionContext: VIEW_SUBMISSION_ORIGINAL_GROUP " + (String)state.getAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP)); + } + } + catch (IdUnusedException iue) { + M_log.warn(this + ":buildStudentViewSubmissionContext: Site not found!" + iue.getMessage()); + } + } + // can the student view model answer or not canViewAssignmentIntoContext(context, assignment, s); } @@ -1260,6 +1352,7 @@ context.put("name_submission_honor_pledge_yes", VIEW_SUBMISSION_HONOR_PLEDGE_YES); context.put("value_submission_honor_pledge_yes", state.getAttribute(VIEW_SUBMISSION_HONOR_PLEDGE_YES)); context.put("attachments", state.getAttribute(ATTACHMENTS)); + context.put("userDirectoryService", UserDirectoryService.getInstance()); context.put("contentTypeImageService", state.getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE)); context.put("currentTime", TimeService.newTime()); @@ -1279,6 +1372,29 @@ } // build_student_view_submission_context + // Get groups containing a user for this assignment (remove SECTION groups) + private Collection getGroupsWithUser(String member, Assignment assignment, Site site) { + Collection groups = new ArrayList(); + if (assignment.getAccess().equals(Assignment.AssignmentAccess.SITE)) + { + Iterator _groups = site.getGroupsWithMember(member).iterator(); + while (_groups.hasNext()) { + Group _g = _groups.next(); + if (_g.getMember(member) != null && _g.getProperties().get(GROUP_SECTION_PROPERTY) == null) + groups.add(_g); + } + } else { + Iterator _it = assignment.getGroups().iterator(); + while (_it.hasNext()) { + String _gRef = _it.next(); + Group _g = site.getGroup(_gRef); + if (_g != null && _g.getMember(member) != null && _g.getProperties().get(GROUP_SECTION_PROPERTY) == null) + groups.add(_g); + } + } + return groups; + } + /** * build the student view of showing an assignment submission confirmation */ @@ -1312,6 +1428,7 @@ Assignment currentAssignment = getAssignment(currentAssignmentReference, "build_student_view_submission_confirmation_context", state); if (currentAssignment != null) { + context.put("assignment", currentAssignment); context.put("assignment_title", currentAssignment.getTitle()); // differenciate submission type @@ -1337,6 +1454,7 @@ AssignmentSubmission s = getSubmission(currentAssignmentReference, user, "build_student_view_submission_confirmation_context",state); if (s != null) { + context.put("submission", s); context.put("submitted", Boolean.valueOf(s.getSubmitted())); context.put("submission_id", s.getId()); if (s.getTimeSubmitted() != null) @@ -1672,11 +1790,7 @@ HashSet rv = new HashSet(); for (Iterator iSubmissions=submissions.iterator(); iSubmissions.hasNext();) { - List submitterIds = ((AssignmentSubmission) iSubmissions.next()).getSubmitterIds(); - if (submitterIds != null && submitterIds.size() > 0) - { - rv.add((String) submitterIds.get(0)); - } + rv.add(((AssignmentSubmission) iSubmissions.next()).getSubmitterId()); } return rv; } @@ -1705,14 +1819,21 @@ if (a != null) { context.put("assignment", a); + if (a.isGroup()) { + Collection _dupUsers = usersInMultipleGroups(a); + if (_dupUsers.size() > 0) context.put("multipleGroupUsers", _dupUsers); } } + } // set up context variables setAssignmentFormContext(state, context); context.put("fField", state.getAttribute(NEW_ASSIGNMENT_FOCUS)); + context.put("group_submissions_enabled", Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.group.submission.enabled", false))); + context.put("visible_date_enabled", Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.visible.date.enabled", false))); + String sortedBy = (String) state.getAttribute(SORTED_BY); String sortedAsc = (String) state.getAttribute(SORTED_ASC); context.put("sortedBy", sortedBy); @@ -1737,6 +1856,11 @@ // set open time context variables putTimePropertiesInContext(context, state, "Open", NEW_ASSIGNMENT_OPENMONTH, NEW_ASSIGNMENT_OPENDAY, NEW_ASSIGNMENT_OPENYEAR, NEW_ASSIGNMENT_OPENHOUR, NEW_ASSIGNMENT_OPENMIN, NEW_ASSIGNMENT_OPENAMPM); + // set visible time context variables + if (Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.visible.date.enabled", false))) { + putTimePropertiesInContext(context, state, "Visible", NEW_ASSIGNMENT_VISIBLEMONTH, NEW_ASSIGNMENT_VISIBLEDAY, NEW_ASSIGNMENT_VISIBLEYEAR, NEW_ASSIGNMENT_VISIBLEHOUR, NEW_ASSIGNMENT_VISIBLEMIN, NEW_ASSIGNMENT_VISIBLEAMPM); + } + // set due time context variables putTimePropertiesInContext(context, state, "Due", NEW_ASSIGNMENT_DUEMONTH, NEW_ASSIGNMENT_DUEDAY, NEW_ASSIGNMENT_DUEYEAR, NEW_ASSIGNMENT_DUEHOUR, NEW_ASSIGNMENT_DUEMIN, NEW_ASSIGNMENT_DUEAMPM); @@ -1758,13 +1882,18 @@ context.put("name_CheckAutoAnnounce", ResourceProperties.NEW_ASSIGNMENT_CHECK_AUTO_ANNOUNCE); context.put("name_CheckAddHonorPledge", NEW_ASSIGNMENT_CHECK_ADD_HONOR_PLEDGE); + context.put("name_CheckIsGroupSubmission", NEW_ASSIGNMENT_GROUP_SUBMIT); + String gs = (String) state.getAttribute(NEW_ASSIGNMENT_GROUP_SUBMIT); + if (gs == null) gs = "0"; // set the values Assignment a = null; String assignmentRef = (String) state.getAttribute(EDIT_ASSIGNMENT_ID); if (assignmentRef != null) { a = getAssignment(assignmentRef, "setAssignmentFormContext", state); + gs = a.isGroup() ? "1": "0"; } + context.put("value_CheckIsGroupSubmission", gs); // 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); @@ -1886,6 +2015,17 @@ if (AssignmentService.getAllowGroupAssignments()) { Collection groupsAllowAddAssignment = AssignmentService.getGroupsAllowAddAssignment(contextString); + if (a != null && a.isGroup()) { + List _valid_groups = new ArrayList(); + Iterator _it = groupsAllowAddAssignment.iterator(); + while (_it.hasNext()) { + Group _group = _it.next(); + if (_group.getProperties().get(GROUP_SECTION_PROPERTY) == null) { + _valid_groups.add(_group); + } + } + groupsAllowAddAssignment = _valid_groups; + } if (range == null) { @@ -2153,6 +2293,11 @@ Time openTime = getTimeFromState(state, NEW_ASSIGNMENT_OPENMONTH, NEW_ASSIGNMENT_OPENDAY, NEW_ASSIGNMENT_OPENYEAR, NEW_ASSIGNMENT_OPENHOUR, NEW_ASSIGNMENT_OPENMIN, NEW_ASSIGNMENT_OPENAMPM); context.put("value_OpenDate", openTime); + if (Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.visible.date.enabled", false))) { + Time visibleTime = getTimeFromState(state, NEW_ASSIGNMENT_VISIBLEMONTH, NEW_ASSIGNMENT_VISIBLEDAY, NEW_ASSIGNMENT_VISIBLEYEAR, NEW_ASSIGNMENT_VISIBLEHOUR, NEW_ASSIGNMENT_VISIBLEMIN, NEW_ASSIGNMENT_VISIBLEAMPM); + context.put("value_VisibleDate", visibleTime); + } + // due time Time dueTime = getTimeFromState(state, NEW_ASSIGNMENT_DUEMONTH, NEW_ASSIGNMENT_DUEDAY, NEW_ASSIGNMENT_DUEYEAR, NEW_ASSIGNMENT_DUEHOUR, NEW_ASSIGNMENT_DUEMIN, NEW_ASSIGNMENT_DUEAMPM); context.put("value_DueDate", dueTime); @@ -2391,12 +2536,12 @@ context.put("alertGradeDraft", Boolean.valueOf(addGradeDraftAlert)); // for the navigation purpose - List userSubmissions = state.getAttribute(USER_SUBMISSIONS) != null ? (List) state.getAttribute(USER_SUBMISSIONS):null; + List userSubmissions = state.getAttribute(USER_SUBMISSIONS) != null ? (List) state.getAttribute(USER_SUBMISSIONS):null; if (userSubmissions != null) { for (int i = 0; i < userSubmissions.size(); i++) { - if (((UserSubmission) userSubmissions.get(i)).getSubmission().getId().equals(submissionId)) + if (((SubmitterSubmission) userSubmissions.get(i)).getSubmission().getId().equals(submissionId)) { boolean goPT = false; boolean goNT = false; @@ -2414,13 +2559,13 @@ if (i>0) { // retrieve the previous submission id - context.put("prevSubmissionId", ((UserSubmission) userSubmissions.get(i-1)).getSubmission().getReference()); + context.put("prevSubmissionId", ((SubmitterSubmission) userSubmissions.get(i-1)).getSubmission().getReference()); } if (i < userSubmissions.size() - 1) { // retrieve the next submission id - context.put("nextSubmissionId", ((UserSubmission) userSubmissions.get(i+1)).getSubmission().getReference()); + context.put("nextSubmissionId", ((SubmitterSubmission) userSubmissions.get(i+1)).getSubmission().getReference()); } } } @@ -2529,6 +2674,8 @@ */ private void putTimePropertiesInState(SessionState state, Time timeValue, String month, String day, String year, String hour, String min, String ampm) { + + try { TimeBreakdown bTime = timeValue.breakdownLocal(); state.setAttribute(month, Integer.valueOf(bTime.getMonth())); state.setAttribute(day, Integer.valueOf(bTime.getDay())); @@ -2549,6 +2696,7 @@ } state.setAttribute(hour, Integer.valueOf((bHour > 12) ? bHour - 12 : bHour)); state.setAttribute(min, Integer.valueOf(bTime.getMin())); + } catch (NullPointerException _npe) { /* TODO empty exception block */ } } /** @@ -2665,6 +2813,7 @@ context.put("sort_submitGrade", SORTED_GRADE_SUBMISSION_BY_GRADE); context.put("sort_submitReleased", SORTED_GRADE_SUBMISSION_BY_RELEASED); context.put("sort_submitReview", SORTED_GRADE_SUBMISSION_CONTENTREVIEW); + context.put("userDirectoryService", UserDirectoryService.getInstance()); String assignmentRef = (String) state.getAttribute(EXPORT_ASSIGNMENT_REF); Assignment assignment = getAssignment(assignmentRef, "build_instructor_grade_assignment_context", state); @@ -2723,7 +2872,7 @@ } } - List userSubmissions = prepPage(state); + List userSubmissions = prepPage(state); state.setAttribute(USER_SUBMISSIONS, userSubmissions); context.put("userSubmissions", state.getAttribute(USER_SUBMISSIONS)); @@ -2945,18 +3094,6 @@ String sortedAsc = (String) state.getAttribute(SORTED_ASC); context.put("sortedBy", sortedBy); context.put("sortedAsc", sortedAsc); - - // put site object into context - try - { - // get current site - Site site = SiteService.getSite((String) state.getAttribute(STATE_CONTEXT_STRING)); - context.put("site", site); - } - catch (Exception ignore) - { - M_log.warn(this + ":build_instructor_reorder_assignment_context " + ignore.getMessage()); - } context.put("contentTypeImageService", state.getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE)); context.put("userDirectoryService", UserDirectoryService.getInstance()); @@ -3053,13 +3190,14 @@ context.put("sortedBy", (String) state.getAttribute(SORTED_SUBMISSION_BY)); context.put("sortedAsc", (String) state.getAttribute(SORTED_SUBMISSION_ASC)); - context.put("sortedBy_lastName", SORTED_SUBMISSION_BY_LASTNAME); - context.put("sortedBy_submitTime", SORTED_SUBMISSION_BY_SUBMIT_TIME); - context.put("sortedBy_grade", SORTED_SUBMISSION_BY_GRADE); - context.put("sortedBy_status", SORTED_SUBMISSION_BY_STATUS); - context.put("sortedBy_released", SORTED_SUBMISSION_BY_RELEASED); - context.put("sortedBy_assignment", SORTED_SUBMISSION_BY_ASSIGNMENT); - context.put("sortedBy_maxGrade", SORTED_SUBMISSION_BY_MAX_GRADE); + + context.put("sortedBy_lastName", SORTED_GRADE_SUBMISSION_BY_LASTNAME); + context.put("sortedBy_submitTime", SORTED_GRADE_SUBMISSION_BY_SUBMIT_TIME); + context.put("sortedBy_grade", SORTED_GRADE_SUBMISSION_BY_GRADE); + context.put("sortedBy_status", SORTED_GRADE_SUBMISSION_BY_STATUS); + context.put("sortedBy_released", SORTED_GRADE_SUBMISSION_BY_RELEASED); + //context.put("sortedBy_assignment", SORTED_GRADE_SUBMISSION_BY_ASSIGNMENT); + //context.put("sortedBy_maxGrade", SORTED_GRADE_SUBMISSION_BY_MAX_GRADE); add2ndToolbarFields(data, context); @@ -3284,10 +3422,10 @@ if (aSubmission.getGradeReleased()) { User[] submitters = aSubmission.getSubmitters(); - if (submitters != null && submitters.length > 0) { - String submitterId = submitters[0].getId(); - String gradeString = StringUtils.trimToNull(aSubmission.getGrade(false)); + String gradeString = StringUtil.trimToNull(aSubmission.getGrade(false)); String grade = gradeString != null ? displayGrade(state,gradeString) : null; + for (int i=0; submitters != null && i < submitters.length; i++) { + String submitterId = submitters[i].getId(); m.put(submitterId, grade); } } @@ -3330,28 +3468,27 @@ if (aSubmission != null) { User[] submitters = aSubmission.getSubmitters(); - String gradeString = StringUtils.trimToNull(displayGrade(state, aSubmission.getGrade(false))); - if (submitters != null && submitters.length > 0) - { + String gradeString = displayGrade(state, StringUtil.trimToNull(aSubmission.getGrade(false))); + for (int i=0; submitters != null && i < submitters.length; i++) { if (associateGradebookAssignment != null) { if (gExternal.isExternalAssignmentDefined(gradebookUid, associateGradebookAssignment)) { // the associated assignment is externally maintained - gExternal.updateExternalAssessmentScore(gradebookUid, associateGradebookAssignment, submitters[0].getId(), - (gradeString != null && aSubmission.getGradeReleased()) ? gradeString : null); + gExternal.updateExternalAssessmentScore(gradebookUid, associateGradebookAssignment, submitters[i].getId(), + (gradeString != null && aSubmission.getGradeReleased()) ? gradeString : ""); } else if (g.isAssignmentDefined(gradebookUid, associateGradebookAssignment)) { // the associated assignment is internal one, update records - g.setAssignmentScoreString(gradebookUid, associateGradebookAssignment, submitters[0].getId(), - gradeString != null ? gradeString : "0", ""); + g.setAssignmentScoreString(gradebookUid, associateGradebookAssignment, submitters[i].getId(), + (gradeString != null && aSubmission.getGradeReleased()) ? gradeString : "", ""); } } else { - gExternal.updateExternalAssessmentScore(gradebookUid, assignmentRef, submitters[0].getId(), - (gradeString != null && aSubmission.getGradeReleased()) ? gradeString : null); + gExternal.updateExternalAssessmentScore(gradebookUid, assignmentRef, submitters[i].getId(), + (gradeString != null && aSubmission.getGradeReleased()) ? gradeString : ""); } } } @@ -3370,16 +3507,15 @@ { AssignmentSubmission aSubmission = (AssignmentSubmission) submissions.next(); User[] submitters = aSubmission.getSubmitters(); - if (submitters != null && submitters.length > 0) - { + for (int i=0; submitters != null && i < submitters.length; i++) { if (isExternalAssociateAssignmentDefined) { // if the old associated assignment is an external maintained one - gExternal.updateExternalAssessmentScore(gradebookUid, associateGradebookAssignment, submitters[0].getId(), null); + gExternal.updateExternalAssessmentScore(gradebookUid, associateGradebookAssignment, submitters[i].getId(), null); } else if (isAssignmentDefined) { - g.setAssignmentScoreString(gradebookUid, associateGradebookAssignment, submitters[0].getId(), "0", assignmentToolTitle); + g.setAssignmentScoreString(gradebookUid, associateGradebookAssignment, submitters[i].getId(), "0", assignmentToolTitle); } } } @@ -3391,17 +3527,17 @@ if (aSubmission != null) { User[] submitters = aSubmission.getSubmitters(); - if (submitters != null && submitters.length > 0) - { + for (int i=0; submitters != null && i < submitters.length; i++) { + if (isExternalAssociateAssignmentDefined) { // external assignment - gExternal.updateExternalAssessmentScore(gradebookUid, assignmentRef, submitters[0].getId(), null); + gExternal.updateExternalAssessmentScore(gradebookUid, assignmentRef, submitters[i].getId(), null); } else if (isAssignmentDefined) { // gb assignment - g.setAssignmentScoreString(gradebookUid, associateGradebookAssignment, submitters[0].getId(), "0", ""); + g.setAssignmentScoreString(gradebookUid, associateGradebookAssignment, submitters[i].getId(), "0", ""); } } } @@ -3507,7 +3643,7 @@ String option = params.getString("option"); if ("changeView".equals(option)) { - state.setAttribute(VIEW_SUBMISSION_LIST_OPTION, params.getString("view")); + doChange_submission_list_option(data); } else if ("search".equals(option)) { @@ -3536,6 +3672,18 @@ } // doView_submission_list_option /** + * Action is to view the content of one specific assignment submission + */ + public void doChange_submission_list_option(RunData data) + { + SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + ParameterParser params = data.getParameters(); + String view = params.getString("view"); + state.setAttribute(VIEW_SUBMISSION_LIST_OPTION, view); + + } // doView_submission_list_option + + /** * Preview of the submission */ public void doPreview_submission(RunData data) @@ -3547,6 +3695,8 @@ state.setAttribute(PREVIEW_SUBMISSION_ASSIGNMENT_REFERENCE, aReference); Assignment a = getAssignment(aReference, "doPreview_submission", state); + saveSubmitInputs(state, params); + // retrieve the submission text (as formatted text) boolean checkForFormattingErrors = true; // the student is submitting something - so check for errors String text = processFormattedTextFromBrowser(state, params.getCleanString(VIEW_SUBMISSION_TEXT), checkForFormattingErrors); @@ -4105,6 +4255,49 @@ } User u = (User) state.getAttribute(STATE_USER); + String group_id = null; + String original_group_id = null; + + if (a.isGroup()) { + + original_group_id = + (params.getString("originalGroup") == null || params.getString("originalGroup").trim().length() == 0) ? null: params.getString("originalGroup"); ; + + if (original_group_id != null) { + state.setAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP, original_group_id); + } else { + if (state.getAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP) != null) + original_group_id = (String)state.getAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP); + else + state.setAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP, null); + } + + String[] groupChoice = params.getStrings("selectedGroups"); + + if (groupChoice != null && groupChoice.length != 0) + { + if (groupChoice.length > 1) { + state.setAttribute(VIEW_SUBMISSION_GROUP, null); + addAlert(state, rb.getString("java.alert.youchoosegroup")); + } else { + group_id = groupChoice[0]; + state.setAttribute(VIEW_SUBMISSION_GROUP, groupChoice[0]); + } + } + else + { + // get the submitted group id + if (state.getAttribute(VIEW_SUBMISSION_GROUP) != null) { + group_id = (String)state.getAttribute(VIEW_SUBMISSION_GROUP); + } else { + state.setAttribute(VIEW_SUBMISSION_GROUP, null); + addAlert(state, rb.getString("java.alert.youchoosegroup")); + } + } + + + } + String assignmentId = ""; if (state.getAttribute(STATE_MESSAGE) == null) { @@ -4125,7 +4318,16 @@ if ((state.getAttribute(STATE_MESSAGE) == null) && (a != null)) { - AssignmentSubmission submission = getSubmission(a.getReference(), u, "post_save_submission", state); + AssignmentSubmission submission = null; + if (a.isGroup()) { + submission = getSubmission(a.getReference(), + (original_group_id == null ? group_id: original_group_id), + "post_save_submission", + state); + } else { + submission = getSubmission(a.getReference(), u, "post_save_submission", state); + } + if (submission != null) { // the submission already exists, change the text and honor pledge value, post it @@ -4143,6 +4344,17 @@ isPreviousSubmissionTime = false; } + if (a.isGroup()) { + if (original_group_id != null && !original_group_id.equals(group_id)) { + // changing group id so we need to check if a submission has already been made for that group + AssignmentSubmission submissioncheck = getSubmission(a.getReference(), group_id, "post_save_submission",state); + if (submissioncheck != null) { + addAlert(state, rb.getString("group.already.submitted")); + M_log.warn(this + ":post_save_submission " + group_id + " has already submitted " + submissioncheck.getId() + "!"); + } + } + sEdit.setSubmitterId(group_id); + } sEdit.setSubmittedText(text); sEdit.setHonorPledgeFlag(Boolean.valueOf(honorPledgeYes).booleanValue()); sEdit.setTimeSubmitted(TimeService.newTime()); @@ -4276,6 +4488,8 @@ } } + sEdit.addSubmissionLogEntry(new java.util.Date() + " " + u.getDisplayName() + " (" + u.getEid() + ") " + (post ? "submitted" : "saved draft")); + AssignmentService.commitEdit(sEdit); } @@ -4285,7 +4499,13 @@ // new submission try { - AssignmentSubmissionEdit edit = AssignmentService.addSubmission(contextString, assignmentId, SessionManager.getCurrentSessionUserId()); + // if assignment is a group submission... send group id and not user id + M_log.debug(this + " NEW SUBMISSION IS GROUP: " + a.isGroup() + " GROUP:" + group_id); + AssignmentSubmissionEdit edit = + a.isGroup() ? + AssignmentService.addSubmission(contextString, assignmentId, group_id): + AssignmentService.addSubmission(contextString, assignmentId, SessionManager.getCurrentSessionUserId()); + edit.setSubmittedText(text); edit.setHonorPledgeFlag(Boolean.valueOf(honorPledgeYes).booleanValue()); edit.setTimeSubmitted(TimeService.newTime()); @@ -4311,6 +4531,8 @@ // set the resubmission properties setResubmissionProperties(a, edit); + edit.addSubmissionLogEntry(new java.util.Date() + " " + u.getDisplayName() + " (" + u.getEid() + ") " + (post ? "submitted" : "saved draft")); + AssignmentService.commitEdit(edit); } catch (PermissionException e) @@ -4461,6 +4683,11 @@ String order = params.getString(NEW_ASSIGNMENT_ORDER); state.setAttribute(NEW_ASSIGNMENT_ORDER, order); + state.setAttribute( + NEW_ASSIGNMENT_GROUP_SUBMIT, + (params.getString(NEW_ASSIGNMENT_GROUP_SUBMIT) == null ? "0": "1") + ); + if (title == null || title.length() == 0) { // empty assignment title @@ -4475,6 +4702,11 @@ // open time Time openTime = putTimeInputInState(params, state, NEW_ASSIGNMENT_OPENMONTH, NEW_ASSIGNMENT_OPENDAY, NEW_ASSIGNMENT_OPENYEAR, NEW_ASSIGNMENT_OPENHOUR, NEW_ASSIGNMENT_OPENMIN, NEW_ASSIGNMENT_OPENAMPM, "newassig.opedat"); + // visible time + if (Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.visible.date.enabled", false))) { + Time visibleTime = putTimeInputInState(params, state, NEW_ASSIGNMENT_VISIBLEMONTH, NEW_ASSIGNMENT_VISIBLEDAY, NEW_ASSIGNMENT_VISIBLEYEAR, NEW_ASSIGNMENT_VISIBLEHOUR, NEW_ASSIGNMENT_VISIBLEMIN, NEW_ASSIGNMENT_VISIBLEAMPM, "newassig.visdat"); + } + // due time Time dueTime = putTimeInputInState(params, state, NEW_ASSIGNMENT_DUEMONTH, NEW_ASSIGNMENT_DUEDAY, NEW_ASSIGNMENT_DUEYEAR, NEW_ASSIGNMENT_DUEHOUR, NEW_ASSIGNMENT_DUEMIN, NEW_ASSIGNMENT_DUEAMPM, "gen.duedat"); // show alert message when due date is in past. Remove it after user confirms the choice. @@ -4685,6 +4917,20 @@ state.removeAttribute(NEW_ASSIGNMENT_GROUPS); } + // check groups for duplicate members here + if ("1".equals(params.getString(NEW_ASSIGNMENT_GROUP_SUBMIT))) { + Collection _dupUsers = usersInMultipleGroups(state, "groups".equals(range),("groups".equals(range) ? data.getParameters().getStrings("selectedGroups") : null)); + if (_dupUsers.size() > 0) { + StringBuilder _sb = new StringBuilder(rb.getString("group.user.multiple.warning") + " "); + Iterator _it = _dupUsers.iterator(); + if (_it.hasNext()) _sb.append(_it.next()); + while (_it.hasNext()) + _sb.append(", " + _it.next()); + addAlert(state, _sb.toString()); + M_log.warn(this + ":post_save_assignment at least one user in multiple groups."); + } + } + // allow resubmission numbers if (params.getString("allowResToggle") != null && params.getString(AssignmentSubmission.ALLOW_RESUBMIT_NUMBER) != null) { @@ -5276,6 +5522,12 @@ // open time Time openTime = getTimeFromState(state, NEW_ASSIGNMENT_OPENMONTH, NEW_ASSIGNMENT_OPENDAY, NEW_ASSIGNMENT_OPENYEAR, NEW_ASSIGNMENT_OPENHOUR, NEW_ASSIGNMENT_OPENMIN, NEW_ASSIGNMENT_OPENAMPM); + // visible time + Time visibleTime = null; + if (Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.visible.date.enabled", false))) { + visibleTime = getTimeFromState(state, NEW_ASSIGNMENT_VISIBLEMONTH, NEW_ASSIGNMENT_VISIBLEDAY, NEW_ASSIGNMENT_VISIBLEYEAR, NEW_ASSIGNMENT_VISIBLEHOUR, NEW_ASSIGNMENT_VISIBLEMIN, NEW_ASSIGNMENT_VISIBLEAMPM); + } + // due time Time dueTime = getTimeFromState(state, NEW_ASSIGNMENT_DUEMONTH, NEW_ASSIGNMENT_DUEDAY, NEW_ASSIGNMENT_DUEYEAR, NEW_ASSIGNMENT_DUEHOUR, NEW_ASSIGNMENT_DUEMIN, NEW_ASSIGNMENT_DUEAMPM); @@ -5294,6 +5546,8 @@ int gradeType = ((Integer) state.getAttribute(NEW_ASSIGNMENT_GRADE_TYPE)).intValue(); + boolean isGroupSubmit = "1".equals((String)state.getAttribute(NEW_ASSIGNMENT_GROUP_SUBMIT)); + String gradePoints = (String) state.getAttribute(NEW_ASSIGNMENT_GRADE_POINTS); String description = (String) state.getAttribute(NEW_ASSIGNMENT_DESCRIPTION); @@ -5341,7 +5595,8 @@ for (Iterator iGroups = groupChoice.iterator(); iGroups.hasNext();) { String groupId = (String) iGroups.next(); - groups.add(site.getGroup(groupId)); + Group _aGroup = site.getGroup(groupId); + if (_aGroup != null) groups.add(_aGroup); } } } @@ -5358,6 +5613,8 @@ Time oldOpenTime = a.getOpenTime(); // old due time Time oldDueTime = a.getDueTime(); + // old visible time + Time oldVisibleTime = a.getVisibleTime(); // commit the changes to AssignmentContent object commitAssignmentContentEdit(state, ac, title, submissionType,useReviewService,allowStudentViewReport, gradeType, gradePoints, description, checkAddHonorPledge, attachments); @@ -5379,9 +5636,9 @@ aPropertiesEdit.addProperty(Assignment.ASSIGNMENT_RELEASEGRADE_NOTIFICATION_VALUE, (String) state.getAttribute(Assignment.ASSIGNMENT_RELEASEGRADE_NOTIFICATION_VALUE)); } - // comment the changes to Assignment object - commitAssignmentEdit(state, post, ac, a, title, openTime, dueTime, closeTime, enableCloseDate, section, range, groups); + commitAssignmentEdit(state, post, ac, a, title, visibleTime, openTime, dueTime, closeTime, enableCloseDate, section, range, groups, isGroupSubmit); + if (post) { // we need to update the submission @@ -5781,11 +6038,9 @@ for (Iterator iSubmissions=submissions.iterator(); iSubmissions.hasNext() && submissionRef == null;) { AssignmentSubmission submission = (AssignmentSubmission) iSubmissions.next(); - List submitterIds = submission.getSubmitterIds(); - if (submitterIds != null && submitterIds.size() > 0 && userId.equals((String) submitterIds.get(0))) - { - submissionRef = submission.getReference(); - } + if (userId.equals(submission.getSubmitterId())) { + submissionRef = submission.getReference(); + } } if (submissionRef != null) { @@ -5806,9 +6061,8 @@ } } + private void initIntegrateWithGradebook(SessionState state, String siteId, String aOldTitle, String oAssociateGradebookAssignment, AssignmentEdit a, String title, Time dueTime, int gradeType, String gradePoints, String addtoGradebook, String associateGradebookAssignment, String range, long category) { - private void initIntegrateWithGradebook(SessionState state, String siteId, String aOldTitle, String oAssociateGradebookAssignment, AssignmentEdit a, String title, Time dueTime, int gradeType, String gradePoints, String addtoGradebook, String associateGradebookAssignment, String range, long category) { - GradebookExternalAssessmentService gExternal = (GradebookExternalAssessmentService) ComponentManager.get("org.sakaiproject.service.gradebook.GradebookExternalAssessmentService"); String context = (String) state.getAttribute(STATE_CONTEXT_STRING); @@ -6175,7 +6429,8 @@ for (Iterator iGroupRefs = groupRefs.iterator(); iGroupRefs.hasNext();) { String groupRef = (String) iGroupRefs.next(); - eGroups.add(site.getGroup(groupRef)); + Group _aGroup = site.getGroup(groupRef); + if (_aGroup != null) eGroups.add(_aGroup); } } e = c.addEvent(/* TimeRange */TimeService.newTimeRange(dueTime.getTime(), /* 0 duration */0 * 60 * 1000), @@ -6223,15 +6478,16 @@ } } - private void commitAssignmentEdit(SessionState state, boolean post, AssignmentContentEdit ac, AssignmentEdit a, String title, Time openTime, Time dueTime, Time closeTime, boolean enableCloseDate, String s, String range, Collection groups) + private void commitAssignmentEdit(SessionState state, boolean post, AssignmentContentEdit ac, AssignmentEdit a, String title, Time visibleTime, Time openTime, Time dueTime, Time closeTime, boolean enableCloseDate, String s, String range, Collection groups, boolean isGroupSubmit) { a.setTitle(title); a.setContent(ac); a.setContext((String) state.getAttribute(STATE_CONTEXT_STRING)); a.setSection(s); + a.setVisibleTime(visibleTime); a.setOpenTime(openTime); a.setDueTime(dueTime); - // set the drop dead date as the due date + a.setGroup(isGroupSubmit); a.setDropDeadTime(dueTime); if (enableCloseDate) { @@ -6272,7 +6528,15 @@ // commit assignment first AssignmentService.commitEdit(a); } + + if (a.isGroup()) { + Collection _dupUsers = usersInMultipleGroups(a); + if (_dupUsers.size() > 0) { + addAlert(state, rb.getString("group.user.multiple.error")); + M_log.warn(this + ":post_save_assignment at least one user in multiple groups."); } + } + } private void editAssignmentProperties(AssignmentEdit a, String checkAddDueTime, String checkAutoAnnounce, String addtoGradebook, String associateGradebookAssignment, String allowResubmitNumber, ResourcePropertiesEdit aPropertiesEdit, boolean post, Time closeTime) { @@ -6653,6 +6917,10 @@ state.setAttribute(NEW_ASSIGNMENT_TITLE, a.getTitle()); state.setAttribute(NEW_ASSIGNMENT_ORDER, a.getPosition_order()); + if (Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.visible.date.enabled", false))) { + putTimePropertiesInState(state, a.getVisibleTime(), NEW_ASSIGNMENT_VISIBLEMONTH, NEW_ASSIGNMENT_VISIBLEDAY, NEW_ASSIGNMENT_VISIBLEYEAR, NEW_ASSIGNMENT_VISIBLEHOUR, NEW_ASSIGNMENT_VISIBLEMIN, NEW_ASSIGNMENT_VISIBLEAMPM); + } + putTimePropertiesInState(state, a.getOpenTime(), NEW_ASSIGNMENT_OPENMONTH, NEW_ASSIGNMENT_OPENDAY, NEW_ASSIGNMENT_OPENYEAR, NEW_ASSIGNMENT_OPENHOUR, NEW_ASSIGNMENT_OPENMIN, NEW_ASSIGNMENT_OPENAMPM); // generate alert when editing an assignment past open date if (a.getOpenTime().before(TimeService.newTime())) @@ -6738,6 +7006,8 @@ state.setAttribute(NEW_ASSIGNMENT_GROUPS, a.getGroups()); + state.setAttribute(NEW_ASSIGNMENT_GROUP_SUBMIT, a.isGroup() ? "1": "0"); + // get all supplement item info into state setAssignmentSupplementItemInState(state, a); @@ -7007,13 +7277,15 @@ } catch (Exception eee) { + // Trapping for InUseException... go ahead and remove them. + if (!(eee instanceof InUseException)) { addAlert(state, rb.getFormattedMessage("youarenot_removeSubmission", new Object[]{s.getReference()})); - M_log.warn(this + ":deleteAssignmentObjects " + eee.getMessage() + " " + s.getReference()); } } } } + } AssignmentContent aContent = aEdit.getContent(); if (aContent != null) @@ -7901,6 +8174,51 @@ { state.setAttribute(VIEW_SUBMISSION_HONOR_PLEDGE_YES, "true"); } + + String assignmentRef = (String) state.getAttribute(VIEW_SUBMISSION_ASSIGNMENT_REFERENCE); + try + { + Assignment assignment = AssignmentService.getAssignment(assignmentRef); + if (assignment.isGroup()) + { + String[] groupChoice = params.getStrings("selectedGroups"); + if (groupChoice != null && groupChoice.length != 0) + { + if (groupChoice.length > 1) { + state.setAttribute(VIEW_SUBMISSION_GROUP, null); + addAlert(state, rb.getString("java.alert.youchoosegroup")); + } else { + state.setAttribute(VIEW_SUBMISSION_GROUP, groupChoice[0]); + } + } + else + { + state.setAttribute(VIEW_SUBMISSION_GROUP, null); + addAlert(state, rb.getString("java.alert.youchoosegroup")); + } + String original_group_id = + params.getString("originalGroup") == null || params.getString("originalGroup").trim().length() == 0 ? null: params.getString("originalGroup"); ; + + if (original_group_id != null) { + state.setAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP, original_group_id); + } else { + state.setAttribute(VIEW_SUBMISSION_ORIGINAL_GROUP, null); + } + + } + + } + catch (PermissionException p) { + M_log.debug(this + " :saveSubmitInputs permission error getting assignment. "); + } + catch ( IdUnusedException e ) + { + } + + + + + } /** @@ -8510,6 +8828,16 @@ int day = tB.getDay(); int year = tB.getYear(); + // set the visible time to be 12:00 PM + if (Boolean.valueOf(ServerConfigurationService.getBoolean("assignment.visible.date.enabled", false))) { + state.setAttribute(NEW_ASSIGNMENT_VISIBLEMONTH, Integer.valueOf(month)); + state.setAttribute(NEW_ASSIGNMENT_VISIBLEDAY, Integer.valueOf(day)); + state.setAttribute(NEW_ASSIGNMENT_VISIBLEYEAR, Integer.valueOf(year)); + state.setAttribute(NEW_ASSIGNMENT_VISIBLEHOUR, Integer.valueOf(12)); + state.setAttribute(NEW_ASSIGNMENT_VISIBLEMIN, Integer.valueOf(0)); + state.setAttribute(NEW_ASSIGNMENT_VISIBLEAMPM, "PM"); + } + // set the open time to be 12:00 PM state.setAttribute(NEW_ASSIGNMENT_OPENMONTH, Integer.valueOf(month)); state.setAttribute(NEW_ASSIGNMENT_OPENDAY, Integer.valueOf(day)); @@ -8677,6 +9005,7 @@ state.removeAttribute(NEW_ASSIGNMENT_ATTACHMENT); state.removeAttribute(NEW_ASSIGNMENT_FOCUS); state.removeAttribute(NEW_ASSIGNMENT_DESCRIPTION_EMPTY); + state.removeAttribute(NEW_ASSIGNMENT_GROUP_SUBMIT); // reset the global navigaion alert flag if (state.getAttribute(ALERT_GLOBAL_NAVIGATION) != null) @@ -9028,9 +9357,9 @@ } /** - * the UserSubmission clas + * the SubmitterSubmission clas */ - public class UserSubmission + public class SubmitterSubmission { /** * the User object @@ -9038,16 +9367,27 @@ User m_user = null; /** + * the Group object + */ + Group m_group = null; + + /** * the AssignmentSubmission object */ AssignmentSubmission m_submission = null; - public UserSubmission(User u, AssignmentSubmission s) + public SubmitterSubmission(User u, AssignmentSubmission s) { m_user = u; m_submission = s; } + public SubmitterSubmission(Group g, AssignmentSubmission s) + { + m_group = g; + m_submission = s; + } + /** * Returns the AssignmentSubmission object */ @@ -9063,6 +9403,13 @@ { return m_user; } + public Group getGroup() + { + return m_group; + } + public void setGroup(Group _group) { + m_group = _group; + } } /** @@ -9150,7 +9497,9 @@ for (Iterator k = a.getGroups().iterator(); k.hasNext();) { // announcement by group - rv = rv.concat(site.getGroup((String) k.next()).getTitle()); + Group _aGroup = site.getGroup((String) k.next()); + if (_aGroup != null) + rv = rv.concat(_aGroup.getTitle()); } } catch (Exception ignore) @@ -9425,9 +9774,9 @@ /** ***************** for sorting submissions in instructor grade assignment view ************* */ else if(m_criteria.equals(SORTED_GRADE_SUBMISSION_CONTENTREVIEW)) { - UserSubmission u1 = (UserSubmission) o1; - UserSubmission u2 = (UserSubmission) o2; - if (u1 == null || u2 == null || u1.getUser() == null || u2.getUser() == null ) + SubmitterSubmission u1 = (SubmitterSubmission) o1; + SubmitterSubmission u2 = (SubmitterSubmission) o2; + if (u1 == null || u2 == null ) { result = 1; } @@ -9457,25 +9806,25 @@ else if (m_criteria.equals(SORTED_GRADE_SUBMISSION_BY_LASTNAME)) { // sorted by the submitters sort name - UserSubmission u1 = (UserSubmission) o1; - UserSubmission u2 = (UserSubmission) o2; + SubmitterSubmission u1 = (SubmitterSubmission) o1; + SubmitterSubmission u2 = (SubmitterSubmission) o2; - if (u1 == null || u2 == null || u1.getUser() == null || u2.getUser() == null ) + if (u1 == null || u2 == null || (u1.getUser() == null && u1.getGroup() == null) || (u2.getUser() == null && u2.getGroup() == null) ) { result = 1; } else { - String lName1 = u1.getUser().getSortName(); - String lName2 = u2.getUser().getSortName(); + String lName1 = u1.getUser() == null ? u1.getGroup().getTitle(): u1.getUser().getSortName(); + String lName2 = u2.getUser() == null ? u2.getGroup().getTitle(): u2.getUser().getSortName(); result = compareString(lName1, lName2); } } else if (m_criteria.equals(SORTED_GRADE_SUBMISSION_BY_SUBMIT_TIME)) { // sorted by submission time - UserSubmission u1 = (UserSubmission) o1; - UserSubmission u2 = (UserSubmission) o2; + SubmitterSubmission u1 = (SubmitterSubmission) o1; + SubmitterSubmission u2 = (SubmitterSubmission) o2; if (u1 == null || u2 == null) { @@ -9508,8 +9857,8 @@ else if (m_criteria.equals(SORTED_GRADE_SUBMISSION_BY_STATUS)) { // sort by submission status - UserSubmission u1 = (UserSubmission) o1; - UserSubmission u2 = (UserSubmission) o2; + SubmitterSubmission u1 = (SubmitterSubmission) o1; + SubmitterSubmission u2 = (SubmitterSubmission) o2; String status1 = ""; String status2 = ""; @@ -9553,8 +9902,8 @@ else if (m_criteria.equals(SORTED_GRADE_SUBMISSION_BY_GRADE)) { // sort by submission status - UserSubmission u1 = (UserSubmission) o1; - UserSubmission u2 = (UserSubmission) o2; + SubmitterSubmission u1 = (SubmitterSubmission) o1; + SubmitterSubmission u2 = (SubmitterSubmission) o2; if (u1 == null || u2 == null) { @@ -9614,8 +9963,8 @@ else if (m_criteria.equals(SORTED_GRADE_SUBMISSION_BY_RELEASED)) { // sort by submission status - UserSubmission u1 = (UserSubmission) o1; - UserSubmission u2 = (UserSubmission) o2; + SubmitterSubmission u1 = (SubmitterSubmission) o1; + SubmitterSubmission u2 = (SubmitterSubmission) o2; if (u1 == null || u2 == null) { @@ -9648,43 +9997,55 @@ else if (m_criteria.equals(SORTED_SUBMISSION_BY_LASTNAME)) { // sorted by the submitters sort name - User[] u1 = ((AssignmentSubmission) o1).getSubmitters(); - User[] u2 = ((AssignmentSubmission) o2).getSubmitters(); + AssignmentSubmission _a1 = (AssignmentSubmission)o1; + AssignmentSubmission _a2 = (AssignmentSubmission)o2; + String _s1 = ""; + String _s2 = ""; - if (u1 == null || u1.length == 0 || u2 == null || u2.length ==0) - { - return 1; + if (_a1.getAssignment().isGroup()) { + try + { + Site site = SiteService.getSite(_a1.getAssignment().getContext()); + _s1 = site.getGroup(_a1.getSubmitterId()).getTitle(); + } + catch (Throwable _dfef) + { + } } else { - String submitters1 = ""; - String submitters2 = ""; - - for (int j = 0; j < u1.length; j++) + try { - if (u1[j] != null && u1[j].getSortName() != null) + _s1 = UserDirectoryService.getUser(_a1.getSubmitterId()).getSortName(); + } + catch (UserNotDefinedException e) { - if (j > 0) - { - submitters1 = submitters1.concat("; "); - } - submitters1 = submitters1.concat("" + u1[j].getSortName()); - } + M_log.warn(this + ": cannot find user id=" + _a1.getSubmitterId() + e.getMessage() + ""); + } + } + if (_a2.getAssignment().isGroup()) { + try + { + Site site = SiteService.getSite(_a2.getAssignment().getContext()); + _s2 = site.getGroup(_a2.getSubmitterId()).getTitle(); } - - for (int j = 0; j < u2.length; j++) + catch (Throwable _dfef) + { // TODO empty exception block + } + } + else + { + try { - if (u2[j] != null && u2[j].getSortName() != null) - { - if (j > 0) - { - submitters2 = submitters2.concat("; "); - } - submitters2 = submitters2.concat(u2[j].getSortName()); - } + _s2 = UserDirectoryService.getUser(_a2.getSubmitterId()).getSortName(); + } + catch (UserNotDefinedException e) + { + M_log.warn(this + ": cannot find user id=" + _a2.getSubmitterId() + e.getMessage() + ""); } - result = compareString(submitters1, submitters2); } + + result = _s1.compareTo(_s2); //compareString(submitters1, submitters2); } else if (m_criteria.equals(SORTED_SUBMISSION_BY_SUBMIT_TIME)) { @@ -10067,7 +10428,12 @@ { // show not deleted assignments Time openTime = a.getOpenTime(); - if (openTime != null && currentTime.after(openTime) && !a.getDraft()) + Time visibleTime = a.getVisibleTime(); + if ( + ( + (openTime != null && currentTime.after(openTime))|| + (visibleTime != null && currentTime.after(visibleTime)) + ) && !a.getDraft()) { returnResources.add(a); } @@ -10096,14 +10462,11 @@ } else if (MODE_INSTRUCTOR_REPORT_SUBMISSIONS.equals(mode)) { - List submissions = new ArrayList(); + List submissions = new ArrayList(); - List assignments = iterator_to_list(AssignmentService.getAssignmentsForContext(contextString)); - if (assignments.size() > 0) - { - // users = AssignmentService.allowAddSubmissionUsers (((Assignment)assignments.get(0)).getReference ()); - } - + List assignments = iterator_to_list(AssignmentService.getAssignmentsForContext(contextString)); + if (assignments.size() > 0) + { try { // get the site object first @@ -10127,17 +10490,39 @@ if (s != null && (s.getSubmitted() || (s.getReturned() && (s.getTimeLastModified().before(s .getTimeReturned()))))) { - // has been subitted or has been returned and not work on it yet - User[] submitters = s.getSubmitters(); - if (submitters != null && submitters.length > 0 && !allowGradeAssignmentUsers.contains(submitters[0])) + if (a.isGroup()) { + User[] _users = s.getSubmitters(); + for (int m=0; _users != null && m < _users.length; m++) { + Member member = site.getMember(_users[m].getId()); + if(member != null && member.isActive()) { + // only include the active student submission + // conder TODO create temporary submissions + SubmitterSubmission _new_sub = new SubmitterSubmission(_users[m], s); + _new_sub.setGroup(site.getGroup(s.getSubmitterId())); + submissions.add(_new_sub); + } + } + } else { + if (s.getSubmitterId() != null && !allowGradeAssignmentUsers.contains(s.getSubmitterId())) { - // find whether the submitter is still an active member of the site - Member member = site.getMember(submitters[0].getId()); - if(member != null && member.isActive()) { - // only include the active student submission - submissions.add(s); - } - } + // find whether the submitter is still an active member of the site + Member member = site.getMember(s.getSubmitterId()); + if(member != null && member.isActive()) { + // only include the active student submission + try + { + SubmitterSubmission _new_sub = new SubmitterSubmission(UserDirectoryService.getUser(s.getSubmitterId()), s); + submissions.add(_new_sub); + } + catch (UserNotDefinedException e) + { + M_log.warn(this + ":sizeResources cannot find user id=" + s.getSubmitterId() + e.getMessage() + ""); + } + + } + } + } + } // if-else } } @@ -10153,7 +10538,9 @@ M_log.warn(this + ":sizeResources " + idUnusedException.getMessage() + " site id=" + contextString); } - returnResources = submissions; + + } + returnResources = submissions; } else if (MODE_INSTRUCTOR_GRADE_ASSIGNMENT.equals(mode)) { @@ -10163,6 +10550,37 @@ String aRef = (String) state.getAttribute(EXPORT_ASSIGNMENT_REF); Boolean searchFilterOnly = (state.getAttribute(SUBMISSIONS_SEARCH_ONLY) != null && ((Boolean) state.getAttribute(SUBMISSIONS_SEARCH_ONLY)) ? Boolean.TRUE:Boolean.FALSE); + try { + if (AssignmentService.getAssignment(aRef).isGroup()) { + + Collection submitterGroups = AssignmentService.getSubmitterGroupList("false", allOrOneGroup, "", aRef, contextString); + + // construct the group-submission list + if (submitterGroups != null && !submitterGroups.isEmpty()) + { + for (Iterator iSubmitterGroupsIterator = submitterGroups.iterator(); iSubmitterGroupsIterator.hasNext();) + { + Group gId = iSubmitterGroupsIterator.next(); + if (gId.getProperties().get(GROUP_SECTION_PROPERTY) == null) { + try + { + AssignmentSubmission sub = AssignmentService.getSubmission(aRef, gId.getId()); + returnResources.add(new SubmitterSubmission(gId, sub)); // UserSubmission accepts either User or Group + } + catch (IdUnusedException subIdException) + { + M_log.warn(this + ".sizeResources: looking for submission for unused assignment id " + aRef + subIdException.getMessage()); + } + catch (PermissionException subPerException) + { + M_log.warn(this + ".sizeResources: cannot have permission to access submission of assignment " + aRef + " of group " + gId.getId()); + } + } + } + } + + } else { + List submitterIds = AssignmentService.getSubmitterIdList(searchFilterOnly.toString(), allOrOneGroup, search, aRef, contextString); // construct the user-submission list @@ -10178,7 +10596,7 @@ try { AssignmentSubmission sub = AssignmentService.getSubmission(aRef, u); - returnResources.add(new UserSubmission(u, sub)); + returnResources.add(new SubmitterSubmission(u, sub)); } catch (IdUnusedException subIdException) { @@ -10195,8 +10613,21 @@ } } } + } + } + catch (PermissionException aPerException) + { + M_log.warn(":getSubmitterGroupList: Not allowed to get assignment " + aRef + " " + aPerException.getMessage()); + } + catch (org.sakaiproject.exception.IdUnusedException e) + { + M_log.warn(this + ":sizeResources cannot find assignment " + e.getMessage() + ""); + } + + } + // sort them all String ascending = "true"; String sort = ""; @@ -10344,7 +10773,7 @@ // when there is decimal points inside the grade, scale the number by 10 // but only one decimal place is supported // for example, change 100.0 to 1000 - if (!grade.equals(".")) + if (!".".equals(grade)) { if (grade.length() > index + 2) { @@ -10939,7 +11368,7 @@ try { AssignmentSubmission sub = AssignmentService.getSubmission(aRef, u); - rv.add(sub); + if (!rv.contains(sub)) rv.add(sub); } catch (IdUnusedException subIdException) { @@ -11149,6 +11578,84 @@ } /** + * A utility method to determine users listed in multiple groups + * eligible to submit an assignment. This is a bad situation in + * the current implementation. Until a *conflict* resolution + * method is instituted at least warn the instructor of the + * situation. + */ + public Collection usersInMultipleGroups(Object assignmentorstate, boolean specify_groups, String[] ingroups) { + List retVal = new ArrayList(); + + try { + + Site s = null; + Collection _assignmentGroups = new ArrayList(); + for (int i=0; ingroups != null && i < ingroups.length; i++) + _assignmentGroups.add(ingroups[i]); + + if (assignmentorstate instanceof SessionState) { + s = SiteService.getSite((String)((SessionState)assignmentorstate).getAttribute(STATE_CONTEXT_STRING)); + } else { + Assignment _a = (Assignment)assignmentorstate; + s = SiteService.getSite(_a.getContext()); + if (_a.getAccess().equals(Assignment.AssignmentAccess.SITE)) { + specify_groups = false; + } else { + _assignmentGroups = _a.getGroups(); + specify_groups = true; + } + } + + Iterator _it = s.getUsers().iterator(); + while (_it.hasNext()) { + String _userRef = _it.next(); + Collection _userGroups = s.getGroupsWithMember(_userRef); + int _count = 0; + StringBuilder _sb = new StringBuilder(); + Iterator _checkGroups = _userGroups.iterator(); + while (_checkGroups.hasNext()) { + Group _checkGroup = _checkGroups.next(); + // exclude Sections from eligible groups + if (_checkGroup.getProperties().get(GROUP_SECTION_PROPERTY) == null) { + if (!specify_groups) { + _count++; + if (_count > 1) _sb.append(", "); + _sb.append(_checkGroup.getTitle()); + } else { + if (_assignmentGroups != null) { + Iterator _assgnRefs = _assignmentGroups.iterator(); + while (_assgnRefs.hasNext()) + { + String _ref = _assgnRefs.next(); + Group _group = s.getGroup(_ref); + if (_group != null && _group.getId().equals(_checkGroup.getId())) { + _count++; + if (_count > 1) _sb.append(", "); + _sb.append(_checkGroup.getTitle()); + } + } + } + } + } + } + if (_count > 1) { + try { + retVal.add(UserDirectoryService.getUser(_userRef).getDisplayName() + " (" + _sb.toString() + ")"); + } catch (UserNotDefinedException _unde) { } + } + } + + } catch (IdUnusedException _te) { + + } + return retVal; + } + public Collection usersInMultipleGroups(Assignment _a) { + return usersInMultipleGroups(_a,false,null); + } + + /** * * @return */ @@ -11265,22 +11772,14 @@ Iterator sIterator = submissions.iterator(); while (sIterator.hasNext()) { + try { AssignmentSubmission s = (AssignmentSubmission) sIterator.next(); - User[] users = s.getSubmitters(); - if (users != null && users.length > 0 && users[0] != null) - { - // if Eid contains non ascii characters, internal user id is used - String userEid = users[0].getEid(); - String candidateEid = AssignmentService.escapeInvalidCharsEntry(userEid); - if (candidateEid.equals(userEid)){ - submissionTable.put(candidateEid, new UploadGradeWrapper(s.getGrade(), s.getSubmittedText(), s.getFeedbackComment(), hasSubmissionAttachment?new ArrayList():s.getSubmittedAttachments(), hasFeedbackAttachment?new ArrayList():s.getFeedbackAttachments(), (s.getSubmitted() && s.getTimeSubmitted() != null)?s.getTimeSubmitted().toString():"", s.getFeedbackText())); - } else { - submissionTable.put(users[0].getId(), new UploadGradeWrapper(s.getGrade(), s.getSubmittedText(), s.getFeedbackComment(), hasSubmissionAttachment?new ArrayList():s.getSubmittedAttachments(), hasFeedbackAttachment?new ArrayList():s.getFeedbackAttachments(), (s.getSubmitted() && s.getTimeSubmitted() != null)?s.getTimeSubmitted().toString():"", s.getFeedbackText())); + String _eid = s.getSubmitterId(); + submissionTable.put(_eid, new UploadGradeWrapper(s.getGrade(), s.getSubmittedText(), s.getFeedbackComment(), hasSubmissionAttachment?new ArrayList():s.getSubmittedAttachments(), hasFeedbackAttachment?new ArrayList():s.getFeedbackAttachments(), (s.getSubmitted() && s.getTimeSubmitted() != null)?s.getTimeSubmitted().toString():"", s.getFeedbackText())); + } catch (Throwable _eidprob) {} } } } - } - } InputStream fileContentStream = fileFromUpload.getInputStream(); if(fileContentStream != null) @@ -11392,24 +11891,23 @@ { // escape the first three header lines String[] items = lines[i].split(","); - if (items.length > 4) + if ((assignment.isGroup() && items.length > 3) || items.length > 4) { // has grade information try { + + String _the_eid = items[1]; + if (!assignment.isGroup()) { User u = UserDirectoryService.getUserByEid(items[1]/*user eid*/); - if (u != null) - { - String userEid = u.getEid(); - UploadGradeWrapper w = null; - if (submissionTable.containsKey(userEid)){w = (UploadGradeWrapper) submissionTable.get(userEid); - } else { - // internal user id is used because eid contains non ascii characters - w = (UploadGradeWrapper) submissionTable.get(u.getId()); + if (u == null) throw new Exception("User not found!"); + _the_eid = u.getId(); } + + UploadGradeWrapper w = (UploadGradeWrapper) submissionTable.get(_the_eid); if (w != null) { - String itemString = items[4]; + String itemString = assignment.isGroup() ? items[3]: items[4]; int gradeType = assignment.getContent().getTypeOfGrade(); if (gradeType == Assignment.SCORE_GRADE_TYPE) { @@ -11422,15 +11920,12 @@ if (state.getAttribute(STATE_MESSAGE) == null) { w.setGrade(gradeType == Assignment.SCORE_GRADE_TYPE?scalePointGrade(state, itemString):itemString); - if (submissionTable.containsKey(userEid)){ - submissionTable.put(userEid, w); - } else { - submissionTable.put(u.getId(), w); + submissionTable.put(_the_eid, w); } + } + } - } - } catch (Exception e ) { M_log.warn(this + ":uploadAll_parseZipFile " + e.getMessage()); @@ -11449,40 +11944,47 @@ } else { - // if Eid contains non ascii characters, internal user id is used - // to avoid confusion the string variable is named userId - String userId = ""; + // get user eid part + String userEid = ""; if (entryName.indexOf("/") != -1) { // there is folder structure inside zip if (!zipHasFolder) zipHasFolder = true; // remove the part of zip name - userId = entryName.substring(entryName.indexOf("/")+1); + userEid = entryName.substring(entryName.indexOf("/")+1); // get out the user name part - if (userId.indexOf("/") != -1) + if (userEid.indexOf("/") != -1) { - userId = userId.substring(0, userId.indexOf("/")); + userEid = userEid.substring(0, userEid.indexOf("/")); } - if (userId.indexOf("(") != -1) + // get the eid part + if (userEid.indexOf("(") != -1) { - userId = userId.substring(userId.indexOf("(")+1, userId.indexOf(")")); + userEid = userEid.substring(userEid.indexOf("(")+1, userEid.indexOf(")")); } - userId=StringUtils.trimToNull(userId); + userEid=StringUtils.trimToNull(userEid); + if (!assignment.isGroup()) { + try { + User u = UserDirectoryService.getUserByEid(userEid/*user eid*/); + if (u != null) userEid = u.getId(); + } catch (Throwable _t) { } } - if (submissionTable.containsKey(userId)) + } + + if (submissionTable.containsKey(userEid)) { + if (!zipHasFolderValidUserId) zipHasFolderValidUserId = true; - if (hasComment && entryName.indexOf("comments") != -1) { // read the comments file String comment = getBodyTextFromZipHtml(zipFile.getInputStream(entry)); if (comment != null) { - UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userId); + UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userEid); r.setComment(comment); - submissionTable.put(userId, r); + submissionTable.put(userEid, r); } } if (hasFeedbackText && entryName.indexOf("feedbackText") != -1) @@ -11491,9 +11993,9 @@ String text = getBodyTextFromZipHtml(zipFile.getInputStream(entry)); if (text != null) { - UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userId); + UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userEid); r.setFeedbackText(text); - submissionTable.put(userId, r); + submissionTable.put(userEid, r); } } if (hasSubmissionText && entryName.indexOf("_submissionText") != -1) @@ -11502,9 +12004,9 @@ String text = getBodyTextFromZipHtml(zipFile.getInputStream(entry)); if (text != null) { - UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userId); + UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userEid); r.setText(text); - submissionTable.put(userId, r); + submissionTable.put(userEid, r); } } if (hasSubmissionAttachment) @@ -11514,9 +12016,9 @@ if ( entryName.indexOf(submissionFolder) != -1) { // clear the submission attachment first - UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userId); - submissionTable.put(userId, r); - submissionTable = uploadZipAttachments(state, submissionTable, zipFile.getInputStream(entry), entry, entryName, userId, "submission"); + UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userEid); + submissionTable.put(userEid, r); + submissionTable = uploadZipAttachments(state, submissionTable, zipFile.getInputStream(entry), entry, entryName, userEid, "submission"); } } if (hasFeedbackAttachment) @@ -11526,9 +12028,9 @@ if ( entryName.indexOf(submissionFolder) != -1) { // clear the feedback attachment first - UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userId); - submissionTable.put(userId, r); - submissionTable = uploadZipAttachments(state, submissionTable, zipFile.getInputStream(entry), entry, entryName, userId, "feedback"); + UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userEid); + submissionTable.put(userEid, r); + submissionTable = uploadZipAttachments(state, submissionTable, zipFile.getInputStream(entry), entry, entryName, userEid, "feedback"); } } @@ -11536,9 +12038,9 @@ if (entryName.indexOf("timestamp") != -1) { byte[] timeStamp = readIntoBytes(zipFile.getInputStream(entry), entryName, entry.getSize()); - UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userId); + UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userEid); r.setSubmissionTimestamp(new String(timeStamp)); - submissionTable.put(userId, r); + submissionTable.put(userEid, r); } } } @@ -11617,22 +12119,13 @@ while (sIterator.hasNext()) { AssignmentSubmission s = (AssignmentSubmission) sIterator.next(); - User[] users = s.getSubmitters(); - if (users != null && users.length > 0 && users[0] != null) + if (submissionTable.containsKey(s.getSubmitterId())) { - // if Eid contains non ascii characters, internal user id is used - String uName = users[0].getEid(); - String uNameCandidate = AssignmentService.escapeInvalidCharsEntry(uName); - if (!uNameCandidate.equals(uName)){ - uName = users[0].getId(); - } - if (submissionTable.containsKey(uName)) - { // update the AssignmetnSubmission record AssignmentSubmissionEdit sEdit = editSubmission(s.getReference(), "doUpload_all", state); if (sEdit != null) { - UploadGradeWrapper w = (UploadGradeWrapper) submissionTable.get(uName); + UploadGradeWrapper w = (UploadGradeWrapper) submissionTable.get(s.getSubmitterId()); // the submission text if (hasSubmissionText) @@ -11737,7 +12230,6 @@ } } } - } /** @@ -11747,12 +12239,10 @@ * @param zin * @param entry * @param entryName - * @param userId + * @param userEid * @param submissionOrFeedback */ - // if Eid contains non ascii characters, internal user id is used - // to avoid confusion the string parameter is named userId - private HashMap uploadZipAttachments(SessionState state, HashMap submissionTable, InputStream zin, ZipEntry entry, String entryName, String userId, String submissionOrFeedback) { + private HashMap uploadZipAttachments(SessionState state, HashMap submissionTable, InputStream zin, ZipEntry entry, String entryName, String userEid, String submissionOrFeedback) { // upload all the files as instructor attachments to the submission for grading purpose String fName = entryName.substring(entryName.lastIndexOf("/") + 1, entryName.length()); ContentTypeImageService iService = (ContentTypeImageService) state.getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE); @@ -11781,7 +12271,7 @@ attachment.getPropertiesEdit().addAll(properties); m_contentHostingService.commitResource(attachment); - UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userId); + UploadGradeWrapper r = (UploadGradeWrapper) submissionTable.get(userEid); List attachments = "submission".equals(submissionOrFeedback)?r.getSubmissionAttachments():r.getFeedbackAttachments(); attachments.add(EntityManager.newReference(attachment.getReference())); if ("submission".equals(submissionOrFeedback)) @@ -11792,7 +12282,7 @@ { r.setFeedbackAttachments(attachments); } - submissionTable.put(userId, r); + submissionTable.put(userEid, r); } catch (Exception e) { @@ -11952,6 +12442,8 @@ { SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); ParameterParser params = data.getParameters(); + String view = params.getString("view"); + state.setAttribute(VIEW_SUBMISSION_LIST_OPTION, view); state.setAttribute(STATE_MODE, MODE_INSTRUCTOR_DOWNLOAD_ALL); } // doPrep_download_all @@ -12346,9 +12838,15 @@ String userId = userIds[i]; try { + String assignmentRef = (String) state.getAttribute(EXPORT_ASSIGNMENT_REF); + Assignment _a = getAssignment(assignmentRef, " resubmit update ", state); + AssignmentSubmission submission = null; + if (_a.isGroup()) { + submission = getSubmission(assignmentRef, userId, "doSave_resubmission_option", state); + } else { User u = UserDirectoryService.getUser(userId); - String assignmentRef = (String) state.getAttribute(EXPORT_ASSIGNMENT_REF); - AssignmentSubmission submission = getSubmission(assignmentRef, u, "doSave_resubmission_option", state); + submission = getSubmission(assignmentRef, u, "doSave_resubmission_option", state); + } if (submission != null) { AssignmentSubmissionEdit submissionEdit = editSubmission(submission.getReference(), "doSave_resubmission_option", state); Index: assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_view_assignment.vm =================================================================== --- assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_view_assignment.vm (revision 109227) +++ assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_view_assignment.vm (working copy) @@ -94,6 +94,39 @@ #end + $tlang.getString("gen.groupassignment") + + + #if ($assignment.isGroup()) + $tlang.getString("gen.yes") + #else + $tlang.getString("gen.no") + #end + + + + + $tlang.getString("gen.visible") + + + #set($count=1) + #set($for="") + #foreach ($group in $assignment.Groups) + #set($groupFound=false) + #set($groupFound=$!site.getGroup($group)) + #if($!groupFound) + #if ($count>1) + #set($for=$for.concat(", ")) + #end + #set($for= $for.concat($validator.escapeHtml($groupFound.Title))) + #set($count=$count+1) + #end + #end + $validator.escapeHtml($!for) + + + + $tlang.getString("gen.stusub") Index: assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_student_preview_submission.vm =================================================================== --- assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_student_preview_submission.vm (revision 109227) +++ assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_student_preview_submission.vm (working copy) @@ -14,6 +14,7 @@ $tlang.getString("gen.title") + #assignmentTitleIcon($assignment) $validator.escapeHtml($assignment.getTitle()) Index: assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission_confirmation.vm =================================================================== --- assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission_confirmation.vm (revision 109227) +++ assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission_confirmation.vm (working copy) @@ -2,8 +2,12 @@ #parse("/vm/assignment/assignment_macros.vm") ## showing the submission confirmation page +

+ #if ($!assignment.isGroup()) + $tlang.getString('gen.group') + #end #if ($!submitted) $tlang.getString('confirm.submission.title') #else @@ -17,10 +21,10 @@ $tlang.getString('confirm.savesubmission.success') #end #if ($!email_confirmation && $!submitted) - #if ($!user_email) - $tlang.getString('confirm.submission.email') + #if ($!user_email) + $tlang.getString('confirm.submission.email') + #end #end - #end

#if ($!email_confirmation && $!submitted) #if ($!user_email) @@ -40,6 +44,34 @@ $validator.escapeHtml($!user_name) #if($!user_id)($!user_id)#end + + #if ($!assignment.isGroup() ) + + + $tlang.getString('gen.group'): + + + #set($aGroup = $!site.getGroup($submission.getSubmitterId())) + #if ($aGroup) + $aGroup.getTitle() + #else + $tlang.getString('group.submission.not.found') + #end + + + + + $tlang.getString('gen.students'): + + + #set ($submitters = $submission.submitters) + #foreach ($submitter in $submitters) + $validator.escapeHtml($submitter.DisplayName)
+ #end + + + #end + ##site @@ -55,6 +87,7 @@ $tlang.getString('assignment') + #assignmentTitleIcon($assignment) $validator.escapeHtml($!assignment_title) @@ -82,6 +115,16 @@ #end + #if ($!submission && $!submission.getSubmissionLog().size() > 0) + + History + + #foreach ($entry in $submission.getSubmissionLog()) + $entry
+ #end + + + #end

#if ($!submitted) Index: assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm =================================================================== --- assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm (revision 109227) +++ assignment-tool/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm (working copy) @@ -100,7 +100,12 @@ #end

- $validator.escapeHtml($assignment.getTitle()) - $!tlang.getString('gen.subm2') + $validator.escapeHtml($assignment.getTitle()) + #if ($!assignment.isGroup() ) + + #else + + #end - $!tlang.getString('gen.subm2')

#if ($alertMessage)
$tlang.getString("gen.alert") $validator.escapeHtml($alertMessage)
#end ## reminder of submission download url @@ -117,12 +122,10 @@ ## show the view by group choice when there is at least one group defined + #if (!$assignment.isGroup()) + #if ($!groups.hasNext()) + #end +

+ + + + #if (($!searchString) && (!$searchString.equals(""))) + + #end + + #end #set ($submissionType = $assignment.getContent().getTypeOfSubmission()) #set ($showMsg = false) #set ($showMsg = $!allMsgNumber) #if (!$!showMsg || $showMsg ==0)

-
$tlang.getString("nostudent_searchview")
#else @@ -362,18 +367,30 @@

$tlang.getString( + #if ($assignment.isGroup()) + $tlang.getString("allowResubmission.groups.label") + #else $tlang.getString("allowResubmission.label") + #end