diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplate.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplate.java index 7f3e831825..0310b28dd0 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplate.java +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplate.java @@ -11,9 +11,11 @@ import java.util.List; class EditingGradingTemplate implements Serializable { private String note; private List<Criteria> criteria; + private GradeLimits gradeLimits; EditingGradingTemplate(GradingReportTemplate template) { this.note = ""; + this.gradeLimits = new GradeLimits(); this.criteria = new ArrayList<>(); for (var criteria : template.getCriteria()) { Criteria editingCriteria = new Criteria(criteria); @@ -29,10 +31,20 @@ class EditingGradingTemplate implements Serializable { this.note = note; } + public GradeLimits getGradeLimits() { + return gradeLimits; + } + public List<Criteria> getCriteria() { return criteria; } + public int getMaxPointsAvailable() { + return criteria.stream() + .mapToInt(Criteria::getMaxPoints) + .sum(); + } + class Criteria implements Serializable { enum Flag { OPPOSITION, REFLECTION @@ -78,6 +90,10 @@ class EditingGradingTemplate implements Serializable { this.flag = flag; } + public int getMaxPoints() { + return points.size(); + } + public List<Point> getPoints() { return points; } diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.html b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.html index 4106b664e9..e6d55f0e0d 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.html +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.html @@ -20,6 +20,38 @@ </small> </div> + <fieldset wicket:id="grade_limits" class="line-length-limit"> + <legend>Grade limits</legend> + <p> + The order in which you specify the grade limits does not matter. + The authors will receive the grade associated with the highest minimum point requirement they met. + </p> + <div class="mb-3"> + <label class="form-label" wicket:for="default_grade">Default grade</label> + <input type="text" class="form-control" wicket:id="default_grade"> + <small class="text-muted">The grade they receive if they do not meet the minimum points for any other grade.</small> + </div> + + <wicket:container wicket:id="grade_limits"> + <div class="row align-items-center mb-3" wicket:id="grade_limit"> + <div class="col"><label class="form-label" wicket:for="minimum">Minimum points</label></div> + <div class="col"><input type="number" class="form-control" min="1" wicket:id="minimum"></div> + <div class="col"><label class="form-label">Grade</label></div> + <div class="col"><input type="text" class="form-control" wicket:id="grade"></div> + <div class="col-auto"><button class="btn btn-sm btn-outline-danger" wicket:id="remove">Remove</button></div> + </div> + </wicket:container> + <div class="mb-3"> + <button class="btn btn-sm btn-outline-success" wicket:id="add">Add new grade</button> + </div> + </fieldset> + + <p class="mb-3"> + <wicket:message key="max_points_available"> + The maximum number of points available is <strong wicket:id="max_points_available">8</strong> with the below criteria. + </wicket:message> + </p> + <div class="mb-3 line-length-limit card" wicket:id="criteria"> <div class="card-header text-bg-info text-white"> <h3 class="text-white mb-0">Criteria 1</h3> diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.java index 5e6e081214..99bd10468b 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.java @@ -8,6 +8,7 @@ import org.apache.wicket.markup.html.GenericWebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.EnumChoiceRenderer; import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.NumberTextField; import org.apache.wicket.markup.html.form.TextArea; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.list.ListItem; @@ -35,6 +36,10 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe } }); + add(new GradeLimitsPanel("grade_limits", editingGradingTemplateModel.map(EditingGradingTemplate::getGradeLimits))); + + add(new Label("max_points_available", editingGradingTemplateModel.map(EditingGradingTemplate::getMaxPointsAvailable))); + add(new ListView<>("criteria", editingGradingTemplateModel.map(EditingGradingTemplate::getCriteria)) { { setReuseItems(true); @@ -153,9 +158,72 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe } } + private static class GradeLimitsPanel extends GenericWebMarkupContainer<GradeLimits> { + public GradeLimitsPanel(String id, IModel<GradeLimits> model) { + super(id, model); + + setOutputMarkupId(true); + + add(new TextField<>("default_grade", LambdaModel.of( + model, + GradeLimits::getDefaultGrade, + GradeLimits::setDefaultGrade)) { + { + add(new AutoSave()); + } + }); + + add(new ListView<>("grade_limits", model.map(GradeLimits::getGradeLimits)) { + @Override + protected void populateItem(ListItem<GradeLimits.GradeLimit> item) { + item.add(new GradeLimitEditingPanel("grade_limit", item.getModel())); + } + }); + + add(new AjaxLink<>("add") { + @Override + public void onClick(AjaxRequestTarget target) { + GradeLimits gradeLimits = GradeLimitsPanel.this.getModelObject(); + gradeLimits.addNewLimit(); + target.add(GradeLimitsPanel.this); + } + }); + } + + private class GradeLimitEditingPanel extends GenericWebMarkupContainer<GradeLimits.GradeLimit> { + public GradeLimitEditingPanel(String id, IModel<GradeLimits.GradeLimit> model) { + super(id, model); + add(new NumberTextField<>("minimum", LambdaModel.of( + model, + GradeLimits.GradeLimit::getLowerLimit, + GradeLimits.GradeLimit::setLowerLimit), Integer.class) { + { + add(new AutoSave()); + } + }); + add(new TextField<>("grade", LambdaModel.of( + model, + GradeLimits.GradeLimit::getGrade, + GradeLimits.GradeLimit::setGrade)) { + { + add(new AutoSave()); + } + }); + add(new AjaxLink<>("remove") { + @Override + public void onClick(AjaxRequestTarget target) { + GradeLimits gradeLimits = GradeLimitsPanel.this.getModelObject(); + gradeLimits.getGradeLimits().remove(model.getObject()); + target.add(GradeLimitsPanel.this); + } + }); + } + } + } + private static class AutoSave extends AjaxFormComponentUpdatingBehavior { public AutoSave() { - super("keyup"); + super("input"); } @Override diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.utf8.properties b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.utf8.properties index 32c9d23c88..e64928d8c4 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.utf8.properties +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/EditingGradingTemplateComponentPanel.utf8.properties @@ -1,2 +1,3 @@ Flag.OPPOSITION=Final seminar opposition Flag.REFLECTION=Reflection +max_points_available=The maximum number of points available is ${max_points_available} with the below criteria. diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/GradeLimits.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/GradeLimits.java new file mode 100644 index 0000000000..bbdaba16f5 --- /dev/null +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/GradeLimits.java @@ -0,0 +1,52 @@ +package se.su.dsv.scipro.admin.pages.grading; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +class GradeLimits implements Serializable { + private List<GradeLimit> gradeLimits; + private String defaultGrade; + + GradeLimits() { + this.gradeLimits = new ArrayList<>(); + this.gradeLimits.add(new GradeLimit()); + } + + void addNewLimit() { + getGradeLimits().add(new GradeLimit()); + } + + public String getDefaultGrade() { + return defaultGrade; + } + + public void setDefaultGrade(String defaultGrade) { + this.defaultGrade = defaultGrade; + } + + public List<GradeLimit> getGradeLimits() { + return gradeLimits; + } + + class GradeLimit implements Serializable { + private String grade; + private int lowerLimit; + + public String getGrade() { + return grade; + } + + public void setGrade(String grade) { + this.grade = grade; + } + + public int getLowerLimit() { + return lowerLimit; + } + + public void setLowerLimit(int lowerLimit) { + this.lowerLimit = lowerLimit; + } + } +}