From 5b1b761b69140a4eef61f4f45b33fdd3664ef494 Mon Sep 17 00:00:00 2001 From: Stephen Marquard Date: Tue, 2 May 2023 20:13:20 +0200 Subject: [PATCH] SAK-47948 Gradebook add support for archive (#11506) --- .../business/GradebookNgBusinessService.java | 9 +- .../framework/GradebookNgEntityProducer.java | 197 +++++++++++++++++- .../src/webapp/WEB-INF/applicationContext.xml | 3 + 3 files changed, 204 insertions(+), 5 deletions(-) diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/business/GradebookNgBusinessService.java b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/business/GradebookNgBusinessService.java index dadc99081566..127c9ef9536a 100644 --- a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/business/GradebookNgBusinessService.java +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/business/GradebookNgBusinessService.java @@ -47,6 +47,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.wicket.Application; import org.sakaiproject.assignment.api.AssignmentConstants; import org.sakaiproject.assignment.api.AssignmentReferenceReckoner; @@ -1298,7 +1299,9 @@ public void putCourseGradesInMatrix(Map matrix, List // Setup the course grade formatter // TODO we want the override except in certain cases. Can we hard code this? - final CourseGradeFormatter courseGradeFormatter = new CourseGradeFormatter(gradebook, role, isCourseGradeVisible, settings.getShowPoints(), true, this.getShowCalculatedGrade()); + final CourseGradeFormatter courseGradeFormatter = Application.exists() ? + new CourseGradeFormatter(gradebook, role, isCourseGradeVisible, settings.getShowPoints(), true, this.getShowCalculatedGrade()) : + null; for (final GbUser student : gbStudents) { // Create and add the user info @@ -1308,7 +1311,9 @@ public void putCourseGradesInMatrix(Map matrix, List String uid = student.getUserUuid(); final CourseGradeTransferBean courseGrade = courseGrades.get(uid); final CourseGradeTransferBean gbCourseGrade = courseGrades.get(uid); - gbCourseGrade.setDisplayString(courseGradeFormatter.format(courseGrade)); + if (courseGradeFormatter != null) { + gbCourseGrade.setDisplayString(courseGradeFormatter.format(courseGrade)); + } sg.setCourseGrade(gbCourseGrade); sg.setHasCourseGradeComment(StringUtils.isNotBlank(getAssignmentGradeComment(getCurrentSiteId(),courseGrade.getId(),uid))); // Add to map so we can build on it later diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/framework/GradebookNgEntityProducer.java b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/framework/GradebookNgEntityProducer.java index 89789dd0db01..44908d1d799d 100644 --- a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/framework/GradebookNgEntityProducer.java +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/framework/GradebookNgEntityProducer.java @@ -15,11 +15,16 @@ */ package org.sakaiproject.gradebookng.framework; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; import org.sakaiproject.entity.api.Entity; import org.sakaiproject.entity.api.EntityManager; @@ -28,11 +33,20 @@ import org.sakaiproject.entity.api.HttpAccess; import org.sakaiproject.entity.api.Reference; import org.sakaiproject.entity.api.ResourceProperties; +import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.grading.api.model.Gradebook; import org.sakaiproject.grading.api.GradingService; import org.sakaiproject.grading.api.Assignment; import org.sakaiproject.grading.api.CategoryDefinition; import org.sakaiproject.grading.api.GradebookInformation; +import org.sakaiproject.grading.api.GradeMappingDefinition; +import org.sakaiproject.grading.api.GradingCategoryType; +import org.sakaiproject.gradebookng.business.GradebookNgBusinessService; +import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.SiteService; +import org.sakaiproject.site.api.ToolConfiguration; +import org.sakaiproject.thread_local.api.ThreadLocalManager; + import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -55,6 +69,18 @@ public class GradebookNgEntityProducer implements EntityProducer, EntityTransfer @Setter protected GradingService gradingService; + @Setter + protected GradebookNgBusinessService businessService; + + @Setter + protected SiteService siteService; + + @Setter + protected ThreadLocalManager threadLocalManager; + + protected final static String CURRENT_PLACEMENT = "sakai:ToolComponent:current.placement"; + protected final static String CURRENT_TOOL = "sakai:ToolComponent:current.tool"; + /** * Register this class as an EntityProducer. */ @@ -69,20 +95,185 @@ public String getLabel() { @Override public boolean willArchiveMerge() { - return false; + return true; } @Override public String archive(final String siteId, final Document doc, final Stack stack, final String archivePath, final List attachments) { - return null; + + Site site = null; + try { + site = siteService.getSite(siteId); + } catch(IdUnusedException e) { + return "ERROR: site does not exist\n"; + } + + ToolConfiguration tool = site.getToolForCommonId("sakai.gradebookng"); + if (tool == null) { + return "Gradebook tool not found in site=" + siteId + "\n"; + } + + threadLocalManager.set(CURRENT_PLACEMENT, tool); + threadLocalManager.set(CURRENT_TOOL, tool.getTool()); + + DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd"); + + StringBuilder result = new StringBuilder(); + result.append("archiving ").append(getLabel()).append("\n"); + + // + Element root = doc.createElement(getLabel()); + + // + Element gradebookConfigEl = doc.createElement("GradebookConfig"); + + Gradebook gradebook = this.gradingService.getGradebook(siteId); + if (gradebook == null) { + return "ERROR: Gradebook not found in site\n"; + } + + GradebookInformation settings = this.gradingService.getGradebookInformation(gradebook.getUid()); + List gradeMappings = settings.getGradeMappings(); + String configuredGradeMappingId = settings.getSelectedGradeMappingId(); + GradeMappingDefinition configuredGradeMapping = gradeMappings.stream() + .filter(gradeMapping -> StringUtils.equals(gradeMapping.getId(), configuredGradeMappingId)) + .findAny() + .get(); + + Map gradeMap = settings.getSelectedGradingScaleBottomPercents(); + + Element gradeMappingsEl = doc.createElement("GradeMappings"); + gradeMappingsEl.setAttribute("name", configuredGradeMapping.getName()); + for (Map.Entry entry : gradeMap.entrySet()) { + Element gradeMappingEl = doc.createElement("GradeMapping"); + gradeMappingEl.setAttribute("letterGrade", entry.getKey()); + gradeMappingEl.setAttribute("bottomPercentage", String.valueOf(entry.getValue())); + gradeMappingsEl.appendChild(gradeMappingEl); + } + + gradebookConfigEl.appendChild(gradeMappingsEl); + + Element courseGradeDisplayedEl = doc.createElement("CourseGradeDisplayed"); + courseGradeDisplayedEl.setTextContent(String.valueOf(settings.getCourseGradeDisplayed())); + gradebookConfigEl.appendChild(courseGradeDisplayedEl); + + Element courseLetterGradeDisplayedEl = doc.createElement("CourseLetterGradeDisplayed"); + courseLetterGradeDisplayedEl.setTextContent(String.valueOf(settings.getCoursePointsDisplayed())); + gradebookConfigEl.appendChild(courseLetterGradeDisplayedEl); + + Element coursePointsDisplayedEl = doc.createElement("CoursePointsDisplayed"); + coursePointsDisplayedEl.setTextContent(String.valueOf(settings.getCoursePointsDisplayed())); + gradebookConfigEl.appendChild(coursePointsDisplayedEl); + + Element totalPointsDisplayedEl = doc.createElement("TotalPointsDisplayed"); + totalPointsDisplayedEl.setTextContent(String.valueOf(settings.getCoursePointsDisplayed())); + gradebookConfigEl.appendChild(totalPointsDisplayedEl); + + Element courseAverageDisplayedEl = doc.createElement("CourseAverageDisplayed"); + courseAverageDisplayedEl.setTextContent(String.valueOf(settings.getCourseAverageDisplayed())); + gradebookConfigEl.appendChild(courseAverageDisplayedEl); + + Element categoryTypeEl = doc.createElement("CategoryType"); + String categoryCode = null; + if (settings.getCategoryType() == GradingCategoryType.NO_CATEGORY) { + categoryCode = "NO_CATEGORIES"; + } else if (settings.getCategoryType() == GradingCategoryType.ONLY_CATEGORY) { + categoryCode = "CATEGORIES_APPLIED"; + } else if (settings.getCategoryType() == GradingCategoryType.WEIGHTED_CATEGORY) { + categoryCode = "WEIGHTED_CATEGORIES_APPLIED"; + } else { + categoryCode = "UNKNOWN"; + } + categoryTypeEl.setTextContent(categoryCode); + gradebookConfigEl.appendChild(categoryTypeEl); + + Element gradeTypeEl = doc.createElement("GradeType"); + String gradeTypeCode = null; + switch(settings.getGradeType()) { + case POINTS: + gradeTypeCode = "POINTS"; + break; + case PERCENTAGE: + gradeTypeCode = "PERCENTAGE"; + break; + case LETTER: + gradeTypeCode = "LETTER"; + break; + default: + gradeTypeCode = "UNKNOWN"; + } + gradeTypeEl.setTextContent(gradeTypeCode); + gradebookConfigEl.appendChild(gradeTypeEl); + + if (settings.getCategoryType() != GradingCategoryType.NO_CATEGORY) { + Element categoriesEl = doc.createElement("categories"); + for (CategoryDefinition category : settings.getCategories()) { + Element categoryEl = doc.createElement("category"); + categoryEl.setAttribute("id", String.valueOf(category.getId())); + categoryEl.setAttribute("name", category.getName()); + categoryEl.setAttribute("extraCredit", String.valueOf(category.getExtraCredit())); + if (settings.getCategoryType() == GradingCategoryType.WEIGHTED_CATEGORY) { + categoryEl.setAttribute("weight", String.valueOf(category.getWeight())); + } else { + categoryEl.setAttribute("weight", ""); + } + categoryEl.setAttribute("dropLowest", String.valueOf(category.getDropLowest())); + categoryEl.setAttribute("dropHighest", String.valueOf(category.getDropHighest())); + categoryEl.setAttribute("keepHighest", String.valueOf(category.getKeepHighest())); + categoryEl.setAttribute("order", String.valueOf(category.getCategoryOrder())); + categoriesEl.appendChild(categoryEl); + } + gradebookConfigEl.appendChild(categoriesEl); + } + + root.appendChild(gradebookConfigEl); + + // + List gradebookItems = this.businessService.getGradebookAssignments(siteId); + + gradebookItems = gradebookItems.stream().filter(item -> { + return !item.getExternallyMaintained(); + }).collect(Collectors.toList()); + + Element gradebookItemsEl = doc.createElement("GradebookItems"); + for (Assignment gradebookItem : gradebookItems) { + Element gradebookItemEl = doc.createElement("GradebookItem"); + gradebookItemEl.setAttribute("id", String.valueOf(gradebookItem.getId())); + gradebookItemEl.setAttribute("name", gradebookItem.getName()); + gradebookItemEl.setAttribute("points", String.valueOf(gradebookItem.getPoints())); + if (gradebookItem.getDueDate() == null) { + gradebookItemEl.setAttribute("dueDate", ""); + } else { + gradebookItemEl.setAttribute("dueDate", dateFormat.format(gradebookItem.getDueDate())); + } + gradebookItemEl.setAttribute("countedInCourseGrade", String.valueOf(gradebookItem.getCounted())); + gradebookItemEl.setAttribute("externallyMaintained", String.valueOf(gradebookItem.getExternallyMaintained())); + gradebookItemEl.setAttribute("externalAppName", gradebookItem.getExternalAppName()); + gradebookItemEl.setAttribute("externalId", gradebookItem.getExternalId()); + gradebookItemEl.setAttribute("releasedToStudent", String.valueOf(gradebookItem.getReleased())); + if (gradebookItem.getCategoryId() == null) { + gradebookItemEl.setAttribute("categoryId", ""); + } else { + gradebookItemEl.setAttribute("categoryId", String.valueOf(gradebookItem.getCategoryId())); + } + gradebookItemEl.setAttribute("extraCredit", String.valueOf(gradebookItem.getExtraCredit())); + gradebookItemEl.setAttribute("order", String.valueOf(gradebookItem.getSortOrder())); + gradebookItemEl.setAttribute("categorizedOrder", String.valueOf(gradebookItem.getCategorizedSortOrder())); + gradebookItemsEl.appendChild(gradebookItemEl); + } + root.appendChild(gradebookItemsEl); + + stack.peek().appendChild(root); + + return result.toString(); } @Override public String merge(final String siteId, final Element root, final String archivePath, final String fromSiteId, final Map attachmentNames, final Map userIdTrans, final Set userListAllowImport) { - return null; + return "GradebookNG merge not supported: nothing to do."; } @Override diff --git a/gradebookng/tool/src/webapp/WEB-INF/applicationContext.xml b/gradebookng/tool/src/webapp/WEB-INF/applicationContext.xml index fba7fbac564f..dd11845973e6 100644 --- a/gradebookng/tool/src/webapp/WEB-INF/applicationContext.xml +++ b/gradebookng/tool/src/webapp/WEB-INF/applicationContext.xml @@ -45,6 +45,9 @@ init-method="init"> + + +