Squash and fix migrations so they run against an empty schema #24
|
@ -105,11 +105,11 @@ public class Idea extends DomainObject {
|
|||
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "literature", column = @Column(name = "literature", insertable = false, updatable = false)),
|
||||
@AttributeOverride(name = "background", column = @Column(name = "background", insertable = false, updatable = false)),
|
||||
@AttributeOverride(name = "problem", column = @Column(name = "problem", insertable = false, updatable = false)),
|
||||
@AttributeOverride(name = "method", column = @Column(name = "method", insertable = false, updatable = false)),
|
||||
@AttributeOverride(name = "interests", column = @Column(name = "interests", insertable = false, updatable = false))
|
||||
@AttributeOverride(name = "literature", column = @Column(name = "literature")),
|
||||
@AttributeOverride(name = "background", column = @Column(name = "background")),
|
||||
@AttributeOverride(name = "problem", column = @Column(name = "problem")),
|
||||
@AttributeOverride(name = "method", column = @Column(name = "method")),
|
||||
@AttributeOverride(name = "interests", column = @Column(name = "interests"))
|
||||
})
|
||||
private TholanderBox tholanderBox = new TholanderBox();
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
<div wicket:id="grading_template_component_panel"></div>
|
||||
|
||||
<div class="position-sticky bottom-0 bg-white p-3 border line-length-limit">
|
||||
<div wicket:id="button_container" class="position-sticky bottom-0 bg-white p-3 border line-length-limit">
|
||||
<button type="submit" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -3,6 +3,7 @@ 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.form.LambdaChoiceRenderer;
|
||||
import org.apache.wicket.markup.html.panel.FeedbackPanel;
|
||||
|
@ -29,6 +30,7 @@ public class AdminGradingTemplateCreationPage extends AbstractAdminProjectPage i
|
|||
|
||||
private final IModel<ProjectType> projectTypeModel;
|
||||
private EditingGradingTemplate editingGradingTemplateModel;
|
||||
private final WebMarkupContainer buttonContainer;
|
||||
|
||||
public AdminGradingTemplateCreationPage() {
|
||||
projectTypeModel = new DetachableServiceModel<>(projectTypeService);
|
||||
|
@ -57,6 +59,11 @@ public class AdminGradingTemplateCreationPage extends AbstractAdminProjectPage i
|
|||
form.setOutputMarkupId(true);
|
||||
add(form);
|
||||
|
||||
buttonContainer = new WebMarkupContainer("button_container");
|
||||
buttonContainer.setOutputMarkupPlaceholderTag(true);
|
||||
buttonContainer.setVisible(false);
|
||||
form.add(buttonContainer);
|
||||
|
||||
form.add(new AjaxDropDownChoice<>(
|
||||
"project_type",
|
||||
projectTypeModel,
|
||||
|
@ -64,7 +71,8 @@ public class AdminGradingTemplateCreationPage extends AbstractAdminProjectPage i
|
|||
new LambdaChoiceRenderer<>(ProjectType::getName, ProjectType::getId)) {
|
||||
@Override
|
||||
public void onNewSelection(AjaxRequestTarget target, ProjectType objectSelected) {
|
||||
target.add(form);
|
||||
buttonContainer.setVisible(true);
|
||||
target.add(form, buttonContainer);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -3,10 +3,18 @@
|
|||
<body>
|
||||
<wicket:extend>
|
||||
<div wicket:id="feedback"></div>
|
||||
<div class="mb-3 lead">
|
||||
<wicket:message key="project_type_name_editing">
|
||||
<span wicket:id="project_type_name"></span>
|
||||
</wicket:message>
|
||||
</div>
|
||||
<form wicket:id="form">
|
||||
<div wicket:id="editing" class="mb-3"></div>
|
||||
<div class="position-sticky bottom-0 bg-white p-3 border line-length-limit">
|
||||
<div class="position-sticky bottom-0 bg-white p-3 border line-length-limit hstack">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<span wicket:id="unsaved_changes_alert" class="text-danger flex-grow-1 text-center" role="alert">
|
||||
<wicket:message key="unsaved_changes"/>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</wicket:extend>
|
||||
|
|
|
@ -2,9 +2,13 @@ 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.basic.Label;
|
||||
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.model.IModel;
|
||||
import org.apache.wicket.model.LoadableDetachableModel;
|
||||
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 +16,10 @@ 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 se.su.dsv.scipro.system.ProjectType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -25,6 +30,8 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
|
|||
0,
|
||||
new LocalizedString("", ""));
|
||||
|
||||
private final WebMarkupContainer unsavedChangesAlert;
|
||||
|
||||
@Inject
|
||||
GradingReportTemplateService gradingReportTemplateService;
|
||||
|
||||
|
@ -38,6 +45,8 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
|
|||
editingGradingTemplate = new EditingGradingTemplate(template);
|
||||
|
||||
add(new FeedbackPanel("feedback"));
|
||||
IModel<GradingReportTemplate> model = LoadableDetachableModel.of(() -> gradingReportTemplateService.getTemplate(id));
|
||||
add(new Label("project_type_name", model.map(GradingReportTemplate::getProjectType).map(ProjectType::getName)));
|
||||
|
||||
Form<EditingGradingTemplate> form = new Form<>("form") {
|
||||
@Override
|
||||
|
@ -47,7 +56,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 +71,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,15 @@ 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> criteria;
|
||||
private GradeLimits gradeLimits;
|
||||
private String projectType;
|
||||
|
||||
public EditingGradingTemplate() {
|
||||
this.gradeLimits = new GradeLimits();
|
||||
|
@ -21,6 +24,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);
|
||||
|
@ -29,6 +42,7 @@ class EditingGradingTemplate implements Serializable {
|
|||
Criteria editingCriteria = new Criteria(criteria);
|
||||
this.criteria.add(editingCriteria);
|
||||
}
|
||||
this.projectType = template.getProjectType().getName();
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
|
@ -61,8 +75,34 @@ class EditingGradingTemplate implements Serializable {
|
|||
.sum();
|
||||
}
|
||||
|
||||
public Boolean hasChanges() {
|
||||
return !Objects.equals(original, this);
|
||||
}
|
||||
|
||||
public void addCriteria() {
|
||||
this.criteria.add(new Criteria());
|
||||
Criteria newCriteria = new Criteria();
|
||||
newCriteria.points.add(newCriteria.new Point());
|
||||
this.criteria.add(newCriteria);
|
||||
|
||||
}
|
||||
|
||||
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(projectType, that.projectType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(note, validFrom, criteria, gradeLimits);
|
||||
}
|
||||
|
||||
class Criteria implements Serializable {
|
||||
|
@ -79,14 +119,14 @@ class EditingGradingTemplate implements Serializable {
|
|||
private List<Point> points = new ArrayList<>();
|
||||
private Flag flag;
|
||||
private Type type = Type.PROJECT;
|
||||
private int pointsRequiredToPass;
|
||||
private int pointsRequiredToPass = 1;
|
||||
|
||||
Criteria(GradingCriterionTemplate criteria) {
|
||||
this.titleSv = criteria.getTitle();
|
||||
this.titleEn = criteria.getTitleEn();
|
||||
this.pointsRequiredToPass = criteria.getPointsRequiredToPass();
|
||||
for (var point : criteria.getGradingCriterionPointTemplates()) {
|
||||
if (point.getPoint() == 0) continue;
|
||||
if (point.getPoint() == 0) continue; // This is to hide zero point requirements that never have any text
|
||||
Point editingPoint = new Point(point);
|
||||
this.points.add(editingPoint);
|
||||
}
|
||||
|
@ -150,6 +190,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 +235,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ import java.time.LocalDate;
|
|||
import java.util.List;
|
||||
|
||||
class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTemplate> {
|
||||
|
||||
private final Label maxPointsAvailable;
|
||||
|
||||
EditingGradingTemplateComponentPanel(
|
||||
String id,
|
||||
IModel<EditingGradingTemplate> editingGradingTemplateModel)
|
||||
|
@ -36,7 +39,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
EditingGradingTemplate::setValidFrom),
|
||||
LocalDate.class);
|
||||
validFromField.add(new BootstrapDatePicker());
|
||||
validFromField.add(new AutoSave());
|
||||
validFromField.add(new AutoSave("changeDate"));
|
||||
add(validFromField);
|
||||
|
||||
add(new TextArea<>("note", LambdaModel.of(
|
||||
|
@ -50,7 +53,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)));
|
||||
maxPointsAvailable = new Label("max_points_available", editingGradingTemplateModel.map(EditingGradingTemplate::getMaxPointsAvailable));
|
||||
maxPointsAvailable.setOutputMarkupId(true);
|
||||
add(maxPointsAvailable);
|
||||
|
||||
|
||||
add(new ListView<>("criteria", editingGradingTemplateModel.map(EditingGradingTemplate::getCriteria)) {
|
||||
{
|
||||
|
@ -64,6 +70,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
public void onClick(AjaxRequestTarget target) {
|
||||
editingGradingTemplateModel.getObject().getCriteria().remove(item.getModelObject());
|
||||
target.add(EditingGradingTemplateComponentPanel.this);
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
});
|
||||
item.add(new CriteriaEditingPanel("criteria", item.getModel()));
|
||||
|
@ -75,6 +82,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
public void onClick(AjaxRequestTarget target) {
|
||||
editingGradingTemplateModel.getObject().addCriteria();
|
||||
target.add(EditingGradingTemplateComponentPanel.this);
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -117,6 +125,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
EditingGradingTemplate.Criteria.Type objectSelected)
|
||||
{
|
||||
// auto save
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
};
|
||||
typeChoice.setRequired(true);
|
||||
|
@ -149,6 +158,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
EditingGradingTemplate.Criteria.Flag objectSelected)
|
||||
{
|
||||
// auto save
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
};
|
||||
flagChoice.setNullValid(true);
|
||||
|
@ -176,6 +186,8 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
EditingGradingTemplate.Criteria.Point newPoint = criteria.new Point();
|
||||
criteria.getPoints().add(newPoint);
|
||||
target.add(CriteriaEditingPanel.this);
|
||||
target.add(maxPointsAvailable);
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -210,13 +222,14 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
EditingGradingTemplate.Criteria criteria = CriteriaEditingPanel.this.getModelObject();
|
||||
criteria.getPoints().remove(model.getObject());
|
||||
target.add(CriteriaEditingPanel.this);
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GradeLimitsPanel extends GenericWebMarkupContainer<GradeLimits> {
|
||||
private class GradeLimitsPanel extends GenericWebMarkupContainer<GradeLimits> {
|
||||
public GradeLimitsPanel(String id, IModel<GradeLimits> model) {
|
||||
super(id, model);
|
||||
|
||||
|
@ -248,6 +261,7 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
GradeLimits gradeLimits = GradeLimitsPanel.this.getModelObject();
|
||||
gradeLimits.addNewLimit();
|
||||
target.add(GradeLimitsPanel.this);
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -278,20 +292,30 @@ class EditingGradingTemplateComponentPanel extends GenericPanel<EditingGradingTe
|
|||
GradeLimits gradeLimits = GradeLimitsPanel.this.getModelObject();
|
||||
gradeLimits.getGradeLimits().remove(model.getObject());
|
||||
target.add(GradeLimitsPanel.this);
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class AutoSave extends AjaxFormComponentUpdatingBehavior {
|
||||
private class AutoSave extends AjaxFormComponentUpdatingBehavior {
|
||||
public AutoSave() {
|
||||
super("input");
|
||||
}
|
||||
|
||||
public AutoSave(String event) {
|
||||
super(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUpdate(AjaxRequestTarget target) {
|
||||
// just trigger the ajax call is enough to update the model object
|
||||
onTemplateChanged(target);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onTemplateChanged(AjaxRequestTarget target) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import se.su.dsv.scipro.report.GradingReportTemplate;
|
|||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
class GradeLimits implements Serializable {
|
||||
private List<GradeLimit> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,3 +3,5 @@ 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.
|
||||
project_type_name_editing=You are editing a ${project_type_name} grading template.
|
||||
|
|
Loading…
Reference in New Issue
Block a user