Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
da53f15bb1
core/src/main
java/se/su/dsv/scipro
daisyExternal/http
grading
GradingModule.javaNationalSubjectCategory.javaNationalSubjectCategoryRepository.javaNationalSubjectCategoryRepositoryImpl.javaNationalSubjectCategoryService.javaNationalSubjectCategoryServiceImpl.java
match
report
workerthreads
resources/db/migration
daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy
view/src
main/java/se/su/dsv/scipro/grading
GradingBasisPanel.htmlGradingBasisPanel.javaIndividualAuthorAssessment.htmlIndividualAuthorAssessment.javaSupervisorGradingReportPage.java
test/java/se/su/dsv/scipro/workerthreads
@ -75,4 +75,6 @@ public interface DaisyAPI {
|
||||
PublishingConsent getPublishingConsent(int projectId, int personId);
|
||||
|
||||
boolean setPublishingConsent(int projectId, int personId, PublishingConsentLevel publishingConsentLevel);
|
||||
|
||||
List<ResearchSubject> getNationalResearchSubjects(int organisationId);
|
||||
}
|
||||
|
@ -434,6 +434,15 @@ public class DaisyAPIImpl implements DaisyAPI {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResearchSubject> getNationalResearchSubjects(int organisationId) {
|
||||
return units()
|
||||
.path(Integer.toString(organisationId))
|
||||
.path("nationalSubjectCategories")
|
||||
.request(MediaType.APPLICATION_XML_TYPE)
|
||||
.get(new GenericType<>() {});
|
||||
}
|
||||
|
||||
private WebTarget program() {
|
||||
return target()
|
||||
.path(PROGRAM);
|
||||
|
@ -25,5 +25,9 @@ public class GradingModule extends PrivateModule {
|
||||
expose(ThesisApprovedHistoryService.class);
|
||||
bind(ThesisSubmissionHistoryService.class).to(GradingHistory.class);
|
||||
expose(ThesisSubmissionHistoryService.class);
|
||||
|
||||
bind(NationalSubjectCategoryRepository.class).to(NationalSubjectCategoryRepositoryImpl.class);
|
||||
bind(NationalSubjectCategoryService.class).to(NationalSubjectCategoryServiceImpl.class);
|
||||
expose(NationalSubjectCategoryService.class);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,116 @@
|
||||
package se.su.dsv.scipro.grading;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "national_subject_category")
|
||||
public class NationalSubjectCategory {
|
||||
@Id
|
||||
@GeneratedValue(strategy = jakarta.persistence.GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Basic
|
||||
@Column(name = "external_id")
|
||||
private Integer externalId;
|
||||
|
||||
@Basic
|
||||
@Column(name = "swedish_name")
|
||||
private String swedishName;
|
||||
|
||||
@Basic
|
||||
@Column(name = "english_name")
|
||||
private String englishName;
|
||||
|
||||
@Basic
|
||||
@Column(name = "active")
|
||||
private boolean active;
|
||||
|
||||
@Basic
|
||||
@Column(name = "preselected")
|
||||
private boolean preselected;
|
||||
|
||||
public NationalSubjectCategory() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getExternalId() {
|
||||
return externalId;
|
||||
}
|
||||
|
||||
public void setExternalId(Integer externalId) {
|
||||
this.externalId = externalId;
|
||||
}
|
||||
|
||||
public String getSwedishName() {
|
||||
return swedishName;
|
||||
}
|
||||
|
||||
public void setSwedishName(String swedishName) {
|
||||
this.swedishName = swedishName;
|
||||
}
|
||||
|
||||
public String getEnglishName() {
|
||||
return englishName;
|
||||
}
|
||||
|
||||
public void setEnglishName(String englishName) {
|
||||
this.englishName = englishName;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public boolean isPreselected() {
|
||||
return preselected;
|
||||
}
|
||||
|
||||
public void setPreselected(boolean preselected) {
|
||||
this.preselected = preselected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof NationalSubjectCategory that)) {
|
||||
return false;
|
||||
}
|
||||
if (this.id != null) {
|
||||
return Objects.equals(this.id, that.id);
|
||||
}
|
||||
return Objects.equals(this.externalId, that.externalId)
|
||||
&& Objects.equals(this.swedishName, that.swedishName)
|
||||
&& Objects.equals(this.englishName, that.englishName)
|
||||
&& Objects.equals(this.active, that.active)
|
||||
&& Objects.equals(this.preselected, that.preselected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (this.id != null) {
|
||||
return Objects.hashCode(id);
|
||||
}
|
||||
return Objects.hash(externalId, swedishName, englishName, active, preselected);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package se.su.dsv.scipro.grading;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface NationalSubjectCategoryRepository {
|
||||
void save(NationalSubjectCategory nationalSubjectCategory);
|
||||
|
||||
Optional<NationalSubjectCategory> findByExternalId(Integer externalId);
|
||||
}
|
40
core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategoryRepositoryImpl.java
Normal file
40
core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategoryRepositoryImpl.java
Normal file
@ -0,0 +1,40 @@
|
||||
package se.su.dsv.scipro.grading;
|
||||
|
||||
import com.google.inject.persist.Transactional;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import se.su.dsv.scipro.system.AbstractRepository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import java.util.Optional;
|
||||
|
||||
public class NationalSubjectCategoryRepositoryImpl
|
||||
extends AbstractRepository
|
||||
implements NationalSubjectCategoryRepository
|
||||
{
|
||||
@Inject
|
||||
public NationalSubjectCategoryRepositoryImpl(Provider<EntityManager> em) {
|
||||
super(em);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void save(NationalSubjectCategory nationalSubjectCategory) {
|
||||
EntityManager entityManager = em();
|
||||
if (entityManager.contains(nationalSubjectCategory)) {
|
||||
entityManager.merge(nationalSubjectCategory);
|
||||
}
|
||||
else {
|
||||
entityManager.persist(nationalSubjectCategory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<NationalSubjectCategory> findByExternalId(Integer externalId) {
|
||||
NationalSubjectCategory nationalSubjectCategory = from(QNationalSubjectCategory.nationalSubjectCategory)
|
||||
.where(QNationalSubjectCategory.nationalSubjectCategory.externalId.eq(externalId))
|
||||
.select(QNationalSubjectCategory.nationalSubjectCategory)
|
||||
.fetchOne();
|
||||
return Optional.ofNullable(nationalSubjectCategory);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package se.su.dsv.scipro.grading;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface NationalSubjectCategoryService {
|
||||
Optional<NationalSubjectCategory> findByExternalId(Integer externalId);
|
||||
|
||||
void save(NationalSubjectCategory nationalSubjectCategory);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package se.su.dsv.scipro.grading;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Optional;
|
||||
|
||||
public class NationalSubjectCategoryServiceImpl
|
||||
implements NationalSubjectCategoryService
|
||||
{
|
||||
private final NationalSubjectCategoryRepository nationalSubjectCategoryRepository;
|
||||
|
||||
@Inject
|
||||
public NationalSubjectCategoryServiceImpl(NationalSubjectCategoryRepository nationalSubjectCategoryRepository) {
|
||||
this.nationalSubjectCategoryRepository = nationalSubjectCategoryRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<NationalSubjectCategory> findByExternalId(Integer externalId) {
|
||||
return nationalSubjectCategoryRepository.findByExternalId(externalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(NationalSubjectCategory nationalSubjectCategory) {
|
||||
nationalSubjectCategoryRepository.save(nationalSubjectCategory);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package se.su.dsv.scipro.match;
|
||||
|
||||
class AllowAllIdeaCreationJudge implements IdeaCreationJudge {
|
||||
@Override
|
||||
public Decision ruling(Idea idea) {
|
||||
return Decision.allowed();
|
||||
}
|
||||
}
|
@ -3,19 +3,25 @@ package se.su.dsv.scipro.match;
|
||||
public final class Decision {
|
||||
private final boolean allowed;
|
||||
private final String reason;
|
||||
private final Integer identifier;
|
||||
|
||||
private Decision(final boolean allowed, final String reason) {
|
||||
private Decision(final boolean allowed, final String reason, Integer identifier) {
|
||||
|
||||
this.allowed = allowed;
|
||||
this.reason = reason;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public static Decision allowed() {
|
||||
return new Decision(true, "");
|
||||
return allowed(null);
|
||||
}
|
||||
|
||||
public static Decision allowed(Integer identifier) {
|
||||
return new Decision(true, "", identifier);
|
||||
}
|
||||
|
||||
public static Decision denied(String reason) {
|
||||
return new Decision(false, reason);
|
||||
return new Decision(false, reason, null);
|
||||
}
|
||||
|
||||
public boolean isAllowed() {
|
||||
@ -25,4 +31,8 @@ public final class Decision {
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public Integer getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
package se.su.dsv.scipro.match;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.multibindings.OptionalBinder;
|
||||
|
||||
public class MatchModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
Multibinder.newSetBinder(binder(), IdeaCreationJudge.class);
|
||||
OptionalBinder.newOptionalBinder(binder(), IdeaCreationJudge.class)
|
||||
.setDefault().to(AllowAllIdeaCreationJudge.class);
|
||||
bind(ProjectStartNotifier.class).asEagerSingleton();
|
||||
bind(AddActivityPlanOnProjectStart.class).asEagerSingleton();
|
||||
bind(ApplicationPeriodService.class).to(ApplicationPeriodServiceImpl.class);
|
||||
|
@ -109,4 +109,8 @@ public class SupervisorGradingReport extends GradingReport {
|
||||
public void setMotivation(String motivation) {
|
||||
this.motivation = motivation;
|
||||
}
|
||||
|
||||
public boolean hasProvidedOverallMotivation() {
|
||||
return getMotivation() != null && !getMotivation().isBlank();
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class IdeaExportWorker extends AbstractWorker {
|
||||
private final IdeaService ideaService;
|
||||
private final MailEventService mailService;
|
||||
private final ProjectService projectService;
|
||||
private final Set<IdeaCreationJudge> ideaCreationJudges;
|
||||
private final IdeaCreationJudge ideaCreationJudge;
|
||||
private final EventBus eventBus;
|
||||
private final FirstMeetingService firstMeetingService;
|
||||
|
||||
@ -35,14 +35,14 @@ public class IdeaExportWorker extends AbstractWorker {
|
||||
public IdeaExportWorker(final IdeaService ideaService,
|
||||
final MailEventService mailService,
|
||||
final ProjectService projectService,
|
||||
final Set<IdeaCreationJudge> ideaCreationJudges,
|
||||
final IdeaCreationJudge ideaCreationJudge,
|
||||
final EventBus eventBus,
|
||||
final FirstMeetingService firstMeetingService)
|
||||
{
|
||||
this.ideaService = ideaService;
|
||||
this.mailService = mailService;
|
||||
this.projectService = projectService;
|
||||
this.ideaCreationJudges = ideaCreationJudges;
|
||||
this.ideaCreationJudge = ideaCreationJudge;
|
||||
this.eventBus = eventBus;
|
||||
this.firstMeetingService = firstMeetingService;
|
||||
}
|
||||
@ -55,7 +55,7 @@ public class IdeaExportWorker extends AbstractWorker {
|
||||
Decision decision = isAllowedToStart(idea);
|
||||
if (decision.isAllowed()) {
|
||||
allow(idea);
|
||||
createProject(idea);
|
||||
createProject(idea, decision.getIdentifier());
|
||||
eventBus.post(new ProjectStartedEvent(idea));
|
||||
} else {
|
||||
deny(idea, decision.getReason());
|
||||
@ -74,13 +74,7 @@ public class IdeaExportWorker extends AbstractWorker {
|
||||
}
|
||||
|
||||
private Decision isAllowedToStart(final Idea idea) {
|
||||
for (IdeaCreationJudge ideaCreationJudge : ideaCreationJudges) {
|
||||
Decision decision = ideaCreationJudge.ruling(idea);
|
||||
if (!decision.isAllowed()) {
|
||||
return decision;
|
||||
}
|
||||
}
|
||||
return Decision.allowed();
|
||||
return ideaCreationJudge.ruling(idea);
|
||||
}
|
||||
|
||||
|
||||
@ -101,7 +95,7 @@ public class IdeaExportWorker extends AbstractWorker {
|
||||
ideaService.save(idea);
|
||||
}
|
||||
|
||||
private void createProject(Idea idea) {
|
||||
private void createProject(Idea idea, Integer identifier) {
|
||||
beginTransaction();
|
||||
LOGGER.info("Exporting idea: {}", idea);
|
||||
Project project = Project.builder()
|
||||
@ -110,6 +104,7 @@ public class IdeaExportWorker extends AbstractWorker {
|
||||
.startDate(getCourseStartDate(idea))
|
||||
.headSupervisor(idea.getMatch().getSupervisor())
|
||||
.projectParticipants(getAuthors(idea))
|
||||
.identifier(identifier)
|
||||
.build();
|
||||
project.setExpectedEndDate(idea.getApplicationPeriod().getCourseEndDate());
|
||||
project.setResearchArea(idea.getResearchArea());
|
||||
|
@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS `national_subject_category` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`external_id` INT NOT NULL,
|
||||
`swedish_name` VARCHAR(255) NOT NULL,
|
||||
`english_name` VARCHAR(255) NOT NULL,
|
||||
`active` BOOLEAN NOT NULL,
|
||||
`preselected` BOOLEAN NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `U_national_subject_category_external_id` (`external_id`)
|
||||
);
|
@ -37,9 +37,7 @@ public class Daisy implements IdeaCreationJudge {
|
||||
|
||||
try {
|
||||
exporterFacade.exportProject(project, project.getHeadSupervisor().getUnit());
|
||||
externalExporter.deleteProject(project);
|
||||
project.setIdentifier(null);
|
||||
return Decision.allowed();
|
||||
return Decision.allowed(project.getIdentifier());
|
||||
} catch (ExternalExportException e) {
|
||||
return Decision.denied(e.getMessage());
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ public class DaisyModule extends ServletModule {
|
||||
bind(ExternalImporter.class).to(ExternalImporterDaisyImpl.class);
|
||||
bind(ImporterTransactions.class).to(ImporterTransactionsImpl.class);
|
||||
|
||||
Multibinder<IdeaCreationJudge> judges = Multibinder.newSetBinder(binder(), IdeaCreationJudge.class);
|
||||
judges.addBinding().to(Daisy.class);
|
||||
OptionalBinder.newOptionalBinder(binder(), IdeaCreationJudge.class)
|
||||
.setBinding().to(Daisy.class);
|
||||
|
||||
bind(ExternalExporter.class).to(ExternalExporterDaisyImpl.class);
|
||||
bind(UserImportWorker.class);
|
||||
|
@ -15,11 +15,13 @@ public class DaisyWorkerInitialization {
|
||||
Provider<UserImportWorker> userImportWorker,
|
||||
Provider<ProjectFinalizer> projectFinalizer,
|
||||
Provider<RejectedThesisWorker> rejectedThesisWorkerProvider,
|
||||
Provider<GradingCompletedMilestoneActivator> gradingFinalizer) {
|
||||
Provider<GradingCompletedMilestoneActivator> gradingFinalizer,
|
||||
Provider<ImportNationalCategories> importNationalCategories) {
|
||||
scheduler.schedule("Export projects to daisy").runBy(projectExporter).dailyAt(1, 0);
|
||||
scheduler.schedule("Remote supervisor (and projects) bulk import").runBy(userImportWorker).dailyAt(1, 30);
|
||||
scheduler.schedule("Mark projects as completed").runBy(projectFinalizer).dailyAt(2, 0);
|
||||
scheduler.schedule("Mark the 'grading completed' milestone as completed").runBy(gradingFinalizer).dailyAt(2, 30);
|
||||
scheduler.schedule("Reject thesis based on examiner rejection in Daisy").runBy(rejectedThesisWorkerProvider).every(5, TimeUnit.MINUTES);
|
||||
scheduler.schedule("Import national subject categories").runBy(importNationalCategories).dailyAt(3, 0);
|
||||
}
|
||||
}
|
||||
|
50
daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/workers/ImportNationalCategories.java
Normal file
50
daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/workers/ImportNationalCategories.java
Normal file
@ -0,0 +1,50 @@
|
||||
package se.su.dsv.scipro.integration.daisy.workers;
|
||||
|
||||
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
|
||||
import se.su.dsv.scipro.grading.NationalSubjectCategory;
|
||||
import se.su.dsv.scipro.grading.NationalSubjectCategoryService;
|
||||
import se.su.dsv.scipro.io.dto.ResearchSubject;
|
||||
import se.su.dsv.scipro.workerthreads.AbstractWorker;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ImportNationalCategories extends AbstractWorker {
|
||||
private static final int DSV = 4;
|
||||
|
||||
private final DaisyAPI daisyAPI;
|
||||
private final NationalSubjectCategoryService nationalSubjectCategoryService;
|
||||
|
||||
@Inject
|
||||
public ImportNationalCategories(DaisyAPI daisyAPI, NationalSubjectCategoryService nationalSubjectCategoryService) {
|
||||
this.daisyAPI = daisyAPI;
|
||||
this.nationalSubjectCategoryService = nationalSubjectCategoryService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWork() {
|
||||
List<ResearchSubject> nationalResearchSubjects = daisyAPI.getNationalResearchSubjects(DSV);
|
||||
for (ResearchSubject researchSubject : nationalResearchSubjects) {
|
||||
Optional<NationalSubjectCategory> nationalSubjectCategory =
|
||||
nationalSubjectCategoryService.findByExternalId(researchSubject.getExternalID());
|
||||
if (nationalSubjectCategory.isEmpty()) {
|
||||
NationalSubjectCategory newSubjectCategory = new NationalSubjectCategory();
|
||||
newSubjectCategory.setExternalId(researchSubject.getExternalID());
|
||||
newSubjectCategory.setSwedishName(researchSubject.getName());
|
||||
newSubjectCategory.setEnglishName(researchSubject.getNameEn());
|
||||
newSubjectCategory.setActive(researchSubject.isActive());
|
||||
newSubjectCategory.setPreselected(researchSubject.isPreselected());
|
||||
nationalSubjectCategoryService.save(newSubjectCategory);
|
||||
}
|
||||
else {
|
||||
NationalSubjectCategory existingSubjectCategory = nationalSubjectCategory.get();
|
||||
existingSubjectCategory.setSwedishName(researchSubject.getName());
|
||||
existingSubjectCategory.setEnglishName(researchSubject.getNameEn());
|
||||
existingSubjectCategory.setActive(researchSubject.isActive());
|
||||
existingSubjectCategory.setPreselected(researchSubject.isPreselected());
|
||||
nationalSubjectCategoryService.save(existingSubjectCategory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -51,7 +51,7 @@
|
||||
</p>
|
||||
<textarea class="form-control" rows="10" wicket:id="overall_motivation"></textarea>
|
||||
</div>
|
||||
<wicket:enclosure child="grading_basis_requirements_not_met">
|
||||
<wicket:container wicket:id="grading_basis_missing">
|
||||
<h4 class="mt-3">Criteria not met</h4>
|
||||
<ul>
|
||||
<li wicket:id="grading_basis_requirements_not_met">
|
||||
@ -61,8 +61,11 @@
|
||||
<span wicket:id="required_points"></span> required to pass
|
||||
</wicket:message>
|
||||
</li>
|
||||
<li wicket:id="overall_motivation_missing">
|
||||
Overall motivation not filled in
|
||||
</li>
|
||||
</ul>
|
||||
</wicket:enclosure>
|
||||
</wicket:container>
|
||||
<wicket:enclosure child="save">
|
||||
<div class="position-sticky bottom-0 bg-white py-3 d-flex">
|
||||
<button class="btn btn-success me-3" wicket:id="save">
|
||||
|
@ -98,7 +98,16 @@ public class GradingBasisPanel extends GenericPanel<Project> {
|
||||
assessment.getPoints(),
|
||||
0) < assessment.criterion().minimumPoints())
|
||||
.toList());
|
||||
add(new AutoHidingListView<>("grading_basis_requirements_not_met", criteriaNotMet) {
|
||||
WebMarkupContainer gradingBasisMissing = new WebMarkupContainer("grading_basis_missing") {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
String overallMotivation = gradingBasis.getObject().getOverallMotivation();
|
||||
setVisible(!criteriaNotMet.getObject().isEmpty() || overallMotivation == null || overallMotivation.isBlank());
|
||||
}
|
||||
};
|
||||
add(gradingBasisMissing);
|
||||
gradingBasisMissing.add(new AutoHidingListView<>("grading_basis_requirements_not_met", criteriaNotMet) {
|
||||
@Override
|
||||
protected void populateItem(ListItem<Assessment> item) {
|
||||
IModel<Criterion> criterion = item.getModel().map(Assessment::criterion);
|
||||
@ -108,12 +117,19 @@ public class GradingBasisPanel extends GenericPanel<Project> {
|
||||
item.add(new Label("required_points", criterion.map(Criterion::minimumPoints)));
|
||||
}
|
||||
});
|
||||
gradingBasisMissing.add(new WebMarkupContainer("overall_motivation_missing") {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
String overallMotivation = gradingBasis.getObject().getOverallMotivation();
|
||||
setVisible(overallMotivation == null || overallMotivation.isBlank());
|
||||
}
|
||||
});
|
||||
|
||||
IModel<String> overallMotivation = LambdaModel.of(gradingBasis,
|
||||
GradingBasis::getOverallMotivation,
|
||||
GradingBasis::setOverallMotivation);
|
||||
TextArea<String> overallMotivationField = new TextArea<>("overall_motivation", overallMotivation);
|
||||
overallMotivationField.setRequired(true);
|
||||
add(overallMotivationField);
|
||||
|
||||
add(new Label("rejection_comment", gradingBasis.map(GradingBasis::rejectionComment)) {
|
||||
|
@ -38,17 +38,18 @@
|
||||
<li wicket:id="status_plagiarism"></li>
|
||||
<li>
|
||||
<div wicket:id="status_grading_basis">></div>
|
||||
<wicket:enclosure child="grading_basis_requirements_not_met">
|
||||
<ul>
|
||||
<li wicket:id="grading_basis_requirements_not_met">
|
||||
<wicket:message key="criteria_not_met">
|
||||
<span wicket:id="title">[U1 title]</span>
|
||||
<span wicket:id="given_points"></span>/<span wicket:id="maximum_points"></span>
|
||||
<span wicket:id="required_points"></span> required to pass
|
||||
</wicket:message>
|
||||
</li>
|
||||
</ul>
|
||||
</wicket:enclosure>
|
||||
<ul wicket:id="grading_basis_missing">
|
||||
<li wicket:id="grading_basis_requirements_not_met">
|
||||
<wicket:message key="criteria_not_met">
|
||||
<span wicket:id="title">[U1 title]</span>
|
||||
<span wicket:id="given_points"></span>/<span wicket:id="maximum_points"></span>
|
||||
<span wicket:id="required_points"></span> required to pass
|
||||
</wicket:message>
|
||||
</li>
|
||||
<li wicket:id="grading_basis_overall_motivation_missing">
|
||||
Overall motivation not filled in
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<div wicket:id="status_individual_assessment"></div>
|
||||
|
@ -84,7 +84,15 @@ public class IndividualAuthorAssessment extends GenericPanel<User> {
|
||||
|
||||
add(new UserLabel("author_name", authorModel));
|
||||
|
||||
add(new AutoHidingListView<>("grading_basis_requirements_not_met", gradingBasisCriterionNotMet) {
|
||||
WebMarkupContainer gradingBasisMissing = new WebMarkupContainer("grading_basis_missing") {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
setVisible(!hasFilledInGradingBasis.getObject());
|
||||
}
|
||||
};
|
||||
add(gradingBasisMissing);
|
||||
gradingBasisMissing.add(new AutoHidingListView<>("grading_basis_requirements_not_met", gradingBasisCriterionNotMet) {
|
||||
@Override
|
||||
protected void populateItem(ListItem<GradingCriterion> item) {
|
||||
item.add(new Label("title", item.getModel().map(GradingCriterion::getTitle)));
|
||||
@ -93,6 +101,13 @@ public class IndividualAuthorAssessment extends GenericPanel<User> {
|
||||
item.add(new Label("required_points", item.getModel().map(GradingCriterion::getPointsRequiredToPass)));
|
||||
}
|
||||
});
|
||||
gradingBasisMissing.add(new WebMarkupContainer("grading_basis_overall_motivation_missing") {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
setVisible(!gradingReport.getObject().hasProvidedOverallMotivation());
|
||||
}
|
||||
});
|
||||
add(new AutoHidingListView<>("individual_assessment_requirements_not_met", individualCriterionNotMet) {
|
||||
@Override
|
||||
protected void populateItem(ListItem<GradingCriterion> item) {
|
||||
@ -164,7 +179,7 @@ public class IndividualAuthorAssessment extends GenericPanel<User> {
|
||||
boolean criteriaMet = supervisorGradingReport.getProjectCriteria()
|
||||
.stream()
|
||||
.allMatch(GradingCriterion::meetsMinimumPointRequirement);
|
||||
return criteriaMet && supervisorGradingReport.hasProvidedRejectionFeedback();
|
||||
return criteriaMet && supervisorGradingReport.hasProvidedRejectionFeedback() && supervisorGradingReport.hasProvidedOverallMotivation();
|
||||
}
|
||||
|
||||
private void redGreen(String id, IModel<Boolean> finished, String redTextKey, String greenTextKey) {
|
||||
|
@ -163,7 +163,7 @@ public class SupervisorGradingReportPage extends AbstractSupervisorProjectDetail
|
||||
boolean criteriaMet = supervisorGradingReport.getProjectCriteria()
|
||||
.stream()
|
||||
.allMatch(GradingCriterion::meetsMinimumPointRequirement);
|
||||
return criteriaMet && supervisorGradingReport.hasProvidedRejectionFeedback();
|
||||
return criteriaMet && supervisorGradingReport.hasProvidedRejectionFeedback() && supervisorGradingReport.hasProvidedOverallMotivation();
|
||||
}
|
||||
|
||||
private boolean individualCriteriaDone(SupervisorGradingReport supervisorGradingReport) {
|
||||
|
@ -19,7 +19,6 @@ import se.su.dsv.scipro.test.DomainObjects;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -46,7 +45,7 @@ public class IdeaExportWorkerTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
worker = new IdeaExportWorker(ideaService, mailService, projectService, Collections.singleton(ideaCreationJudge), eventBus, firstMeetingService) {
|
||||
worker = new IdeaExportWorker(ideaService, mailService, projectService, ideaCreationJudge, eventBus, firstMeetingService) {
|
||||
@Override
|
||||
protected void beginTransaction() {
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user