Skip to content

Commit

Permalink
SAK-33603 - Assignment Soft Deletion UI (sakaiproject#5302)
Browse files Browse the repository at this point in the history
  • Loading branch information
Miguel Pellicer authored and ern committed Feb 13, 2018
1 parent 7ca8fa1 commit f36e493
Show file tree
Hide file tree
Showing 21 changed files with 336 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,15 @@ public interface AssignmentService extends EntityProducer {
*/
public Collection<Assignment> getAssignmentsForContext(String context);

/**
* Access all the Assignments that are deleted
*
* @param context -
* Describes the portlet context - generated with DefaultId.getChannel().
* @return List All the deleted assignments will be listed
*/
public Collection<Assignment> getDeletedAssignmentsForContext(String context);

/**
* Retrieve a map of Assignments to a list of User IDs of those who
* may submit each assignment. This map is filtered to only those
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public interface AssignmentRepository extends SerializableRepository<Assignment,

List<Assignment> findAssignmentsBySite(String siteId);

List<Assignment> findDeletedAssignmentsBySite(String siteId);

List<String> findAllAssignmentIds();

void newAssignment(Assignment assignment);
Expand Down
6 changes: 6 additions & 0 deletions assignment/bundles/resources/assignment.properties
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,13 @@ youmust8 = You must upload an attachment
list.show = Show
list.itemsper = items...
update = Update
removedAssignmentList = Removed Assignments List
removeSelected = Remove Selected
selectAssignments = Select Assignments
restoreSelected = Restore Selected
hardRemoveSelected = Permanently Remove Selected
restoreConfirmation = These items will be restored. Are you sure?
hardRemoveConfirmation = These items will be permanently removed and cannot be recovered. Are you sure?
subasstudent = Submit as Student
alert.globalNavi = If you choose to exit without clicking any of the assignment submission navigation action buttons at the top or 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 on this page.
viewassign = View Assignment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,15 @@ public Collection<Assignment> getAssignmentsForContext(String context) {
return assignments;
}

@Override
public Collection<Assignment> getDeletedAssignmentsForContext(String context) {
log.debug("GET DELETED ASSIGNMENTS : CONTEXT : {}", context);
List<Assignment> assignments = new ArrayList<>();
if (StringUtils.isBlank(context)) return assignments;

return assignmentRepository.findDeletedAssignmentsBySite(context);
}

@Override
public Map<Assignment, List<String>> getSubmittableAssignmentsForContext(String context) {
Map<Assignment, List<String>> submittable = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ public List<Assignment> findAssignmentsBySite(String siteId) {
.list();
}

@Override
@SuppressWarnings("unchecked")
public List<Assignment> findDeletedAssignmentsBySite(String siteId) {
return startCriteriaQuery()
.add(Restrictions.eq("context", siteId))
.add(Restrictions.eq("deleted", Boolean.TRUE))
.list();
}

@Override
public List<String> findAllAssignmentIds() {
return startCriteriaQuery()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,32 @@ public void findSubmissionForUser() {
}
}

@Test
public void getDeletedAssignmentsForContext() {
String context = UUID.randomUUID().toString();
Assignment assignment = createNewAssignment(context);
String stringRef = AssignmentReferenceReckoner.reckoner().context(assignment.getContext()).subtype("a").id(assignment.getId()).reckon().getReference();
when(securityService.unlock(AssignmentServiceConstants.SECURE_REMOVE_ASSIGNMENT, stringRef)).thenReturn(true);
//The assignment list should contain the newly created element
Collection<Assignment> assignmentCollection = assignmentService.getAssignmentsForContext(context);
Assert.assertNotNull(assignmentCollection);
Assert.assertEquals(1, assignmentCollection.size());
//Soft delete the assignment
try{
assignmentService.softDeleteAssignment(assignment);
} catch (PermissionException e) {
Assert.fail("Get Deleted Assignments For context");
}
//The assignment list should not contain the assignment because it's deleted
assignmentCollection = assignmentService.getAssignmentsForContext(context);
Assert.assertNotNull(assignmentCollection);
Assert.assertEquals(0, assignmentCollection.size());
//The assignment list should contain the assignment because it's deleted
Collection<Assignment> deletedAssignmentCollection = assignmentService.getDeletedAssignmentsForContext(context);
Assert.assertNotNull(deletedAssignmentCollection);
Assert.assertEquals(1, deletedAssignmentCollection.size());
}

@Test
public void duplicateAssignment() throws IdUnusedException {
// Setup a new Assignment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,11 @@ public class AssignmentAction extends PagedResourceActionII {
*/
private static final String TEMPLATE_LIST_ASSIGNMENTS = "_list_assignments";

/**
* The list view of softly deleted assignments
*/
private static final String MODE_LIST_DELETED_ASSIGNMENTS = "Assignment.mode_list_removed_assignments";

/* ************************* vm names ************************** */
/**
* The student view of assignment
Expand Down Expand Up @@ -705,6 +710,10 @@ public class AssignmentAction extends PagedResourceActionII {
* The instructor view to list users details
**/
private static final String TEMPLATE_INSTRUCTOR_VIEW_STUDENTS_DETAILS = "_instructor_view_students_details";
/**
* The instructor view to list deleted assignment
*/
private static final String TEMPLATE_INSTRUCTOR_LIST_DELETED_ASSIGNMENTS = "_instructor_list_deleted_assignments";
/**
* The options page
*/
Expand Down Expand Up @@ -1084,6 +1093,10 @@ public String buildMainPanelContext(VelocityPortlet portlet, Context context, Ru
boolean allowAllGroups = assignmentService.allowAllGroups(contextString);
context.put("allowAllGroups", Boolean.valueOf(allowAllGroups));

// allow recover assignment?
boolean allowRecoverAssignment = assignmentService.allowRemoveAssignment(AssignmentReferenceReckoner.reckoner().context(contextString).reckon().getReference());
context.put("allowRecoverAssignment", allowRecoverAssignment);

//Is the review service allowed?
Site s = null;
try {
Expand Down Expand Up @@ -1259,6 +1272,10 @@ public String buildMainPanelContext(VelocityPortlet portlet, Context context, Ru
}
} else if (mode.equals(MODE_STUDENT_REVIEW_EDIT)) {
template = build_student_review_edit_context(portlet, context, data, state);
} else if (MODE_LIST_DELETED_ASSIGNMENTS.equals(mode)) {
if (allowRecoverAssignment) {
template = build_list_deleted_assignments_context(portlet, context, data, state);
}
}

if (template == null) {
Expand Down Expand Up @@ -2275,6 +2292,34 @@ private HashSet<String> getAllowAddSubmissionUsersIdSet(List users) {
return rv;
}

/**
* build the view of assignments list
*/
private String build_list_deleted_assignments_context(VelocityPortlet portlet, Context context, RunData data, SessionState state) {
// cleaning from view attribute
state.removeAttribute(FROM_VIEW);

String contextString = (String) state.getAttribute(STATE_CONTEXT_STRING);
String sortedBy = (String) state.getAttribute(SORTED_BY);
String sortedAsc = (String) state.getAttribute(SORTED_ASC);
context.put("sortedBy", sortedBy);
context.put("sortedAsc", sortedAsc);

List<Assignment> assignments = prepPage(state);
context.put("assignments", assignments.iterator());

add2ndToolbarFields(data, context);

// inform the observing courier that we just updated the page...
// if there are pending requests to do so they can be cleared
justDelivered(state);

pagingInfoToContext(state, context);

String template = (String) getContext(data).get("template");
return template + TEMPLATE_INSTRUCTOR_LIST_DELETED_ASSIGNMENTS;
} // build_list_deleted_assignments_context

/**
* build the instructor view of creating a new assignment or editing an existing one
*/
Expand Down Expand Up @@ -5457,6 +5502,18 @@ public void doList_assignments(RunData data) {

} // doList_assignments

/**
* Action is to view the list of deleted assignments
*/
public void doView_deletedAssignments(RunData data) {
SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());

state.setAttribute(STATE_MODE, MODE_LIST_DELETED_ASSIGNMENTS);
state.setAttribute(SORTED_BY, SORTED_BY_TITLE);
state.setAttribute(SORTED_ASC, Boolean.TRUE.toString());

} // doView_deletedAssignments

/**
* Action is to cancel the student view grade process
*/
Expand Down Expand Up @@ -9558,40 +9615,88 @@ private void removeCalendarEventFromCalendar(SessionState state, Assignment assi
/**
* Action is to delete the assignment and also the related AssignmentSubmission
*/
public void doDeep_delete_assignment(RunData data) {
public void doHardRemove_confirm_assignment(RunData data) {
if (!"POST".equals(data.getRequest().getMethod())) {
return;
}

SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
ParameterParser params = data.getParameters();

// get the delete assignment ids
List<String> ids = (List<String>) state.getAttribute(DELETE_ASSIGNMENT_IDS);
for (String id : ids) {
Assignment a = null;
try {
a = assignmentService.getAssignment(id);
// get the assignment ids
String[] assignmentIds = params.getStrings("selectedAssignments");
if (assignmentIds != null) {
for (String id : assignmentIds) {
Assignment a = null;
try {
a = assignmentService.getAssignment(id);

if (a != null) {
if (taggingManager.isTaggable()) {
for (TaggingProvider provider : taggingManager.getProviders()) {
provider.removeTags(assignmentActivityProducer.getActivity(a));
if (a != null) {
if (taggingManager.isTaggable()) {
for (TaggingProvider provider : taggingManager.getProviders()) {
provider.removeTags(assignmentActivityProducer.getActivity(a));
}
}

assignmentService.deleteAssignment(a);
}

assignmentService.deleteAssignmentAndAllReferences(a);
} catch (IdUnusedException | PermissionException e) {
addAlert(state, rb.getFormattedMessage("youarenot_editAssignment", id));
log.warn(e.getMessage());
}
}

} catch (IdUnusedException | PermissionException e) {
addAlert(state, rb.getFormattedMessage("youarenot_editAssignment", id));
log.warn(e.getMessage());
if (state.getAttribute(STATE_MESSAGE) == null) {
state.setAttribute("selectedAssignments", new ArrayList());
state.setAttribute(STATE_MODE, MODE_LIST_ASSIGNMENTS);
state.setAttribute(STATE_SELECTED_VIEW, MODE_LIST_ASSIGNMENTS);
}
} else {
addAlert(state, rb.getString("youmust6"));
}
} // doHardRemove_confirm_assignment

/**
* Action is to show the restore assigment confirmation screen
*/
public void doRestore_confirm_assignment(RunData data) {
if (!"POST".equals(data.getRequest().getMethod())) {
return;
}

SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
ParameterParser params = data.getParameters();

// get the assignment ids
String[] assignmentIds = params.getStrings("selectedAssignments");
if (assignmentIds != null) {
for (String id : assignmentIds) {
Assignment a = null;
try {
a = assignmentService.getAssignment(id);

if (a != null) {
a.setDeleted(false);
assignmentService.updateAssignment(a);
}

} catch (IdUnusedException | PermissionException e) {
addAlert(state, rb.getFormattedMessage("youarenot_editAssignment", id));
log.warn(e.getMessage());
}
}

if (state.getAttribute(STATE_MESSAGE) == null) {
state.setAttribute(DELETE_ASSIGNMENT_IDS, new ArrayList());
state.setAttribute("selectedAssignments", new ArrayList());
state.setAttribute(STATE_MODE, MODE_LIST_ASSIGNMENTS);
state.setAttribute(STATE_SELECTED_VIEW, MODE_LIST_ASSIGNMENTS);
}
} else {
addAlert(state, rb.getString("youmust6"));
}
}

} // doRestore_confirm_assignment

/**
* Action is to show the duplicate assignment screen
Expand Down Expand Up @@ -11929,6 +12034,9 @@ protected int sizeResources(SessionState state) {
}
break;
}
case MODE_LIST_DELETED_ASSIGNMENTS:
returnResources.addAll(assignmentService.getDeletedAssignmentsForContext((String) state.getAttribute(STATE_CONTEXT_STRING)));
break;
}

// sort them all
Expand Down Expand Up @@ -11997,6 +12105,8 @@ public void doView(RunData data) {
doReport_submissions(data);
} else if (MODE_STUDENT_VIEW.equals(viewMode)) {
doView_student(data);
} if (MODE_LIST_DELETED_ASSIGNMENTS.equals(viewMode)) {
doView_deletedAssignments(data);
}

// reset the global navigaion alert flag
Expand Down
19 changes: 19 additions & 0 deletions assignment/tool/src/webapp/js/assignments.js
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,25 @@ ASN.checkEnableRemove = function()
document.getElementById( "btnRemove" ).className = (selected ? "active" : "" );
};

ASN.checkEnableRestore = function()
{
var selected = false;
var checkboxes = document.getElementsByName( "selectedAssignments" );
for( var i = 0; i < checkboxes.length; i++ )
{
if( checkboxes[i].checked )
{
selected = true;
break;
}
}

document.getElementById( "btnRestore" ).disabled = !selected;
document.getElementById( "btnRestore" ).className = (selected ? "active" : "" );
document.getElementById( "btnHardRemove" ).disabled = !selected;
document.getElementById( "btnHardRemove" ).className = (selected ? "active" : "" );
};

ASN.toggleResubmitTimePanel = function()
{
if( document.getElementById( "allowResubmitNumber" ).value !== 0 && document.getElementById( "allowResubmitTime" ) !== null )
Expand Down
Loading

0 comments on commit f36e493

Please sign in to comment.