Skip to content

Commit

Permalink
SAK-45039 Improve number of submission in grades widget (sakaiproject…
Browse files Browse the repository at this point in the history
…#9051)

https://jira.sakaiproject.org/browse/SAK-45039

This change results in the grades api endpoint asking assignments or
samigo for the number of submissions and graded, when the GB assignment
is externally maintained.
  • Loading branch information
adrianfish authored Mar 5, 2021
1 parent 146cf55 commit 2295f17
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -659,13 +659,14 @@ public interface AssignmentService extends EntityProducer {
*
* @param context The site id
* @param assignmentId The assignment id
* @param allowReadAssignment Is the curent user allowed to read?
* @param allowAddAssignment Is the curent user allowed to add assignments?
* @param allowSubmitAssignment Is the curent user allowed to submit assignments?
* @param allowReadAssignment Is the current user allowed to read?
* @param allowAddAssignment Is the current user allowed to add assignments?
* @param allowSubmitAssignment Is the current user allowed to submit assignments?
* @param allowGradeAssignment Is the current user allowed to grade assignments?
* @return The url as a String
*/
public String getDeepLinkWithPermissions(String context, String assignmentId, boolean allowReadAssignment
, boolean allowAddAssignment, boolean allowSubmitAssignment) throws Exception;
, boolean allowAddAssignment, boolean allowSubmitAssignment, boolean allowGradeAssignment) throws Exception;

/**
* Get a link directly into an assignment itself. Depending on your status, you
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ public Optional<String> getEntityUrl(Reference ref, Entity.UrlType urlType) {

try {
Assignment a = getAssignment(ref);
return Optional.of(this.getDeepLink(a.getContext(), a.getId(), userDirectoryService.getCurrentUser().getId()));
return Optional.of(getDeepLink(a.getContext(), a.getId(), userDirectoryService.getCurrentUser().getId()));
} catch (Exception e) {
return Optional.empty();
}
Expand Down Expand Up @@ -2459,7 +2459,7 @@ public Integer getScaleFactor() {
}

@Override
public String getDeepLinkWithPermissions(String context, String assignmentId, boolean allowReadAssignment, boolean allowAddAssignment, boolean allowSubmitAssignment) throws Exception {
public String getDeepLinkWithPermissions(String context, String assignmentId, boolean allowReadAssignment, boolean allowAddAssignment, boolean allowSubmitAssignment, boolean allowGradeAssignment) throws Exception {
Assignment a = getAssignment(assignmentId);

String assignmentContext = a.getContext(); // assignment context
Expand All @@ -2471,7 +2471,14 @@ public String getDeepLinkWithPermissions(String context, String assignmentId, bo
ToolConfiguration fromTool = site.getToolForCommonId("sakai.assignment.grades");
// Three different urls to be rendered depending on the
// user's permission
if (allowAddAssignment) {
if (allowGradeAssignment) {
return serverConfigurationService.getPortalUrl()
+ "/directtool/"
+ fromTool.getId()
+ "?assignmentId="
+ AssignmentReferenceReckoner.reckoner().context(context).id(assignmentId).reckon().getReference()
+ "&panel=Main&sakai_action=doGrade_assignment";
} else if (allowAddAssignment) {
return serverConfigurationService.getPortalUrl()
+ "/directtool/"
+ fromTool.getId()
Expand Down Expand Up @@ -2513,8 +2520,9 @@ public String getDeepLink(String context, String assignmentId, String userId) th
boolean allowReadAssignment = permissionCheck(SECURE_ACCESS_ASSIGNMENT, resourceString, userId);
boolean allowAddAssignment = permissionCheck(SECURE_ADD_ASSIGNMENT, resourceString, userId) || (!getGroupsAllowFunction(SECURE_ADD_ASSIGNMENT, context, userId).isEmpty());
boolean allowSubmitAssignment = permissionCheck(SECURE_ADD_ASSIGNMENT_SUBMISSION, resourceString, userId);
boolean allowGradeAssignment = permissionCheck(SECURE_GRADE_ASSIGNMENT_SUBMISSION, resourceString, userId);

return getDeepLinkWithPermissions(context, assignmentId, allowReadAssignment, allowAddAssignment, allowSubmitAssignment);
return getDeepLinkWithPermissions(context, assignmentId, allowReadAssignment, allowAddAssignment, allowSubmitAssignment, allowGradeAssignment);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,12 @@ public Map<String, String> getAssignmentDeepLinks(EntityView view,
.get("allowAddAssignment")).booleanValue() : false;
boolean allowSubmitAssignment = params.get("allowSubmitAssignment") != null ? ((Boolean) params
.get("allowSubmitAssignment")).booleanValue() : false;
boolean allowGradeAssignment = params.get("allowGradeAssignment") != null ? ((Boolean) params
.get("allowGradeAssignment")).booleanValue() : false;

assignData.put("assignmentUrl"
, assignmentService.getDeepLinkWithPermissions(context, assignmentId
, allowReadAssignment, allowAddAssignment, allowSubmitAssignment));
, allowReadAssignment, allowAddAssignment, allowSubmitAssignment, allowGradeAssignment));
} catch (IdUnusedException e) {
throw new EntityNotFoundException("Assignment or site not found", assignmentId, e);
} catch (PermissionException e) {
Expand Down
2 changes: 1 addition & 1 deletion gradebookng/bundle/src/main/bundle/gradebookng.properties
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,6 @@ sort_course_a_to_z=Course: A-Z
sort_course_z_to_a=Course: Z-A
course_average=Course Avg.
submissions=submissions
new_submissions=new submissions
new_submissions=ungraded item(s)
view=View
widget_title=Grades
8 changes: 8 additions & 0 deletions webapi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@
<groupId>org.sakaiproject.edu-services.gradebook</groupId>
<artifactId>gradebook-service-api</artifactId>
</dependency>
<dependency>
<groupId>org.sakaiproject.samigo</groupId>
<artifactId>samigo-services</artifactId>
</dependency>
<dependency>
<groupId>org.sakaiproject.samigo</groupId>
<artifactId>samigo-api</artifactId>
</dependency>
<!-- Spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,22 @@
******************************************************************************/
package org.sakaiproject.webapi.controllers;

import org.sakaiproject.webapi.beans.GradeRestBean;
import org.sakaiproject.service.gradebook.shared.GradebookNotFoundException;
import org.sakaiproject.assignment.api.AssignmentService;
import org.sakaiproject.assignment.api.model.Assignment;
import org.sakaiproject.assignment.api.model.AssignmentSubmission;
import org.sakaiproject.entity.api.Entity;
import org.sakaiproject.entity.api.EntityManager;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.service.gradebook.shared.GradebookService;
import org.sakaiproject.service.gradebook.shared.GradeDefinition;
import org.sakaiproject.service.gradebook.shared.SortType;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.tool.assessment.data.dao.grading.AssessmentGradingData;
import org.sakaiproject.tool.assessment.services.GradingService;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.webapi.beans.GradeRestBean;

import org.springframework.http.MediaType;

Expand All @@ -35,6 +42,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand All @@ -48,11 +56,19 @@
@RestController
public class GradesController extends AbstractSakaiApiController {

@Resource(name = "org_sakaiproject_service_gradebook_GradebookService")
private GradebookService gradebookService;
@Resource
private AssignmentService assignmentService;

@Resource
private EntityManager entityManager;

@Resource(name = "org_sakaiproject_service_gradebook_GradebookService")
private GradebookService gradebookService;

@Resource
private SiteService siteService;

@Resource
private SiteService siteService;
private GradingService samigoGradingService;

private Function<Site, List<GradeRestBean>> convert = (s) -> {

Expand All @@ -66,49 +82,87 @@ public class GradesController extends AbstractSakaiApiController {
return gradebookService.getAssignments(s.getId()).stream()
.map(a -> {

GradeRestBean gtb = new GradeRestBean(a);
List<String> students = new ArrayList<>(s.getUsers());
List<GradeDefinition> grades
= gradebookService.getGradesForStudentsForItem(s.getId(), a.getId(), students);
try {
GradeRestBean gtb = new GradeRestBean(a);

double total = 0;
for (GradeDefinition gd : grades) {
if (gd.getGradeEntryType() == GradebookService.GRADE_TYPE_POINTS) {
total += Double.parseDouble(gd.getGrade());
gtb.setSiteTitle(s.getTitle());
gtb.setUrl(url);

List<String> students = new ArrayList<>(s.getUsers());
List<GradeDefinition> grades
= gradebookService.getGradesForStudentsForItem(s.getId(), a.getId(), students);

double total = 0;
for (GradeDefinition gd : grades) {
if (gd.getGradeEntryType() == GradebookService.GRADE_TYPE_POINTS) {
total += Double.parseDouble(gd.getGrade());
}
}
}

int count = grades.size();
gtb.setAverageScore(total > 0 && count > 0 ? total / count : 0);
gtb.setUngraded(students.size() - count);
gtb.setSiteTitle(s.getTitle());
gtb.setUrl(url);
return gtb;
}).collect(Collectors.toList());
int count = grades.size();
gtb.setAverageScore(total > 0 && count > 0 ? total / count : 0);
gtb.setUngraded(students.size() - count);

if (a.isExternallyMaintained()) {
int submitted = 0, graded = 0;
switch (a.getExternalAppName()) {
case "Assignments":
try {
Assignment assignment = assignmentService.getAssignment(entityManager.newReference(a.getExternalId()));
for (AssignmentSubmission as : assignment.getSubmissions()) {
if (as.getUserSubmission()) submitted += 1;
if (as.getGraded()) graded += 1;
}
gtb.setUrl(entityManager.getUrl(a.getExternalId(), Entity.UrlType.PORTAL).orElse(""));
} catch (IdUnusedException idue) {
log.error("Gradebook external assignment id of {} not a valid assignment", a.getExternalId());
} catch (PermissionException pe) {
log.error("Not allowed to access assignment {}", a.getExternalId());
}
break;
case "Tests & Quizzes":
GradingService samigoGradingService = new GradingService();
List<AssessmentGradingData> gradings = samigoGradingService.getAllSubmissions(a.getExternalId());
for (AssessmentGradingData grading : gradings) {
if (grading.getStatus() == 1) submitted += 1;
// TODO: this is bum way of working out if an instructor has scored a quiz.
if (grading.getFinalScore() != 0.0) graded +=1;
}
break;
default:
}
gtb.setUngraded(submitted - graded);
}
return gtb;
} catch (Exception e) {
log.error("Failed to build bean for assignment {}", a.getId(), e);
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
} catch (Exception gnfe) {
return Collections.<GradeRestBean>emptyList();
}
};

@ApiOperation(value = "Get a particular user's grades data")
@GetMapping(value = "/users/{userId}/grades", produces = MediaType.APPLICATION_JSON_VALUE)
@GetMapping(value = "/users/{userId}/grades", produces = MediaType.APPLICATION_JSON_VALUE)
public List<GradeRestBean> getUserGrades(@PathVariable String userId) throws UserNotDefinedException {

checkSakaiSession();
checkSakaiSession();
return siteService.getUserSites().stream().map(convert).flatMap(Collection::stream).collect(Collectors.toList());
}
}

@ApiOperation(value = "Get a particular site's grades data")
@GetMapping(value = "/sites/{siteId}/grades", produces = MediaType.APPLICATION_JSON_VALUE)
@GetMapping(value = "/sites/{siteId}/grades", produces = MediaType.APPLICATION_JSON_VALUE)
public List<GradeRestBean> getSiteGrades(@PathVariable String siteId) throws UserNotDefinedException {

checkSakaiSession();
checkSakaiSession();

try {
return convert.apply(siteService.getSite(siteId));
} catch (Exception e) {
log.error("Failed to get grades for site {}. Returning empty list ...", siteId);
return Collections.<GradeRestBean>emptyList();
}
}
}
}

0 comments on commit 2295f17

Please sign in to comment.