2984 PO 3) Mark which steps are completed

This commit is contained in:
Andreas Svanberg 2023-10-25 12:06:49 +02:00
parent 7d9bde2892
commit 841dfbc8a8
3 changed files with 135 additions and 6 deletions

@ -8,12 +8,26 @@
This process consists of five steps outlined below.
</p>
<ol>
<li>Approve final thesis</li>
<li>Check for plagiarism</li>
<li>Supply publication metadata</li>
<li>Fill in general criteria (assessment of the thesis)</li>
<li>Fill in individual criteria for each author</li>
<li>Send to examiner for grading (done individually in each author's tab)</li>
<li wicket:id="step_final_thesis">Approve final thesis</li>
<li wicket:id="step_plagiarism">Check for plagiarism</li>
<li wicket:id="step_publication_metadata">Supply publication metadata</li>
<li wicket:id="step_general_criteria">Fill in general criteria (assessment of the thesis)</li>
<li>
<span wicket:id="step_individual_criteria">Fill in individual criteria for each author</span>
<ul>
<li wicket:id="step_individual_criteria_author">
<span wicket:id="author"></span>
</li>
</ul>
</li>
<li>
<span wicket:id="step_sent_to_examiner">Send to examiner for grading (done individually in each author's tab)</span>
<ul>
<li wicket:id="step_sent_to_examiner_author">
<span wicket:id="author"></span>
</li>
</ul>
</li>
</ol>
<p>Follow the instructions in each step, and you'll be able to send the thesis to the examiner.</p>
<div class="row mb-3">

@ -1,32 +1,47 @@
package se.su.dsv.scipro.grading;
import org.apache.wicket.Component;
import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.extensions.markup.html.tabs.TabbedPanel;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.request.flow.RedirectToUrlException;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.danekja.java.util.function.serializable.SerializableFunction;
import se.su.dsv.scipro.components.BootstrapCardTabbedPanel;
import se.su.dsv.scipro.components.ListAdapterModel;
import se.su.dsv.scipro.components.RedGreenLabel;
import se.su.dsv.scipro.data.DetachableServiceModel;
import se.su.dsv.scipro.finalthesis.ApproveFinalThesisPanel;
import se.su.dsv.scipro.finalthesis.FinalThesis;
import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService;
import se.su.dsv.scipro.oauth.OAuth;
import se.su.dsv.scipro.oauth.OAuthService;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.report.GradingCriterion;
import se.su.dsv.scipro.report.GradingReportService;
import se.su.dsv.scipro.report.SupervisorGradingReport;
import se.su.dsv.scipro.reviewer.timeline.TimelinePanel;
import se.su.dsv.scipro.security.auth.ProjectModuleComponent;
import se.su.dsv.scipro.supervisor.pages.AbstractSupervisorProjectDetailsPage;
import se.su.dsv.scipro.system.ProjectModule;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.system.UserService;
import se.su.dsv.scipro.util.Either;
import javax.inject.Inject;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@ProjectModuleComponent(ProjectModule.GRADING)
@ -37,10 +52,68 @@ public class SupervisorGradingReportPage extends AbstractSupervisorProjectDetail
private OAuthService oAuthService;
@Inject
private UserService userService;
@Inject
private GradingReportService gradingReportService;
@Inject
private FinalThesisService finalThesisService;
@Inject
private PublicationMetadataService publicationMetadataService;
@Inject
private GradingService gradingService;
public SupervisorGradingReportPage(PageParameters pp) {
super(pp);
IModel<Boolean> hasApprovedFinalThesis =
LoadableDetachableModel.of(() -> finalThesisService.findByProject(projectModel.getObject()))
.filter(ft -> ft.getStatus() == FinalThesis.Status.APPROVED)
.isPresent();
add(newGreenHighlight("step_final_thesis", hasApprovedFinalThesis, new ResourceModel("step_final_thesis")));
IModel<Boolean> hasCheckedForPlagiarism =
LoadableDetachableModel.of(() -> finalThesisService.findByProject(projectModel.getObject()))
.map(FinalThesis::getTextMatchingDocument)
.isPresent();
add(newGreenHighlight("step_plagiarism", hasCheckedForPlagiarism, new ResourceModel("step_plagiarism")));
IModel<Boolean> hasProvidedPublicationMetadata =
LoadableDetachableModel.of(() -> publicationMetadataService.getByProject(projectModel.getObject()))
.filter(metadata -> notBlank(metadata.getAbstractEnglish()) || notBlank(metadata.getAbstractSwedish()))
.filter(metadata -> notBlank(metadata.getKeywordsEnglish()) || notBlank(metadata.getKeywordsSwedish()))
.isPresent();
add(newGreenHighlight("step_publication_metadata", hasProvidedPublicationMetadata, new ResourceModel("step_publication_metadata")));
IModel<List<SupervisorGradingReport>> gradingReports = LoadableDetachableModel.of(() ->
gradingReportService.getSupervisorGradingReports(projectModel.getObject()));
IModel<Boolean> generalCriteriaDone = gradingReports
.map(reports -> reports.stream().allMatch(this::generalCriteriaDone));
add(newGreenHighlight("step_general_criteria", generalCriteriaDone, new ResourceModel("step_general_criteria")));
IModel<Boolean> individualCriteriaDone = gradingReports
.map(reports -> reports.stream().allMatch(this::individualCriteriaDone));
add(newGreenHighlight("step_individual_criteria", individualCriteriaDone, new ResourceModel("step_individual_criteria")));
add(new ListView<>("step_individual_criteria_author", gradingReports) {
@Override
protected void populateItem(ListItem<SupervisorGradingReport> item) {
IModel<Boolean> individualCriteriaDone = item.getModel().map(SupervisorGradingReportPage.this::individualCriteriaDone);
item.add(newGreenHighlight("author", individualCriteriaDone, item.getModel().map(SupervisorGradingReport::getUser).map(User::getFullName)));
}
});
IModel<Boolean> sentToExaminer = LoadableDetachableModel.of(() -> projectModel.getObject()
.getProjectParticipants()
.stream()
.allMatch(this::sentToExaminer));
add(newGreenHighlight("step_sent_to_examiner", sentToExaminer, new ResourceModel("step_send_to_examiner")));
add(new ListView<>("step_sent_to_examiner_author", new ListAdapterModel<>(projectModel.map(Project::getProjectParticipants))) {
@Override
protected void populateItem(ListItem<User> item) {
IModel<Boolean> sentToExaminer = item.getModel().map(SupervisorGradingReportPage.this::sentToExaminer);
item.add(newGreenHighlight("author", sentToExaminer, item.getModel().map(User::getFullName)));
}
});
List<ITab> tabs = new ArrayList<>();
tabs.add(createTab(Model.of("Final thesis"),
panelId -> new ApproveFinalThesisPanel(panelId, projectModel)));
@ -77,6 +150,42 @@ public class SupervisorGradingReportPage extends AbstractSupervisorProjectDetail
add(new ExaminerTimelinePanel("examiner_timeline", projectModel));
}
private boolean notBlank(String s) {
return s != null && !s.isBlank();
}
private Component newGreenHighlight(String id, IModel<Boolean> completed, IModel<String> text) {
return new RedGreenLabel(id, completed, text, text);
}
private boolean generalCriteriaDone(SupervisorGradingReport supervisorGradingReport) {
boolean criteriaMet = supervisorGradingReport.getProjectCriteria()
.stream()
.allMatch(GradingCriterion::meetsMinimumPointRequirement);
return criteriaMet && supervisorGradingReport.hasProvidedRejectionFeedback();
}
private boolean individualCriteriaDone(SupervisorGradingReport supervisorGradingReport) {
return supervisorGradingReport.getIndividualCriteria()
.stream()
.allMatch(GradingCriterion::meetsMinimumPointRequirement);
}
private boolean sentToExaminer(User author) {
String token = getSession().getMetaData(OAuth.TOKEN);
Project project = projectModel.getObject();
List<Examination> examinations = gradingService.getExaminations(token, project.getIdentifier(), author.getIdentifier());
for (Examination examination : examinations) {
if (examination.hasManyPassingGrades()) {
Either<GetGradeError, Optional<Result>> result = gradingService.getResult(token, project.getIdentifier(), author.getIdentifier(), examination.id());
if (result.isRight() && result.right().isEmpty()) {
return false;
}
}
}
return true;
}
private ITab createTab(IModel<String> title, SerializableFunction<String, WebMarkupContainer> newPanel) {
return new AbstractTab(title) {
@Override

@ -0,0 +1,6 @@
step_final_thesis=Approve final thesis
step_plagiarism=Check for plagiarism
step_publication_metadata=Supply publication metadata
step_general_criteria=Fill in general criteria (assessment of the thesis)
step_individual_criteria=Fill in individual criteria for each author
step_send_to_examiner=Send to examiner for grading (done individually in each author's tab)