From 4b113715d64b19427226a854ac878a1452a96bca Mon Sep 17 00:00:00 2001 From: Nico Athanassiadis Date: Wed, 13 Nov 2024 14:30:22 +0100 Subject: [PATCH 01/16] User alert on unsaved changes in grading template Grading template did not have any way to alert the user that changes had been made when editing a template. Added a way to detect and alert the user when changes have been made on the grading template they are editing. If the user removes his changes, so the template is in the same state as it was when the user started editing the template the alert will disappear. --- .../grading/AdminGradingTemplateEditPage.html | 5 +- .../grading/AdminGradingTemplateEditPage.java | 28 +++++++-- .../pages/grading/EditingGradingTemplate.java | 58 +++++++++++++++++++ .../EditingGradingTemplateComponentPanel.java | 17 +++++- .../admin/pages/grading/GradeLimits.java | 26 +++++++++ .../grading/wicket-package.utf8.properties | 1 + 6 files changed, 128 insertions(+), 7 deletions(-) diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.html b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.html index 9e28766880..626408b739 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.html +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.html @@ -5,8 +5,11 @@
-
+
+ + +
diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java index da4a0b42a7..c255d1be51 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java @@ -2,9 +2,10 @@ package se.su.dsv.scipro.admin.pages.grading; import jakarta.inject.Inject; import org.apache.wicket.RestartResponseException; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.panel.FeedbackPanel; -import org.apache.wicket.model.Model; import org.apache.wicket.request.mapper.parameter.PageParameters; import se.su.dsv.scipro.admin.pages.AbstractAdminProjectPage; import se.su.dsv.scipro.grading.GradingReportTemplateService; @@ -12,9 +13,9 @@ import se.su.dsv.scipro.grading.GradingReportTemplateUpdate; import se.su.dsv.scipro.grading.LocalizedString; import se.su.dsv.scipro.report.DuplicateDateException; import se.su.dsv.scipro.report.GradingReportTemplate; -import se.su.dsv.scipro.report.ValidDateMustBeInTheFutureException; import se.su.dsv.scipro.report.NoSuchTemplateException; import se.su.dsv.scipro.report.TemplateLockedException; +import se.su.dsv.scipro.report.ValidDateMustBeInTheFutureException; import java.util.ArrayList; import java.util.List; @@ -25,6 +26,8 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple 0, new LocalizedString("", "")); + private final WebMarkupContainer unsavedChangesAlert; + @Inject GradingReportTemplateService gradingReportTemplateService; @@ -47,7 +50,8 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple GradingReportTemplateUpdate update = toUpdate( editingGradingTemplate); - gradingReportTemplateService.update(id, update); + GradingReportTemplate newTemplate = gradingReportTemplateService.update(id, update); + editingGradingTemplate = new EditingGradingTemplate(newTemplate); success(getString("template_updated")); } catch (ValidDateMustBeInTheFutureException e) { error(getString("valid_from_must_be_in_the_future", () -> e)); @@ -61,7 +65,23 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple } }; - form.add(new EditingGradingTemplateComponentPanel("editing", Model.of(editingGradingTemplate))); + unsavedChangesAlert = new WebMarkupContainer("unsaved_changes_alert") { + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(editingGradingTemplate.hasChanges()); + } + }; + form.add(unsavedChangesAlert); + unsavedChangesAlert.setOutputMarkupPlaceholderTag(true); + + form.add(new EditingGradingTemplateComponentPanel("editing", () -> editingGradingTemplate) { + @Override + protected void onTemplateChanged(AjaxRequestTarget target) { + super.onTemplateChanged(target); + target.add(unsavedChangesAlert); + } + }); add(form); } 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 7e4e935ad5..04f6402920 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 @@ -8,8 +8,10 @@ import java.io.Serializable; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import java.util.Objects; class EditingGradingTemplate implements Serializable { + private EditingGradingTemplate original; private String note; private LocalDate validFrom; private List criteria; @@ -21,6 +23,16 @@ class EditingGradingTemplate implements Serializable { } EditingGradingTemplate(GradingReportTemplate template) { + this(template, null); + this.original = new EditingGradingTemplate(template, null); + } + + /** + * Private constructor for creating a new instance of EditingGradingTemplate + * to be able to track changes made. + * @param doNotCreateOriginal Only exists to differentiate the signature from the public constructor + */ + private EditingGradingTemplate(GradingReportTemplate template, @SuppressWarnings("unused") Void doNotCreateOriginal) { this.note = template.getNote(); this.validFrom = template.getValidFrom(); this.gradeLimits = new GradeLimits(template); @@ -61,10 +73,28 @@ class EditingGradingTemplate implements Serializable { .sum(); } + public Boolean hasChanges() { + return !Objects.equals(original, this); + } + public void addCriteria() { this.criteria.add(new Criteria()); } + @Override + public boolean equals(Object o) { + return o instanceof EditingGradingTemplate that + && Objects.equals(note, that.note) + && Objects.equals(validFrom, that.validFrom) + && Objects.equals(criteria, that.criteria) + && Objects.equals(gradeLimits, that.gradeLimits); + } + + @Override + public int hashCode() { + return Objects.hash(note, validFrom, criteria, gradeLimits); + } + class Criteria implements Serializable { enum Flag { OPPOSITION, REFLECTION @@ -150,6 +180,22 @@ class EditingGradingTemplate implements Serializable { this.pointsRequiredToPass = pointsRequiredToPass; } + @Override + public boolean equals(Object o) { + return o instanceof Criteria criterion + && pointsRequiredToPass == criterion.pointsRequiredToPass + && Objects.equals(titleSv, criterion.titleSv) + && Objects.equals(titleEn, criterion.titleEn) + && Objects.equals(points, criterion.points) + && flag == criterion.flag + && type == criterion.type; + } + + @Override + public int hashCode() { + return Objects.hash(titleSv, titleEn, points, flag, type, pointsRequiredToPass); + } + class Point implements Serializable { private String requirementEn; private String requirementSv; @@ -179,6 +225,18 @@ class EditingGradingTemplate implements Serializable { public void setRequirementSv(String requirementSv) { this.requirementSv = requirementSv; } + + @Override + public boolean equals(Object o) { + return o instanceof Point point + && Objects.equals(requirementEn, point.requirementEn) + && Objects.equals(requirementSv, point.requirementSv); + } + + @Override + public int hashCode() { + return Objects.hash(requirementEn, requirementSv); + } } } } 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 fb6b0af006..5980e6834c 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 @@ -64,6 +64,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel { + private class GradeLimitsPanel extends GenericWebMarkupContainer { public GradeLimitsPanel(String id, IModel model) { super(id, model); @@ -248,6 +254,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel gradeLimits; @@ -41,6 +42,19 @@ class GradeLimits implements Serializable { return gradeLimits; } + @Override + public boolean equals(Object o) { + + return o instanceof GradeLimits that + && Objects.equals(gradeLimits, that.gradeLimits) + && Objects.equals(failingGrade, that.failingGrade); + } + + @Override + public int hashCode() { + return Objects.hash(gradeLimits, failingGrade); + } + class GradeLimit implements Serializable { private String grade; private int lowerLimit; @@ -60,5 +74,17 @@ class GradeLimits implements Serializable { public void setLowerLimit(int lowerLimit) { this.lowerLimit = lowerLimit; } + + @Override + public boolean equals(Object o) { + return o instanceof GradeLimit that + && lowerLimit == that.lowerLimit + && Objects.equals(grade, that.grade); + } + + @Override + public int hashCode() { + return Objects.hash(grade, lowerLimit); + } } } diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/wicket-package.utf8.properties b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/wicket-package.utf8.properties index f761f20e4e..25726d2d64 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/wicket-package.utf8.properties +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/wicket-package.utf8.properties @@ -3,3 +3,4 @@ valid_from_must_be_in_the_future=The templates valid date must be in the future. another_template_exists_for_the_given_date_date=There is already another ${projectType.name} template that becomes valid at ${validFrom}, please pick another date. template_is_locked=You can not edit templates that have become current. The template you are trying to edit became current at ${validFrom}. template_created=New template for ${name} created. +unsaved_changes=The grading template has been changed, unsaved changes will be lost if you do not save. -- 2.39.5 From ea54958e71bc50134df39dcefdf5d50f87a8a7cd Mon Sep 17 00:00:00 2001 From: Nico Athanassiadis Date: Tue, 19 Nov 2024 07:10:18 +0100 Subject: [PATCH 02/16] Added project type title when viewing or editing When you chose to edit a template you could not see what type the template is. For example if it was a bachelor or master type template. Now when you choose to edit a grading template the type will be shown as a heading, so you can more easily see what type of template you are currently editing. The heading will read: `You are editing a grading template.` The will display the correct type of the grading template you are editing. Open to change of what exactly the heading will display if anyone has a better idea for it. --- .../admin/pages/grading/EditingGradingTemplate.java | 9 ++++++++- .../grading/EditingGradingTemplateComponentPanel.html | 6 ++++++ .../grading/EditingGradingTemplateComponentPanel.java | 1 + .../EditingGradingTemplateComponentPanel.utf8.properties | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) 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 04f6402920..1202d83137 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 @@ -16,6 +16,7 @@ class EditingGradingTemplate implements Serializable { private LocalDate validFrom; private List criteria; private GradeLimits gradeLimits; + private String projectType; public EditingGradingTemplate() { this.gradeLimits = new GradeLimits(); @@ -41,6 +42,7 @@ class EditingGradingTemplate implements Serializable { Criteria editingCriteria = new Criteria(criteria); this.criteria.add(editingCriteria); } + this.projectType = template.getProjectType().getName(); } public String getNote() { @@ -81,13 +83,18 @@ class EditingGradingTemplate implements Serializable { this.criteria.add(new Criteria()); } + public String getProjectType() { + return projectType; + } + @Override public boolean equals(Object o) { return o instanceof EditingGradingTemplate that && Objects.equals(note, that.note) && Objects.equals(validFrom, that.validFrom) && Objects.equals(criteria, that.criteria) - && Objects.equals(gradeLimits, that.gradeLimits); + && Objects.equals(gradeLimits, that.gradeLimits) + && Objects.equals(projectType, that.projectType); } @Override 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 80952a8f02..f4ea4e67dc 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 @@ -9,6 +9,12 @@ +
+ + + +
+