Allows admins to manage grading report templates #14
@ -33,4 +33,9 @@ public interface GradingReportTemplateService {
|
||||
NoSuchTemplateException,
|
||||
DuplicateDateException,
|
||||
TemplateLockedException;
|
||||
|
||||
GradingReportTemplate create(ProjectType projectType, GradingReportTemplateUpdate update)
|
||||
throws
|
||||
ValidDateMustBeInTheFutureException,
|
||||
DuplicateDateException;
|
||||
}
|
||||
|
@ -269,4 +269,25 @@ public class GradingReportServiceImpl implements GradingReportTemplateService, G
|
||||
|
||||
return gradingReportTemplateRepo.updateTemplate(templateId, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GradingReportTemplate create(ProjectType projectType, GradingReportTemplateUpdate update)
|
||||
throws ValidDateMustBeInTheFutureException, DuplicateDateException
|
||||
{
|
||||
LocalDate today = LocalDate.now(clock);
|
||||
if (!update.validFrom().isAfter(today)) {
|
||||
throw new ValidDateMustBeInTheFutureException(update.validFrom(), today.plusDays(1));
|
||||
}
|
||||
|
||||
GradingReportTemplate currentTemplate = gradingReportTemplateRepo.getCurrentTemplate(
|
||||
projectType,
|
||||
update.validFrom());
|
||||
if (currentTemplate != null &&
|
||||
Objects.equals(currentTemplate.getValidFrom(), update.validFrom()))
|
||||
{
|
||||
throw new DuplicateDateException(update.validFrom(), projectType);
|
||||
}
|
||||
|
||||
return gradingReportTemplateRepo.createTemplate(projectType, update);
|
||||
}
|
||||
}
|
||||
|
@ -20,4 +20,6 @@ public interface GradingReportTemplateRepo extends JpaRepository<GradingReportTe
|
||||
GradingReportTemplate getTemplateById(long templateId);
|
||||
|
||||
GradingReportTemplate updateTemplate(long templateId, GradingReportTemplateUpdate update);
|
||||
|
||||
GradingReportTemplate createTemplate(ProjectType projectType, GradingReportTemplateUpdate update);
|
||||
}
|
||||
|
@ -65,6 +65,13 @@ public class GradingReportTemplateRepoImpl extends GenericRepo<GradingReportTemp
|
||||
@Transactional
|
||||
public GradingReportTemplate updateTemplate(long templateId, GradingReportTemplateUpdate update) {
|
||||
GradingReportTemplate gradingReportTemplate = findOne(templateId);
|
||||
return updateTemplate(gradingReportTemplate, update);
|
||||
}
|
||||
|
||||
private GradingReportTemplate updateTemplate(
|
||||
GradingReportTemplate gradingReportTemplate,
|
||||
GradingReportTemplateUpdate update)
|
||||
{
|
||||
gradingReportTemplate.setValidFrom(update.validFrom());
|
||||
gradingReportTemplate.setNote(update.note());
|
||||
gradingReportTemplate.setFailingGrade(update.failingGrade());
|
||||
@ -111,6 +118,13 @@ public class GradingReportTemplateRepoImpl extends GenericRepo<GradingReportTemp
|
||||
return save(gradingReportTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public GradingReportTemplate createTemplate(ProjectType projectType, GradingReportTemplateUpdate update) {
|
||||
GradingReportTemplate gradingReportTemplate = new GradingReportTemplate(projectType, update.validFrom());
|
||||
return updateTemplate(gradingReportTemplate, update);
|
||||
}
|
||||
|
||||
private GradingCriterionPointTemplate toPointTemplate(GradingReportTemplateUpdate.Criteria.Requirement requirement) {
|
||||
return new GradingCriterionPointTemplate.Builder()
|
||||
.point(requirement.points())
|
||||
|
@ -14,6 +14,7 @@ import org.apache.wicket.util.convert.converter.LocalDateConverter;
|
||||
import org.apache.wicket.util.convert.converter.LocalDateTimeConverter;
|
||||
import se.su.dsv.scipro.activityplan.*;
|
||||
import se.su.dsv.scipro.admin.pages.*;
|
||||
import se.su.dsv.scipro.admin.pages.grading.AdminGradingTemplateCreationPage;
|
||||
import se.su.dsv.scipro.admin.pages.grading.AdminGradingTemplateEditPage;
|
||||
import se.su.dsv.scipro.admin.pages.grading.AdminGradingTemplatePage;
|
||||
import se.su.dsv.scipro.admin.pages.grading.AdminGradingTemplatesOverviewPage;
|
||||
@ -288,6 +289,7 @@ public class SciProApplication extends LifecycleManagedWebApplication {
|
||||
mountPage("admin/project/grading/template", AdminGradingTemplatesOverviewPage.class);
|
||||
mountPage("admin/project/grading/template/view", AdminGradingTemplatePage.class);
|
||||
mountPage("admin/project/grading/template/edit", AdminGradingTemplateEditPage.class);
|
||||
mountPage("admin/project/grading/template/create", AdminGradingTemplateCreationPage.class);
|
||||
mountPage("admin/edit", AdminEditProjectPage.class);
|
||||
mountPage("admin/finalseminars", AdminFinalSeminarPage.class);
|
||||
mountPage("admin/finalseminars/exemptions", AdminFinalSeminarExemptionPage.class);
|
||||
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:extend>
|
||||
<h1>Create a new grading report template</h1>
|
||||
|
||||
<div wicket:id="feedback"></div>
|
||||
|
||||
<form wicket:id="form" class="line-length-limit">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" wicket:for="project_type">Project type</label>
|
||||
<select wicket:id="project_type" class="form-select">
|
||||
<option value="bachelor">Bachelor</option>
|
||||
<option value="master">Master</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div wicket:id="grading_template_component_panel"></div>
|
||||
|
||||
<div class="position-sticky bottom-0 bg-white p-3 border line-length-limit">
|
||||
<button type="submit" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</wicket:extend>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,80 @@
|
||||
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.form.Form;
|
||||
import org.apache.wicket.markup.html.form.LambdaChoiceRenderer;
|
||||
import org.apache.wicket.markup.html.panel.FeedbackPanel;
|
||||
import org.apache.wicket.model.IModel;
|
||||
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.components.AjaxDropDownChoice;
|
||||
import se.su.dsv.scipro.data.DetachableServiceModel;
|
||||
import se.su.dsv.scipro.grading.GradingReportTemplateService;
|
||||
import se.su.dsv.scipro.grading.GradingReportTemplateUpdate;
|
||||
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.system.ProjectType;
|
||||
import se.su.dsv.scipro.system.ProjectTypeService;
|
||||
|
||||
public class AdminGradingTemplateCreationPage extends AbstractAdminProjectPage implements MenuHighlightGradingTemplates {
|
||||
|
||||
@Inject
|
||||
GradingReportTemplateService gradingReportTemplateService;
|
||||
@Inject
|
||||
ProjectTypeService projectTypeService;
|
||||
|
||||
private final IModel<ProjectType> projectTypeModel;
|
||||
private EditingGradingTemplate editingGradingTemplateModel;
|
||||
|
||||
public AdminGradingTemplateCreationPage() {
|
||||
projectTypeModel = new DetachableServiceModel<>(projectTypeService);
|
||||
|
||||
add(new FeedbackPanel("feedback"));
|
||||
|
||||
Form<?> form = new Form<>("form") {
|
||||
@Override
|
||||
protected void onSubmit() {
|
||||
super.onSubmit();
|
||||
GradingReportTemplateUpdate update = AdminGradingTemplateEditPage.toUpdate(editingGradingTemplateModel);
|
||||
try {
|
||||
GradingReportTemplate gradingReportTemplate = gradingReportTemplateService.create(
|
||||
projectTypeModel.getObject(),
|
||||
update);
|
||||
getSession().success(getString("template_created", projectTypeModel));
|
||||
PageParameters pageParameters = AdminGradingTemplateEditPage.getPageParameters(gradingReportTemplate);
|
||||
throw new RestartResponseException(AdminGradingTemplateEditPage.class, pageParameters);
|
||||
} catch (ValidDateMustBeInTheFutureException e) {
|
||||
error(getString("valid_from_must_be_in_the_future", () -> e));
|
||||
} catch (DuplicateDateException e) {
|
||||
error(getString("another_template_exists_for_the_given_date_date", () -> e));
|
||||
}
|
||||
}
|
||||
};
|
||||
form.setOutputMarkupId(true);
|
||||
add(form);
|
||||
|
||||
form.add(new AjaxDropDownChoice<>(
|
||||
"project_type",
|
||||
projectTypeModel,
|
||||
gradingReportTemplateService.getProjectTypes(),
|
||||
new LambdaChoiceRenderer<>(ProjectType::getName, ProjectType::getId)) {
|
||||
@Override
|
||||
public void onNewSelection(AjaxRequestTarget target, ProjectType objectSelected) {
|
||||
target.add(form);
|
||||
}
|
||||
});
|
||||
|
||||
editingGradingTemplateModel = new EditingGradingTemplate();
|
||||
form.add(new EditingGradingTemplateComponentPanel("grading_template_component_panel", Model.of(editingGradingTemplateModel)) {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
setVisible(projectTypeModel.getObject() != null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -66,17 +66,17 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
|
||||
add(form);
|
||||
}
|
||||
|
||||
private GradingReportTemplateUpdate toUpdate(EditingGradingTemplate editingGradingTemplate) {
|
||||
public static GradingReportTemplateUpdate toUpdate(EditingGradingTemplate editingGradingTemplate) {
|
||||
List<GradingReportTemplateUpdate.GradeLimit> gradeLimits = editingGradingTemplate
|
||||
.getGradeLimits()
|
||||
.getGradeLimits()
|
||||
.stream()
|
||||
.map(this::toGrade)
|
||||
.map(AdminGradingTemplateEditPage::toGrade)
|
||||
.toList();
|
||||
List<GradingReportTemplateUpdate.Criteria> criteria = editingGradingTemplate
|
||||
.getCriteria()
|
||||
.stream()
|
||||
.map(this::toCriteria)
|
||||
.map(AdminGradingTemplateEditPage::toCriteria)
|
||||
.toList();
|
||||
return new GradingReportTemplateUpdate(
|
||||
editingGradingTemplate.getValidFrom(),
|
||||
@ -86,7 +86,7 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
|
||||
criteria);
|
||||
}
|
||||
|
||||
private GradingReportTemplateUpdate.Criteria toCriteria(EditingGradingTemplate.Criteria criteria) {
|
||||
private static GradingReportTemplateUpdate.Criteria toCriteria(EditingGradingTemplate.Criteria criteria) {
|
||||
ArrayList<GradingReportTemplateUpdate.Criteria.Requirement> requirements = new ArrayList<>();
|
||||
requirements.add(ZERO_REQUIREMENT);
|
||||
for (int i = 0; i < criteria.getPoints().size(); i++) {
|
||||
@ -117,7 +117,7 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
|
||||
};
|
||||
}
|
||||
|
||||
private GradingReportTemplateUpdate.GradeLimit toGrade(GradeLimits.GradeLimit gradeLimit) {
|
||||
private static GradingReportTemplateUpdate.GradeLimit toGrade(GradeLimits.GradeLimit gradeLimit) {
|
||||
return new GradingReportTemplateUpdate.GradeLimit(
|
||||
gradeLimit.getGrade(),
|
||||
gradeLimit.getLowerLimit());
|
||||
|
@ -32,15 +32,9 @@
|
||||
</p>
|
||||
|
||||
<div class="btn-group mb-3" role="group">
|
||||
<button type="button" class="btn btn-outline-primary">Create new template</button>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" href="#">Create new based on another template</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
<wicket:link>
|
||||
<a href="AdminGradingTemplateCreationPage.html" class="btn btn-outline-primary">Create new template</a>
|
||||
</wicket:link>
|
||||
</div>
|
||||
|
||||
<div class="mb-3" wicket:id="project_types">
|
||||
|
@ -15,6 +15,11 @@ class EditingGradingTemplate implements Serializable {
|
||||
private List<Criteria> criteria;
|
||||
private GradeLimits gradeLimits;
|
||||
|
||||
public EditingGradingTemplate() {
|
||||
this.gradeLimits = new GradeLimits();
|
||||
this.criteria = new ArrayList<>();
|
||||
}
|
||||
|
||||
EditingGradingTemplate(GradingReportTemplate template) {
|
||||
this.note = template.getNote();
|
||||
this.validFrom = template.getValidFrom();
|
||||
|
@ -10,6 +10,10 @@ class GradeLimits implements Serializable {
|
||||
private List<GradeLimit> gradeLimits;
|
||||
private String failingGrade;
|
||||
|
||||
public GradeLimits() {
|
||||
this.gradeLimits = new ArrayList<>();
|
||||
}
|
||||
|
||||
GradeLimits(GradingReportTemplate template) {
|
||||
this.gradeLimits = new ArrayList<>();
|
||||
for (var gradeLimit : template.getGradeLimits()) {
|
||||
|
@ -2,3 +2,4 @@ template_updated=Template updated
|
||||
valid_from_must_be_in_the_future=The templates valid date must be in the future. The given date was ${validFrom} but it must be at least ${earliestAllowedValidFrom}.
|
||||
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.
|
Loading…
x
Reference in New Issue
Block a user