diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/GradebookNgApplication.properties b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/GradebookNgApplication.properties index 68cb90bfb4..7b394ba3ba 100644 --- a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/GradebookNgApplication.properties +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/GradebookNgApplication.properties @@ -42,6 +42,9 @@ label.gradeitem.counted=Gradebook Item is included in the course grade calculati label.gradeitem.notcounted=Gradebook Item not included in course grade calculation. label.gradeitem.extracredit=This is an Extra Credit Gradebook Item label.gradeitem.extracreditcategory=This is an Extra Credit Category +label.gradeitem.droplowestcategory=This category is dropping the {0} lowest score(s). +label.gradeitem.drophighestcategory=This category is dropping the {0} highest score(s). +label.gradeitem.keephighestcategory=This category is only keeping the {0} highest score(s). label.gradeitem.categoryaverage={0} Weighted Average label.gradeitem.categoryaveragelabel=Weighted Average label.gradeitem.categoryheadertooltip=Category: {0} @@ -86,6 +89,7 @@ filter.studentsclear = Clear student filter filter.groups = Filter by group/section button.addgradeitem = Add Gradebook Item +button.viewgradebookitems = View Gradebook Items button.savechanges = Save Changes button.cancel = Cancel button.done = Done @@ -102,6 +106,7 @@ button.print = Print heading.addgradeitem = Add Gradebook Item heading.editgradeitem = Edit Gradebook Item +heading.viewgradebookitems = View Gradebook Items heading.studentsummary = Grade Summary for {0} ({1}) heading.updateungradeditems = Set Score for Empty Cells heading.gradelog = Grade Log for {0} ({1}) @@ -284,6 +289,15 @@ importExport.export.csv.headers.example.ignore = This column will be ignored # Student ID and Student Name are not here because they are a special string. # To i18n these, the import helper would need to be made to look for columns by position instead of by column title +#Items Page Labels +items.tableHeader.items = Gradebook Item +items.tableHeader.outOf = Points +items.tableHeader.numberGraded = Number of
Graded Students +items.tableHeader.statistics = Grade Statistics
[Average Score] +items.tableHeader.delete = Delete + +items.table.total.points = Total Points + assignment.option.edit = Edit Item Details assignment.option.viewgradestatistics = View Grade Statistics assignment.option.moveleft = Move Left @@ -355,6 +369,8 @@ label.nocategoryscore = - errorpage.heading = Something went wrong errorpage.text = You should refresh and try again. If you end up back here, quote the following error number to your local IT Support: {0}. +itemspage.main.heading = Gradebook Items + settingspage.main.heading = Settings settingspage.gradeentry.heading = Grade Entry diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/model/GbItem.java b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/model/GbItem.java new file mode 100644 index 0000000000..4a38570910 --- /dev/null +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/model/GbItem.java @@ -0,0 +1,35 @@ +package org.sakaiproject.gradebookng.tool.model; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.sakaiproject.service.gradebook.shared.Assignment; +import org.sakaiproject.service.gradebook.shared.CategoryDefinition; + +@AllArgsConstructor +public class GbItem implements Serializable { + + private static final long serialVersionUID = 1L; + + @Getter + @Setter + private Long itemId; + + @Getter + @Setter + private CategoryDefinition categoryDefinition; + + @Getter + @Setter + private Assignment gradebookItem; + + @Getter + @Setter + private Double categoryPointsOrWeight; + + @Getter + @Setter + private Integer numGraded; +} diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/BasePage.java b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/BasePage.java index 08373b2dc2..234a995440 100644 --- a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/BasePage.java +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/BasePage.java @@ -170,6 +170,7 @@ public class BasePage extends WebPage { this.settingsPageLink.add(new Label("screenreaderlabel", getString("link.screenreader.tabnotselected"))); nav.add(this.settingsPageLink); + add(nav); // Add a FeedbackPanel for displaying our messages @@ -239,15 +240,19 @@ public class BasePage extends WebPage { * Helper to build a notification flag with a Bootstrap popover */ public WebMarkupContainer buildFlagWithPopover(final String componentId, final String message) { + return this.buildFlagWithPopover(componentId, message, "#gradebookGrades", "manual", "bottom"); + } + + public WebMarkupContainer buildFlagWithPopover(final String componentId, final String message, final String dataContainer, final String dataTrigger, final String dataPlacement) { final WebMarkupContainer flagWithPopover = new WebMarkupContainer(componentId); flagWithPopover.add(new AttributeModifier("title", message)); flagWithPopover.add(new AttributeModifier("aria-label", message)); flagWithPopover.add(new AttributeModifier("data-toggle", "popover")); - flagWithPopover.add(new AttributeModifier("data-trigger", "manual")); - flagWithPopover.add(new AttributeModifier("data-placement", "bottom")); + flagWithPopover.add(new AttributeModifier("data-trigger", dataTrigger)); + flagWithPopover.add(new AttributeModifier("data-placement", dataPlacement)); flagWithPopover.add(new AttributeModifier("data-html", "true")); - flagWithPopover.add(new AttributeModifier("data-container", "#gradebookGrades")); + flagWithPopover.add(new AttributeModifier("data-container", dataContainer)); flagWithPopover.add(new AttributeModifier("data-template", "
")); flagWithPopover.add(new AttributeModifier("data-content", generatePopoverContent(message))); diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/GradebookPage.html b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/GradebookPage.html index 3e54a2ecfb..c4b43432b3 100644 --- a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/GradebookPage.html +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/pages/GradebookPage.html @@ -24,6 +24,9 @@
+ +
+ + + + + + + diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/panels/GradebookItemsPanel.java b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/panels/GradebookItemsPanel.java new file mode 100644 index 0000000000..6eff9b88ef --- /dev/null +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/tool/panels/GradebookItemsPanel.java @@ -0,0 +1,404 @@ +package org.sakaiproject.gradebookng.tool.panels; + +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.behavior.AttributeAppender; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.head.CssHeaderItem; +import org.apache.wicket.markup.head.IHeaderResponse; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.LoadableDetachableModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.StringResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; +import org.sakaiproject.component.cover.ServerConfigurationService; +import org.sakaiproject.gradebookng.business.GradebookNgBusinessService; +import org.sakaiproject.gradebookng.business.util.FormatHelper; +import org.sakaiproject.gradebookng.tool.component.GbAjaxLink; +import org.sakaiproject.gradebookng.tool.component.GbFeedbackPanel; +import org.sakaiproject.gradebookng.tool.model.GbItem; +import org.sakaiproject.gradebookng.tool.model.GbModalWindow; +import org.sakaiproject.gradebookng.tool.pages.GradebookPage; +import org.sakaiproject.service.gradebook.shared.*; +import org.sakaiproject.gradebookng.business.model.GbStudentGradeInfo; +import org.sakaiproject.gradebookng.business.model.GbGradeInfo; + +import java.util.*; + +/** + * Created by David P. Bauer [dbauer1@udayton.edu] on 8/1/17. + */ +public class GradebookItemsPanel extends Panel { + private static final long serialVersionUID = 1L; + + private static final String ICON_SAKAI = "icon-sakai--"; + + private final GradingType gradingType; + + @SpringBean(name = "org.sakaiproject.gradebookng.business.GradebookNgBusinessService") + protected GradebookNgBusinessService businessService; + + private Double overAllPoints = 0D; + private final ModalWindow window; + + private boolean weightedCategories; + + public GradebookItemsPanel(final String id, final ModalWindow window) { + super(id); + this.window = window; + + this.weightedCategories = this.businessService.getGradebookSettings().getCategoryType() == GradebookService.CATEGORY_TYPE_WEIGHTED_CATEGORY; + + add(new GbFeedbackPanel("items-feedback")); + + this.gradingType = GradingType.valueOf(this.businessService.getGradebook().getGrade_type()); + } + + @Override + public void renderHead(final IHeaderResponse response) { + super.renderHead(response); + + final String version = ServerConfigurationService.getString("portal.cdn.version", ""); + + response.render(CssHeaderItem.forUrl(String.format("/gradebookng-tool/styles/gradebook-items.css?version=%s", version))); + } + + @Override + protected void onBeforeRender() { + super.onBeforeRender(); + + final IModel> loadableItemList = new LoadableDetachableModel>() { + private static final long serialVersionUID = 1L; + + @Override + protected List load() { + return getItemsList(); + } + }; + + final WebMarkupContainer itemListContainer = new WebMarkupContainer("item-list-container"); + itemListContainer.setOutputMarkupId(true); + add(itemListContainer); + + final ListView itemListView = new ListView("items", loadableItemList) { + private static final long serialVersionUID = 1L; + + int studentCount = businessService.getGradeableUsers().size(); + + @Override + protected void populateItem(ListItem item) { + final GbItem gbItem = item.getModelObject(); + + final Assignment assignment = gbItem.getGradebookItem(); + final CategoryDefinition categoryDefinition = gbItem.getCategoryDefinition(); + + final GradebookPage gradebookPage = (GradebookPage) getPage(); + + final WebMarkupContainer externalAppFlag = gradebookPage.buildFlagWithPopover("externalAppFlag", "", "#itemsPage", "focus", "right"); + if (assignment == null || StringUtils.isBlank(assignment.getExternalAppName())) { + externalAppFlag.setVisible(false); + } else { + externalAppFlag.add(new AttributeModifier("data-content", + gradebookPage.generatePopoverContent(new StringResourceModel("label.gradeitem.externalapplabel", + null, new Object[] { assignment.getExternalAppName() }).getString()))); + String iconClass = ICON_SAKAI + "default-tool"; + if ("Assignments".equals(assignment.getExternalAppName())) { + iconClass = ICON_SAKAI + "sakai-assignment-grades"; + } else if ("Tests & Quizzes".equals(assignment.getExternalAppName())) { + iconClass = ICON_SAKAI + "sakai-samigo"; + } else if ("Lesson Builder".equals(assignment.getExternalAppName())) { + iconClass = ICON_SAKAI + "sakai-lessonbuildertool"; + } else if ("Attendance".equals(assignment.getExternalAppName())) { + iconClass = ICON_SAKAI + "sakai-attendance"; + } + externalAppFlag + .add(new AttributeModifier("class", "gb-external-app-flag " + iconClass)); + } + item.add(externalAppFlag); + + GbAjaxLink editLink = new GbAjaxLink("editAssignmentDetails", Model.of(gbItem.getItemId())) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(final AjaxRequestTarget target) { + final GradebookPage gradebookPage = (GradebookPage) getPage(); + final GbModalWindow window = gradebookPage.getAddOrEditGradeItemWindow(); + window.setTitle(getString("heading.editgradeitem")); + AddOrEditGradeItemPanel addOrEditGradeItemPanel = new AddOrEditGradeItemPanel(window.getContentId(), window, getModel()); + addOrEditGradeItemPanel.setFromModalWindow(true); + window.setContent(addOrEditGradeItemPanel); + window.showUnloadConfirmation(false); + window.setWindowClosedCallback((ModalWindow.WindowClosedCallback) ajaxRequestTarget -> { + ajaxRequestTarget.add(itemListContainer); + ajaxRequestTarget.addChildren(GradebookItemsPanel.this, GbFeedbackPanel.class); + ajaxRequestTarget.appendJavaScript("$('#itemsPage').find('[data-toggle=\"popover\"]').popover();"); + }); + window.show(target); + } + + @Override + public boolean isEnabled() { + return assignment != null; + } + }; + editLink.add(new Label("name-label", assignment == null ? categoryDefinition.getName() : assignment.getName())); + + item.add(editLink); + + item.add(gradebookPage.buildFlagWithPopover("extraCreditFlag", getString("label.gradeitem.extracredit"), "#itemsPage", "focus", "bottom") + .setVisible(assignment != null && assignment.isExtraCredit())); + item.add(gradebookPage.buildFlagWithPopover("notCountedFlag", getString("label.gradeitem.notcounted"), "#itemsPage", "focus", "bottom") + .setVisible(assignment != null && !assignment.isCounted())); + item.add(gradebookPage.buildFlagWithPopover("notReleasedFlag", getString("label.gradeitem.notreleased"), "#itemsPage", "focus", "bottom") + .setVisible(assignment != null && !assignment.isReleased())); + + if (categoryDefinition != null) { + item.add(new AttributeModifier("data-category-id", categoryDefinition.getId())); + } + item.add(gradebookPage.buildFlagWithPopover("extraCreditCategoryFlag", getString("label.gradeitem.extracreditcategory"), "#itemsPage", "focus", "bottom") + .setVisible(categoryDefinition != null && Boolean.TRUE.equals(categoryDefinition.isExtraCredit()))); + item.add(gradebookPage.buildFlagWithPopover("dropLowestCategoryFlag", getString("label.gradeitem.droplowestcategory").replace("{0}", + String.valueOf(categoryDefinition != null ? categoryDefinition.getDrop_lowest() : "")), "#itemsPage", "focus", "bottom") + .setVisible(categoryDefinition != null && categoryDefinition.getDrop_lowest() != null && categoryDefinition.getDrop_lowest() > 0)); + item.add(gradebookPage.buildFlagWithPopover("dropHighestCategoryFlag", getString("label.gradeitem.drophighestcategory").replace("{0}", + String.valueOf(categoryDefinition != null ? categoryDefinition.getDropHighest() : "")), "#itemsPage", "focus", "bottom") + .setVisible(categoryDefinition != null && categoryDefinition.getDropHighest() != null && categoryDefinition.getDropHighest() > 0)); + item.add(gradebookPage.buildFlagWithPopover("keepHighestCategoryFlag", getString("label.gradeitem.keephighestcategory").replace("{0}", + String.valueOf(categoryDefinition != null ? categoryDefinition.getKeepHighest() : "")), "#itemsPage", "focus", "bottom") + .setVisible(categoryDefinition != null && categoryDefinition.getKeepHighest() != null && categoryDefinition.getKeepHighest() > 0)); + + item.add(new GbAjaxLink("viewAssignmentGradeStatistics", Model.of(gbItem.getItemId())) { + private static final long serialVersionUID = 1L; + @Override + public void onClick(final AjaxRequestTarget target) { + final GradebookPage gradebookPage = (GradebookPage) getPage(); + final GbModalWindow window = gradebookPage.getGradeStatisticsWindow(); + window.setComponentToReturnFocusTo(this); + window.setContent(new GradeStatisticsPanel(window.getContentId(), getModel(), window)); + window.setWindowClosedCallback((ModalWindow.WindowClosedCallback) ajaxRequestTarget -> { + ajaxRequestTarget.add(itemListContainer); + ajaxRequestTarget.addChildren(GradebookItemsPanel.this, GbFeedbackPanel.class); + ajaxRequestTarget.appendJavaScript("$('#itemsPage').find('[data-toggle=\"popover\"]').popover();"); + }); + window.show(target); + } + + @Override + public boolean isVisible() { + return assignment != null; + } + }); + + WebMarkupContainer numberGradedCol = new WebMarkupContainer("number-graded"); + Label numberGradedLabel = new Label("number-graded-label", (gbItem.getNumGraded() + " / " + studentCount)) { + @Override + public boolean isVisible() { + return assignment != null; + } + }; + if (assignment != null && gbItem.getNumGraded() < studentCount) { + numberGradedCol.add(new AttributeAppender("class", " ungradedStudents")); + } + numberGradedCol.add(numberGradedLabel); + item.add(numberGradedCol); + + if (assignment != null) { + // We know this is an assignment + item.add(new Label("out-of-label", assignment.getPoints())); + final List allGrades = new ArrayList<>(); + final List gradeInfo = businessService.buildGradeMatrix(Collections.singletonList(assignment)); + for (final GbStudentGradeInfo studentGradeInfo : gradeInfo) { + final Map studentGrades = studentGradeInfo.getGrades(); + final GbGradeInfo grade = studentGrades.get(gbItem.getItemId()); + if (grade != null && grade.getGrade() != null) { + allGrades.add(Double.valueOf(grade.getGrade())); + } + } + if (allGrades.size() > 0) { + item.add(new Label("average-label", constructAverageLabel(allGrades, assignment))); + } else { + item.add(new Label("average-label", "-")); + } + } else { + // This item is a category + String categoryPointsOrWeight; + if (categoryDefinition.getId() == -1) { + categoryPointsOrWeight = "-"; + item.add(new AttributeAppender("style", "background: #e6e6e6;")); + } else { + categoryPointsOrWeight = GradebookItemsPanel.this.weightedCategories ? FormatHelper.formatDoubleAsPercentage(gbItem.getCategoryPointsOrWeight() * 100) : FormatHelper.formatDoubleToDecimal(gbItem.getCategoryPointsOrWeight()); + if (categoryDefinition.isExtraCredit()) { + categoryPointsOrWeight = "+" + categoryPointsOrWeight; + } + } + item.add(new Label("out-of-label", categoryPointsOrWeight)); + item.add(new Label("average-label", "").setVisible(false)); + item.add(new AttributeAppender("class", "categoryRow")); + } + + item.add(new GbAjaxLink("deleteGradeItem", Model.of(gbItem.getItemId())) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(final AjaxRequestTarget target) { + + final GradebookPage gradebookPage = (GradebookPage) getPage(); + final GbModalWindow window = gradebookPage.getDeleteItemWindow(); + final DeleteItemPanel deleteItemPanel = new DeleteItemPanel(window.getContentId(), getModel(), window); + deleteItemPanel.setFromModalWindow(true); + window.setTitle(getString("delete.label")); + window.setComponentToReturnFocusTo(this); + window.setContent(deleteItemPanel); + window.showUnloadConfirmation(false); + window.setWindowClosedCallback((ModalWindow.WindowClosedCallback) ajaxRequestTarget -> { + ajaxRequestTarget.add(itemListContainer); + ajaxRequestTarget.addChildren(GradebookItemsPanel.this, GbFeedbackPanel.class); + ajaxRequestTarget.appendJavaScript("$('#itemsPage').find('[data-toggle=\"popover\"]').popover();"); + }); + + window.show(target); + } + + @Override + public boolean isVisible() { + return assignment != null && StringUtils.isBlank(assignment.getExternalAppName()); + } + }); + + } + }; + itemListContainer.add(itemListView); + + WebMarkupContainer totalPtsContainer = new WebMarkupContainer("total-points-container") { + @Override + public boolean isVisible() { + return !GradebookItemsPanel.this.weightedCategories; + } + }; + itemListContainer.add(totalPtsContainer); + + totalPtsContainer.add(new Label("total-points", GradebookItemsPanel.this.overAllPoints)); + + add(new GbAjaxLink("done") { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(final AjaxRequestTarget target) { + GradebookItemsPanel.this.window.close(target); + } + }); + } + + private int countNumberofGradedAssignments(List grades, long assignmentId){ + int gradedCounter = 0; + for(int q = 0; q < grades.size(); q++){ + final GbGradeInfo gradeInfo = grades.get(q).getGrades().get(assignmentId); + if(gradeInfo != null){ + if(gradeInfo.getGrade() != null){ + gradedCounter++; + } + } + } + return gradedCounter; + } + + private List getItemsList() { + SortType sortBy = SortType.SORT_BY_SORTING; + + final List itemList = new ArrayList<>(); + + if (this.businessService.categoriesAreEnabled()) { + + sortBy = SortType.SORT_BY_CATEGORY; + + // Returns a sorted list of all categories in the Gradebook + final List categories = this.businessService.getGradebookCategories(); + + for (CategoryDefinition categoryDefinition : categories) { + + Double totalCategoryPoints = 0D; + + // Get sorted list of assignments for the category. + final List assignmentList = this.businessService.getGradebookAssignmentsForCategory(categoryDefinition.getId(), sortBy); + final List grades = this.businessService.buildGradeMatrix(assignmentList); + final List tempList = new ArrayList<>(); + + int numberToDrop = 0; + int numberToKeep = assignmentList.size(); + + if ((categoryDefinition.getDropHighest() != null && categoryDefinition.getDropHighest() > 0) + || categoryDefinition.getDrop_lowest() != null && categoryDefinition.getDrop_lowest() > 0) { + numberToDrop = categoryDefinition.getDrop_lowest() + categoryDefinition.getDropHighest(); + } else if (categoryDefinition.getKeepHighest() != null && categoryDefinition.getKeepHighest() > 0) { + numberToKeep = categoryDefinition.getKeepHighest(); + } + + for (Assignment assignment : assignmentList) { + tempList.add(new GbItem(assignment.getId(), null, assignment, null, countNumberofGradedAssignments(grades, assignment.getId()))); + + if (assignment.isCounted() && !assignment.isExtraCredit()) { + if (numberToDrop == 0 && numberToKeep > 0) { + totalCategoryPoints += assignment.getPoints(); + if (!categoryDefinition.isExtraCredit()) { + GradebookItemsPanel.this.overAllPoints = GradebookItemsPanel.this.overAllPoints + assignment.getPoints(); + } + numberToKeep--; + } else if (numberToDrop > 0) { + numberToDrop--; + } + } + } + // Add Category itself to list + itemList.add(new GbItem(categoryDefinition.getId(), categoryDefinition, null, weightedCategories ? categoryDefinition.getWeight() : totalCategoryPoints, null)); + // Add all assignments in the category + itemList.addAll(tempList); + } + final List uncategorizedAssignments = this.businessService.getGradebookAssignmentsForCategory(null, sortBy); + if (uncategorizedAssignments != null && !uncategorizedAssignments.isEmpty()) { + final List uncategorizedGbItems = new ArrayList<>(); + final List grades = this.businessService.buildGradeMatrix(uncategorizedAssignments); + for (Assignment assignment : uncategorizedAssignments) { + uncategorizedGbItems.add(new GbItem(assignment.getId(), null, assignment, null, countNumberofGradedAssignments(grades, assignment.getId()))); + } + final CategoryDefinition uncategorized = new CategoryDefinition(); + uncategorized.setId(-1L); + uncategorized.setName("Uncategorized"); + // Add the "Uncategorized" category + itemList.add(new GbItem(uncategorized.getId(), uncategorized, null, 0D, null)); + // Add all uncategorized items + itemList.addAll(uncategorizedGbItems); + } + } else { + // Categories are not enabled so just add all assignments to the list. + final List allAssignments = this.businessService.getGradebookAssignments(sortBy); + final List grades = this.businessService.buildGradeMatrix(allAssignments); + for (final Assignment assignment : allAssignments) { + itemList.add(new GbItem(assignment.getId(), null, assignment, null, countNumberofGradedAssignments(grades, assignment.getId()))); + if (assignment.isCounted() && !assignment.isExtraCredit()) { + GradebookItemsPanel.this.overAllPoints += assignment.getPoints(); + } + } + } + return itemList; + } + private String constructAverageLabel(final List allGrades, final Assignment assignment) { + final double average = calculateAverage(allGrades); + + final Double total = assignment.getPoints(); + return FormatHelper.formatDoubleAsPercentage(100 * (average / total)); + } + private double calculateAverage(final List allGrades) { + double sum = 0; + for (Double grade : allGrades) { + sum += grade; + } + return sum / allGrades.size(); + } + +} diff --git a/gradebookng/tool/src/webapp/styles/gradebook-grades.css b/gradebookng/tool/src/webapp/styles/gradebook-grades.css index be5fc5332c..f6921e9634 100644 --- a/gradebookng/tool/src/webapp/styles/gradebook-grades.css +++ b/gradebookng/tool/src/webapp/styles/gradebook-grades.css @@ -519,4 +519,4 @@ div.wicket-modal div.w_right > div { #gradebookGrades .gb-student-number-cell .gb-title { text-align: left; -} \ No newline at end of file +} diff --git a/gradebookng/tool/src/webapp/styles/gradebook-items.css b/gradebookng/tool/src/webapp/styles/gradebook-items.css new file mode 100644 index 0000000000..78389bdc89 --- /dev/null +++ b/gradebookng/tool/src/webapp/styles/gradebook-items.css @@ -0,0 +1,107 @@ +/* **************************************************************** * + * Gradebook Items styles * + * **************************************************************** */ + +#itemsPage [class*="gb-flag"] { + padding: 0 4px; + text-decoration: none; +} + +#itemsPage .itemsTable thead tr th { + background: #F0f0f0; +} + +#itemsPage .itemsTable td.nameColumn { + padding-left: 4em; +} + +#itemsPage .itemsTable tr.categoryRow { + background: #bfedff; + border-top: 4px solid #ddd; +} + +#itemsPage .itemsTable tr td { + vertical-align: middle; +} + +#itemsPage .itemsTable tr.categoryRow td.nameColumn { + padding-left: 8px; +} + +#itemsPage .itemsTable tr.categoryRow td.totalColumn { + color: #777; +} + +#itemsPage .itemsTable tr.categoryRow td, #itemsPage .itemsTable td.totalPoints { + text-shadow: 1px 1px 2px #FFF; + font-weight: normal; + line-height: 16px; + font-size: 16px; +} + +#itemsPage .itemsTable td.totalPoints { + color: #777; +} + +#itemsPage .itemsTable td.ungradedStudents { + color: #a94442; + font-weight: bold; +} + +#itemsPage .itemsTable div.itemAverage { + display: inline-block; + width: 30%; + padding: 0 4px; +} + +#itemsPage span.gb-external-app-flag { + margin-left: -20px; +} + +#itemsPage .gb-category-extra-credit:before { + font-family: 'gradebook-icons'; + content: '\f0fe'; + vertical-align: bottom; + margin-right: 4px; + color: #999; +} + +#itemsPage .gb-category-drop-lowest:before { + font-family: 'FontAwesome'; + content: '\f0ab'; + vertical-align: bottom; + margin-right: 4px; + color: #999; +} + +#itemsPage .gb-category-drop-highest:before { + font-family: 'FontAwesome'; + content: '\f0ab'; + vertical-align: bottom; + margin-right: 4px; + color: #999; +} + +#itemsPage .gb-category-keep-highest:before { + font-family: 'FontAwesome'; + content: '\f0aa'; + vertical-align: bottom; + margin-right: 4px; + color: #999; +} + +#itemsPage .gb-flag-delete:before { + font-family: 'FontAwesome'; + content: '\f014'; + color: #a94442; + font-size: 16px; +} + +#itemsPage .gb-flag-statistics:before { + font-family: 'FontAwesome'; + content: '\f201'; +} + +#itemsPage .gb-flag-delete:hover, #itemsPage .gb-flag-delete:focus{ + color: #843534; +} \ No newline at end of file