WIP: Allow supervisors to request improvements from final seminar opponents #78

Draft
ansv7779 wants to merge 24 commits from opponent-completion into develop
8 changed files with 68 additions and 25 deletions
Showing only changes of commit 5e3f6c1383 - Show all commits

View File

@ -31,6 +31,7 @@ import se.su.dsv.scipro.finalseminar.AuthorRepository;
import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationRepository;
import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationServiceImpl;
import se.su.dsv.scipro.finalseminar.FinalSeminarCreationSubscribers;
import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionGrading;
import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionRepo;
import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionServiceImpl;
import se.su.dsv.scipro.finalseminar.FinalSeminarRepository;
@ -430,8 +431,11 @@ public class CoreConfig {
}
@Bean
public FinalSeminarOppositionServiceImpl finalSeminarOppositionService(Provider<EntityManager> em) {
return new FinalSeminarOppositionServiceImpl(em);
public FinalSeminarOppositionServiceImpl finalSeminarOppositionService(
Provider<EntityManager> em,
FinalSeminarOppositionGrading finalSeminarOppositionGrading
) {
return new FinalSeminarOppositionServiceImpl(em, finalSeminarOppositionGrading);
}
@Bean

View File

@ -0,0 +1,7 @@
package se.su.dsv.scipro.finalseminar;
import java.util.List;
public interface FinalSeminarOppositionGrading {
List<OppositionCriterion> oppositionCriteria(FinalSeminarOpposition opposition);
}

View File

@ -1,8 +1,11 @@
package se.su.dsv.scipro.finalseminar;
import java.util.List;
import se.su.dsv.scipro.system.GenericService;
public interface FinalSeminarOppositionService extends GenericService<FinalSeminarOpposition, Long> {
@Override
void delete(Long aLong);
List<OppositionCriterion> getCriteriaForOpposition(FinalSeminarOpposition opposition);
}

View File

@ -3,14 +3,26 @@ package se.su.dsv.scipro.finalseminar;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.persistence.EntityManager;
import java.util.List;
import se.su.dsv.scipro.system.AbstractServiceImpl;
public class FinalSeminarOppositionServiceImpl
extends AbstractServiceImpl<FinalSeminarOpposition, Long>
implements FinalSeminarOppositionService {
private final FinalSeminarOppositionGrading finalSeminarOppositionGrading;
@Inject
public FinalSeminarOppositionServiceImpl(Provider<EntityManager> em) {
public FinalSeminarOppositionServiceImpl(
Provider<EntityManager> em,
FinalSeminarOppositionGrading finalSeminarOppositionGrading
) {
super(em, FinalSeminarOpposition.class, QFinalSeminarOpposition.finalSeminarOpposition);
this.finalSeminarOppositionGrading = finalSeminarOppositionGrading;
}
@Override
public List<OppositionCriterion> getCriteriaForOpposition(FinalSeminarOpposition opposition) {
return finalSeminarOppositionGrading.oppositionCriteria(opposition);
}
}

View File

@ -0,0 +1,3 @@
package se.su.dsv.scipro.finalseminar;
public record OppositionCriterion(int points, String requirement) {}

View File

@ -8,6 +8,8 @@ import java.time.Instant;
import java.time.LocalDate;
import java.util.*;
import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition;
import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionGrading;
import se.su.dsv.scipro.finalseminar.OppositionCriterion;
import se.su.dsv.scipro.grading.GradingBasis;
import se.su.dsv.scipro.grading.GradingReportTemplateService;
import se.su.dsv.scipro.grading.GradingReportTemplateUpdate;
@ -20,7 +22,8 @@ import se.su.dsv.scipro.system.ProjectTypeService;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.util.Either;
public class GradingReportServiceImpl implements GradingReportTemplateService, GradingReportService {
public class GradingReportServiceImpl
implements GradingReportTemplateService, GradingReportService, FinalSeminarOppositionGrading {
private final EventBus eventBus;
private final ThesisSubmissionHistoryService thesisSubmissionHistoryService;
@ -289,4 +292,17 @@ public class GradingReportServiceImpl implements GradingReportTemplateService, G
return gradingReportTemplateRepo.createTemplate(projectType, update);
}
@Override
@Transactional
public List<OppositionCriterion> oppositionCriteria(FinalSeminarOpposition opposition) {
return getSupervisorGradingReport(opposition.getProject(), opposition.getUser())
.getIndividualCriteria()
.stream()
.filter(individualCriterion -> individualCriterion.getFlag() == AbstractGradingCriterion.Flag.OPPOSITION)
.map(GradingCriterion::getGradingCriterionPoints)
.flatMap(Collection::stream)
.map(gcp -> new OppositionCriterion(gcp.getPoint(), gcp.getDescription(Language.ENGLISH)))
.toList();
}
}

View File

@ -25,7 +25,7 @@
<div class="mb-3">
<label>Points:</label>
<input type="text" class="form-control gradingPoints" wicket:id="points"/>
<select class="form-select" wicket:id="points"></select>
</div>
<label>Motivation:</label>

View File

@ -11,10 +11,11 @@ import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.feedback.FencedFeedbackPanel;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.LambdaChoiceRenderer;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
@ -23,11 +24,12 @@ import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LambdaModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.validation.validator.RangeValidator;
import org.apache.wicket.validation.validator.StringValidator;
import se.su.dsv.scipro.components.ListAdapterModel;
import se.su.dsv.scipro.components.StatelessModel;
import se.su.dsv.scipro.profile.UserLinkPanel;
import se.su.dsv.scipro.report.GradingReportService;
import se.su.dsv.scipro.report.OppositionReportService;
@ -229,29 +231,25 @@ public class SeminarOppositionPanel extends Panel {
private class FinalSeminarOppositionForm extends Form<FinalSeminarOpposition> {
private IModel<OppositionCriterion> pointsModel = new StatelessModel<>();
private IModel<String> feedbackModel = new Model<>();
public FinalSeminarOppositionForm(String id, final IModel<FinalSeminarOpposition> finalSeminarOpposition) {
super(id, finalSeminarOpposition);
FormComponent<Integer> pointsField = new TextField<>(
IModel<List<OppositionCriterion>> criteriaModel = LoadableDetachableModel.of(() ->
finalSeminarOppositionService.getCriteriaForOpposition(finalSeminarOpposition.getObject())
);
FormComponent<OppositionCriterion> pointsField = new DropDownChoice<>(
POINTS,
LambdaModel.of(
finalSeminarOpposition,
FinalSeminarOpposition::getPoints,
FinalSeminarOpposition::setPoints
)
)
.add(RangeValidator.range(MIN_POINTS, MAX_POINTS))
.setType(Integer.class)
.setRequired(true);
pointsModel,
criteriaModel,
new LambdaChoiceRenderer<>(OppositionCriterion::points)
);
pointsField.setRequired(true);
add(pointsField);
TextArea<String> feedback = new TextArea<>(
GRADING_FEEDBACK,
LambdaModel.of(
finalSeminarOpposition,
FinalSeminarOpposition::getFeedback,
FinalSeminarOpposition::setFeedback
)
);
TextArea<String> feedback = new TextArea<>(GRADING_FEEDBACK, feedbackModel);
feedback.add(StringValidator.maximumLength(FEEDBACK_MAX_LENGTH));
feedback.setRequired(true);
add(feedback);