Allow supervisors to request improvements from final seminar opponents #78

Merged
niat8586 merged 41 commits from opponent-completion into develop 2025-03-05 10:05:38 +01:00
44 changed files with 275 additions and 124 deletions
Showing only changes of commit a20455df97 - Show all commits

View File

@ -17,7 +17,7 @@ import se.su.dsv.scipro.checklist.ChecklistAnswerServiceImpl;
import se.su.dsv.scipro.checklist.ChecklistServiceImpl; import se.su.dsv.scipro.checklist.ChecklistServiceImpl;
import se.su.dsv.scipro.checklist.ChecklistTemplateService; import se.su.dsv.scipro.checklist.ChecklistTemplateService;
import se.su.dsv.scipro.checklist.ChecklistTemplateServiceImpl; import se.su.dsv.scipro.checklist.ChecklistTemplateServiceImpl;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPIImpl; import se.su.dsv.scipro.daisyexternal.http.DaisyAPIImpl;
import se.su.dsv.scipro.date.DateServiceImpl; import se.su.dsv.scipro.date.DateServiceImpl;
import se.su.dsv.scipro.file.FileDescriptionRepo; import se.su.dsv.scipro.file.FileDescriptionRepo;
import se.su.dsv.scipro.file.FileReferenceRepository; import se.su.dsv.scipro.file.FileReferenceRepository;

View File

@ -226,6 +226,11 @@ public class DataInitializer implements Lifecycle {
stina_student = createStudent(STUDENT_2); stina_student = createStudent(STUDENT_2);
sid_student = createStudent(STUDENT_3); sid_student = createStudent(STUDENT_3);
simon_student = createStudent(STUDENT_4); simon_student = createStudent(STUDENT_4);
// Used to test submitting ideas
// can not be used as author on any idea
// can not be used as author on any project
createStudent("Stig");
} }
private User createStudent(String firstName) { private User createStudent(String firstName) {

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.exceptions; package se.su.dsv.scipro.daisyexternal.exceptions;
public class ExternalImportException extends RuntimeException { public class ExternalImportException extends RuntimeException {

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http; package se.su.dsv.scipro.daisyexternal.http;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import java.io.InputStream; import java.io.InputStream;
@ -6,7 +6,26 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import se.su.dsv.scipro.io.dto.*; import se.su.dsv.scipro.io.dto.AddThesisAuthor;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.CourseRegistration;
import se.su.dsv.scipro.io.dto.Employee;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Program;
import se.su.dsv.scipro.io.dto.ProgramAdmission;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.PublishingConsent;
import se.su.dsv.scipro.io.dto.PublishingConsentLevel;
import se.su.dsv.scipro.io.dto.ResearchArea;
import se.su.dsv.scipro.io.dto.ResearchSubject;
import se.su.dsv.scipro.io.dto.StudentProgramAdmission;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisPublication;
import se.su.dsv.scipro.io.dto.ThesisRejection;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.dto.Unit;
import se.su.dsv.scipro.io.dto.UserName;
public interface DaisyAPI { public interface DaisyAPI {
Set<ProjectParticipant> getContributors(Integer projectId); Set<ProjectParticipant> getContributors(Integer projectId);

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http; package se.su.dsv.scipro.daisyexternal.http;
import static jakarta.ws.rs.client.Entity.xml; import static jakarta.ws.rs.client.Entity.xml;
@ -16,9 +16,33 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import java.io.InputStream; import java.io.InputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import se.su.dsv.scipro.io.dto.*; import se.su.dsv.scipro.io.dto.AddThesisAuthor;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.CourseRegistration;
import se.su.dsv.scipro.io.dto.Employee;
import se.su.dsv.scipro.io.dto.ObjectFactory;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Program;
import se.su.dsv.scipro.io.dto.ProgramAdmission;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.PublishingConsent;
import se.su.dsv.scipro.io.dto.PublishingConsentLevel;
import se.su.dsv.scipro.io.dto.ResearchArea;
import se.su.dsv.scipro.io.dto.ResearchSubject;
import se.su.dsv.scipro.io.dto.StudentProgramAdmission;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisPublication;
import se.su.dsv.scipro.io.dto.ThesisRejection;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.dto.Unit;
import se.su.dsv.scipro.io.dto.UserName;
public class DaisyAPIImpl implements DaisyAPI { public class DaisyAPIImpl implements DaisyAPI {
@ -364,8 +388,7 @@ public class DaisyAPIImpl implements DaisyAPI {
@Override @Override
public OrganisationalUnit orgunit(final int unitId) { public OrganisationalUnit orgunit(final int unitId) {
return () -> return () ->
target() units()
.path("orgunit")
.path(Integer.toString(unitId)) .path(Integer.toString(unitId))
.path("researchAreas") .path("researchAreas")
.request(MediaType.APPLICATION_XML_TYPE) .request(MediaType.APPLICATION_XML_TYPE)

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http; package se.su.dsv.scipro.daisyexternal.http;
import java.util.List; import java.util.List;
import se.su.dsv.scipro.io.dto.ResearchArea; import se.su.dsv.scipro.io.dto.ResearchArea;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http; package se.su.dsv.scipro.daisyexternal.http;
import java.io.InputStream; import java.io.InputStream;
import java.util.function.Function; import java.util.function.Function;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http; package se.su.dsv.scipro.daisyexternal.http;
public abstract class Semester { public abstract class Semester {

View File

@ -1,9 +1,6 @@
package se.su.dsv.scipro.workerthreads; package se.su.dsv.scipro.workerthreads;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityTransaction;
import java.util.Date; import java.util.Date;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -58,6 +55,22 @@ public abstract class AbstractWorker implements Worker {
* Do manually transaction-handled work * Do manually transaction-handled work
*/ */
try { try {
// When the switch from Guice to Spring happened all workers became singletons
// because that's the default in Spring. In Guice they were "prototype" scoped
// and therefore the worker object was re-created before each execution which
// reset the successfulWorker field to true.
//
// Now that they're singletons the field is never reset to true after a
// failure and the worker will be stuck in a failed state even after a
// subsequent successful run.
//
// TODO:
// In the future this flag should be removed and any execution that does
// not throw an exception should be considered successful.
// If a worker needs to signal a non-exception as a failure that should
// be an internal matter and not something the scheduler should consider.
setSuccessfulWorker(true);
doWork(); doWork();
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
LOGGER.info("Worker {} threw an exception", getClass().getSimpleName()); LOGGER.info("Worker {} threw an exception", getClass().getSimpleName());

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" <jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
version="3.0"> version="3.0">
<jaxb:globalBindings> <jaxb:globalBindings>
<!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime --> <!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime -->
@ -12,4 +13,11 @@
<xjc:simple /> <xjc:simple />
<xjc:serializable uid="1" /> <xjc:serializable uid="1" />
</jaxb:globalBindings> </jaxb:globalBindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="../xsd/daisy_api.xsd" node="/xs:schema">
<jaxb:bindings node="xs:simpleType[@name='status']" >
<jaxb:typesafeEnumClass name="Status2" />
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0" <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="addThesisAuthor" type="addThesisAuthor"/> <xs:element name="addThesisAuthor" type="addThesisAuthor"/>
<xs:element name="courseRegistrationForCourse" type="courseRegistrationGet"/> <xs:element name="courseRegistrationForCourse" type="courseRegistrationGet"/>
@ -62,6 +60,7 @@
<xs:element name="degree" type="degree"/> <xs:element name="degree" type="degree"/>
<xs:element name="programAdmission" type="programAdmission"/> <xs:element name="programAdmission" type="programAdmission"/>
<xs:element name="student" type="student"/> <xs:element name="student" type="student"/>
<xs:complexType name="addThesisAuthor"> <xs:complexType name="addThesisAuthor">
<xs:sequence> <xs:sequence>
<xs:element name="student" type="AddThesisAuthorStudent" minOccurs="1"> <xs:element name="student" type="AddThesisAuthorStudent" minOccurs="1">
@ -75,6 +74,8 @@
<xs:sequence> <xs:sequence>
<xs:element name="level" type="educationalLevel" minOccurs="1"> <xs:element name="level" type="educationalLevel" minOccurs="1">
</xs:element> </xs:element>
<xs:element name="courseCredits" type="xs:decimal" minOccurs="0">
</xs:element>
<xs:element name="department" type="serializableUnit" minOccurs="1"> <xs:element name="department" type="serializableUnit" minOccurs="1">
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
@ -615,6 +616,8 @@
</xs:element> </xs:element>
<xs:element name="break" type="xs:boolean" minOccurs="1"> <xs:element name="break" type="xs:boolean" minOccurs="1">
</xs:element> </xs:element>
<xs:element name="reparticipant" type="xs:boolean" minOccurs="1">
</xs:element>
<xs:element name="inactive" type="xs:boolean" minOccurs="1"> <xs:element name="inactive" type="xs:boolean" minOccurs="1">
</xs:element> </xs:element>
<xs:element name="userName" type="xs:string" minOccurs="0"> <xs:element name="userName" type="xs:string" minOccurs="0">

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http; package se.su.dsv.scipro.daisyexternal.http;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal; package se.su.dsv.scipro.daisyexternal;
/** /**
* Specifies interaction of an importing service component. * Specifies interaction of an importing service component.

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal; package se.su.dsv.scipro.daisyexternal;
import java.util.Map; import java.util.Map;
import se.su.dsv.scipro.io.dto.Person; import se.su.dsv.scipro.io.dto.Person;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.impl; package se.su.dsv.scipro.daisyexternal.impl;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
@ -6,10 +6,10 @@ import jakarta.ws.rs.ClientErrorException;
import java.util.*; import java.util.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.ExternalImporter; import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions; import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.exceptions.ExternalImportException; import se.su.dsv.scipro.daisyexternal.exceptions.ExternalImportException;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Employee; import se.su.dsv.scipro.io.dto.Employee;
import se.su.dsv.scipro.io.dto.Person; import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Thesis; import se.su.dsv.scipro.io.dto.Thesis;

View File

@ -1,23 +1,43 @@
package se.su.dsv.scipro.daisyExternal.impl; package se.su.dsv.scipro.daisyexternal.impl;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Named; import jakarta.inject.Named;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import java.util.*; import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions; import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.*; import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Course;
import se.su.dsv.scipro.io.dto.CourseRegistration;
import se.su.dsv.scipro.io.dto.EducationalLevel;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProgramType;
import se.su.dsv.scipro.io.dto.ResearchArea; import se.su.dsv.scipro.io.dto.ResearchArea;
import se.su.dsv.scipro.io.dto.StudentProgramAdmission;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.UserName;
import se.su.dsv.scipro.match.ProgramService; import se.su.dsv.scipro.match.ProgramService;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.project.ProjectService; import se.su.dsv.scipro.project.ProjectService;
import se.su.dsv.scipro.security.auth.roles.Roles; import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.system.*; import se.su.dsv.scipro.system.DegreeType;
import se.su.dsv.scipro.system.Language;
import se.su.dsv.scipro.system.Program; import se.su.dsv.scipro.system.Program;
import se.su.dsv.scipro.system.ResearchAreaService;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.system.UserNameService;
import se.su.dsv.scipro.system.UserService;
import se.su.dsv.scipro.system.Username;
import se.su.dsv.scipro.util.Pair; import se.su.dsv.scipro.util.Pair;
@Named @Named

View File

@ -4,7 +4,7 @@ import jakarta.inject.Inject;
import jakarta.ws.rs.ProcessingException; import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.WebApplicationException;
import java.util.List; import java.util.List;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalthesis.PublishingConsentService; import se.su.dsv.scipro.finalthesis.PublishingConsentService;
import se.su.dsv.scipro.io.dto.PublishingConsentLevel; import se.su.dsv.scipro.io.dto.PublishingConsentLevel;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;

View File

@ -5,11 +5,11 @@ import jakarta.inject.Provider;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import se.su.dsv.scipro.daisyExternal.ExternalImporter; import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions; import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.impl.ExternalImporterDaisyImpl; import se.su.dsv.scipro.daisyexternal.impl.ExternalImporterDaisyImpl;
import se.su.dsv.scipro.daisyExternal.impl.ImporterTransactionsImpl; import se.su.dsv.scipro.daisyexternal.impl.ImporterTransactionsImpl;
import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.finalthesis.FinalThesisService; import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.forum.ProjectForumService; import se.su.dsv.scipro.forum.ProjectForumService;

View File

@ -9,7 +9,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.security.auth.roles.Roles; import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.system.User; import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.system.UserSearchProvider; import se.su.dsv.scipro.system.UserSearchProvider;

View File

@ -6,7 +6,7 @@ import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person; import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant; import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.Role; import se.su.dsv.scipro.io.dto.Role;

View File

@ -9,7 +9,7 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.GradingCompletedEvent; import se.su.dsv.scipro.grading.GradingCompletedEvent;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant; import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Course; import se.su.dsv.scipro.io.dto.Course;

View File

@ -3,7 +3,7 @@ package se.su.dsv.scipro.integration.daisy.workers;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.NationalSubjectCategory; import se.su.dsv.scipro.grading.NationalSubjectCategory;
import se.su.dsv.scipro.grading.NationalSubjectCategoryService; import se.su.dsv.scipro.grading.NationalSubjectCategoryService;
import se.su.dsv.scipro.io.dto.ResearchSubject; import se.su.dsv.scipro.io.dto.ResearchSubject;

View File

@ -16,14 +16,22 @@ import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalseminar.FinalSeminar; import se.su.dsv.scipro.finalseminar.FinalSeminar;
import se.su.dsv.scipro.finalseminar.FinalSeminarParticipation; import se.su.dsv.scipro.finalseminar.FinalSeminarParticipation;
import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.finalthesis.FinalThesis; import se.su.dsv.scipro.finalthesis.FinalThesis;
import se.su.dsv.scipro.finalthesis.FinalThesisService; import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.io.ExternalExporter; import se.su.dsv.scipro.io.ExternalExporter;
import se.su.dsv.scipro.io.dto.*; import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.ResearchAreaWithID;
import se.su.dsv.scipro.io.dto.ResearchAreas;
import se.su.dsv.scipro.io.dto.Role;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.dto.UnitWithID;
import se.su.dsv.scipro.io.exceptions.ExternalExportException; import se.su.dsv.scipro.io.exceptions.ExternalExportException;
import se.su.dsv.scipro.io.facade.ExporterFacade; import se.su.dsv.scipro.io.facade.ExporterFacade;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;

View File

@ -6,7 +6,7 @@ import java.time.Instant;
import java.util.Optional; import java.util.Optional;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.ThesisApprovedHistoryService; import se.su.dsv.scipro.grading.ThesisApprovedHistoryService;
import se.su.dsv.scipro.io.dto.STATUS; import se.su.dsv.scipro.io.dto.STATUS;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;

View File

@ -4,7 +4,7 @@ import jakarta.inject.Inject;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalthesis.FinalThesis; import se.su.dsv.scipro.finalthesis.FinalThesis;
import se.su.dsv.scipro.finalthesis.FinalThesisService; import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.forum.ProjectForumService; import se.su.dsv.scipro.forum.ProjectForumService;

View File

@ -8,10 +8,10 @@ import java.util.*;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.ExternalImporter; import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions; import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.http.Semester; import se.su.dsv.scipro.daisyexternal.http.Semester;
import se.su.dsv.scipro.io.dto.Person; import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Program; import se.su.dsv.scipro.io.dto.Program;
import se.su.dsv.scipro.io.dto.ProgramAdmission; import se.su.dsv.scipro.io.dto.ProgramAdmission;

View File

@ -2,18 +2,26 @@ package se.su.dsv.scipro.io.impl;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import java.math.BigDecimal;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.ExternalExporter; import se.su.dsv.scipro.io.ExternalExporter;
import se.su.dsv.scipro.io.dto.*; import se.su.dsv.scipro.io.dto.AddThesisAuthor;
import se.su.dsv.scipro.io.dto.AddThesisAuthorCourse;
import se.su.dsv.scipro.io.dto.AddThesisAuthorStudent;
import se.su.dsv.scipro.io.dto.EducationalLevel;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.ResearchAreaWithID;
import se.su.dsv.scipro.io.dto.ResearchAreas;
import se.su.dsv.scipro.io.dto.Role;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.io.dto.UnitWithID;
import se.su.dsv.scipro.io.exceptions.ExternalExportException; import se.su.dsv.scipro.io.exceptions.ExternalExportException;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.reusable.SciProUtilities; import se.su.dsv.scipro.reusable.SciProUtilities;
import se.su.dsv.scipro.system.DegreeType;
import se.su.dsv.scipro.system.Unit; import se.su.dsv.scipro.system.Unit;
import se.su.dsv.scipro.system.User; import se.su.dsv.scipro.system.User;
@ -23,14 +31,6 @@ public class ExternalExporterDaisyImpl implements ExternalExporter {
static final int MAX_TITLE_LENGTH = 255; static final int MAX_TITLE_LENGTH = 255;
private static final int DSV = 4; private static final int DSV = 4;
private static Map<DegreeType, EducationalLevel> classMap = new HashMap<>() {
{
put(DegreeType.NONE, EducationalLevel.UNKNOWN);
put(DegreeType.BACHELOR, EducationalLevel.FIRST_CYCLE);
put(DegreeType.MAGISTER, EducationalLevel.SECOND_CYCLE);
put(DegreeType.MASTER, EducationalLevel.SECOND_CYCLE);
}
};
private final DaisyAPI api; private final DaisyAPI api;
@ -82,7 +82,21 @@ public class ExternalExporterDaisyImpl implements ExternalExporter {
} }
private EducationalLevel toDaisyLevel(Project project) { private EducationalLevel toDaisyLevel(Project project) {
return classMap.get(project.getProjectTypeDegreeType()); return switch (project.getProjectTypeDegreeType()) {
case NONE -> EducationalLevel.UNKNOWN;
case BACHELOR -> EducationalLevel.FIRST_CYCLE;
case MAGISTER -> EducationalLevel.SECOND_CYCLE;
case MASTER -> EducationalLevel.SECOND_CYCLE;
};
}
private static BigDecimal toDaisyCredits(Project project) {
return switch (project.getProjectTypeDegreeType()) {
case BACHELOR -> BigDecimal.valueOf(15);
case MAGISTER -> BigDecimal.valueOf(15);
case MASTER -> BigDecimal.valueOf(30);
case NONE -> null;
};
} }
@Override @Override
@ -95,6 +109,7 @@ public class ExternalExporterDaisyImpl implements ExternalExporter {
AddThesisAuthorCourse authorCourse = new AddThesisAuthorCourse(); AddThesisAuthorCourse authorCourse = new AddThesisAuthorCourse();
authorCourse.setLevel(toDaisyLevel(project)); authorCourse.setLevel(toDaisyLevel(project));
authorCourse.setDepartment(department); authorCourse.setDepartment(department);
authorCourse.setCourseCredits(toDaisyCredits(project));
AddThesisAuthor addThesisAuthor = new AddThesisAuthor(); AddThesisAuthor addThesisAuthor = new AddThesisAuthor();
addThesisAuthor.setCourse(authorCourse); addThesisAuthor.setCourse(authorCourse);

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.impl; package se.su.dsv.scipro.daisyexternal.impl;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
@ -9,8 +9,8 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions; import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person; import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.springdata.services.UnitService; import se.su.dsv.scipro.springdata.services.UnitService;
import se.su.dsv.scipro.system.UserImportService; import se.su.dsv.scipro.system.UserImportService;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.impl; package se.su.dsv.scipro.daisyexternal.impl;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.AdditionalAnswers.returnsFirstArg;
@ -12,12 +12,17 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person; import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.UserName; import se.su.dsv.scipro.io.dto.UserName;
import se.su.dsv.scipro.match.ProgramService; import se.su.dsv.scipro.match.ProgramService;
import se.su.dsv.scipro.project.ProjectService; import se.su.dsv.scipro.project.ProjectService;
import se.su.dsv.scipro.system.*; import se.su.dsv.scipro.system.ProjectTypeService;
import se.su.dsv.scipro.system.ResearchAreaService;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.system.UserNameService;
import se.su.dsv.scipro.system.UserService;
import se.su.dsv.scipro.system.Username;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class ImporterTransactionsImplTest { public class ImporterTransactionsImplTest {

View File

@ -11,7 +11,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.GradingCompletedEvent; import se.su.dsv.scipro.grading.GradingCompletedEvent;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant; import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Course; import se.su.dsv.scipro.io.dto.Course;

View File

@ -14,11 +14,16 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.finalthesis.FinalThesisService; import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.io.ExternalExporter; import se.su.dsv.scipro.io.ExternalExporter;
import se.su.dsv.scipro.io.dto.*; import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.Role;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.facade.ExporterFacade; import se.su.dsv.scipro.io.facade.ExporterFacade;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.project.ProjectRepo; import se.su.dsv.scipro.project.ProjectRepo;

View File

@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.ThesisApprovedHistoryService; import se.su.dsv.scipro.grading.ThesisApprovedHistoryService;
import se.su.dsv.scipro.io.dto.STATUS; import se.su.dsv.scipro.io.dto.STATUS;
import se.su.dsv.scipro.io.dto.Thesis; import se.su.dsv.scipro.io.dto.Thesis;

View File

@ -4,15 +4,19 @@ import static java.util.Arrays.asList;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import java.util.*; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.ExternalImporter; import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions; import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person; import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Thesis; import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.match.ProgramService; import se.su.dsv.scipro.match.ProgramService;

View File

@ -16,7 +16,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated; import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.reusable.SciProUtilities; import se.su.dsv.scipro.reusable.SciProUtilities;

View File

@ -72,4 +72,22 @@
</notes> </notes>
<cve>CVE-2024-23076</cve> <cve>CVE-2024-23076</cve>
</suppress> </suppress>
<suppress>
<notes>
https://nvd.nist.gov/vuln/detail/CVE-2024-49203
https://github.com/querydsl/querydsl/issues/3757
Basically if you allow untrusted user input to be used in the "ORDER BY" clause
you can be vulnerable to SQL injection.
I believe this is nonsense and akin to saying every Java application has a
security vulnerability because JDBC allows you to execute arbitrary SQL if you
do not properly use PreparedStatement with parameters over a string-concatenated
Statement.
Even if this is considered a valid vulnerability we do not, currently, allow
untrusted user input to be used in the "ORDER BY" clause.
</notes>
<cve>CVE-2024-49203</cve>
</suppress>
</suppressions> </suppressions>

View File

@ -24,7 +24,7 @@
<!-- Dependency versions --> <!-- Dependency versions -->
<slf4j.version>2.0.7</slf4j.version> <slf4j.version>2.0.7</slf4j.version>
<log4j2.version>2.20.0</log4j2.version> <log4j2.version>2.20.0</log4j2.version>
<wicket.version>10.1.0</wicket.version> <wicket.version>10.4.0</wicket.version>
<!-- See https://hibernate.org/orm/releases/ for which version Hibernate implements --> <!-- See https://hibernate.org/orm/releases/ for which version Hibernate implements -->
<jakarta.persistence-api.version>3.1.0</jakarta.persistence-api.version> <jakarta.persistence-api.version>3.1.0</jakarta.persistence-api.version>
@ -39,6 +39,8 @@
<jersey.version>3.1.6</jersey.version> <jersey.version>3.1.6</jersey.version>
<poi.version>5.2.5</poi.version> <poi.version>5.2.5</poi.version>
<jackson.version>2.17.0</jackson.version> <jackson.version>2.17.0</jackson.version>
<spring.boot.version>3.4.1</spring.boot.version>
<springdoc.openapi.version>2.8.3</springdoc.openapi.version>
<!-- Database stuff --> <!-- Database stuff -->
<database.showSql>false</database.showSql> <database.showSql>false</database.showSql>
@ -100,7 +102,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>spring-boot-dependencies</artifactId>
<version>3.2.12</version> <version>${spring.boot.version}</version>
<scope>import</scope> <scope>import</scope>
<type>pom</type> <type>pom</type>
</dependency> </dependency>
@ -261,7 +263,7 @@
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.5.0</version> <version>${springdoc.openapi.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -178,7 +178,13 @@ class ReflectionModalBodyPanel extends Panel {
public SupervisorEditReflectionForm(String id, IModel<Reflection> reflectionModel) { public SupervisorEditReflectionForm(String id, IModel<Reflection> reflectionModel) {
super(id, reflectionModel); super(id, reflectionModel);
IModel<String> reflectionTextModel = new Model<>(getReflectionText(reflectionModel.getObject())); IModel<String> reflectionTextModel = new Model<>();
Reflection reflection = reflectionModel.getObject();
if (reflection instanceof Reflection.Submitted submitted) {
reflectionTextModel.setObject(submitted.reflection());
} else if (reflection instanceof Reflection.ImprovementsNeeded improvementsNeeded) {
reflectionTextModel.setObject(improvementsNeeded.oldReflection());
}
TextArea<String> reflectionTextArea = new TextArea<>("reflection", reflectionTextModel); TextArea<String> reflectionTextArea = new TextArea<>("reflection", reflectionTextModel);
reflectionTextArea.setRequired(true); reflectionTextArea.setRequired(true);

View File

@ -20,7 +20,7 @@ import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model; import org.apache.wicket.model.Model;
import se.su.dsv.scipro.components.BootstrapDatePicker; import se.su.dsv.scipro.components.BootstrapDatePicker;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.file.FileDescription; import se.su.dsv.scipro.file.FileDescription;
import se.su.dsv.scipro.file.FileService; import se.su.dsv.scipro.file.FileService;
import se.su.dsv.scipro.finalseminar.FinalSeminar; import se.su.dsv.scipro.finalseminar.FinalSeminar;

View File

@ -8,6 +8,7 @@
<wicket:panel> <wicket:panel>
<div class="mb-3"> <div class="mb-3">
<label class="col-form-label" wicket:for="background">Background</label> <label class="col-form-label" wicket:for="background">Background</label>
<div wicket:id="background_feedback"></div>
<textarea wicket:id="background" class="form-control" rows="4"></textarea> <textarea wicket:id="background" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary"> <small class="form-text text-body-secondary">
Describe the background of your topic, preferably both theoretical, empirical and/or practical. Describe the background of your topic, preferably both theoretical, empirical and/or practical.
@ -16,6 +17,7 @@
<div class="mb-3"> <div class="mb-3">
<label class="col-form-label" wicket:for="literature">Literature</label> <label class="col-form-label" wicket:for="literature">Literature</label>
<div wicket:id="literature_feedback"></div>
<textarea wicket:id="literature" class="form-control" rows="4"></textarea> <textarea wicket:id="literature" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary"> <small class="form-text text-body-secondary">
Describe the connection to your background, for example literature, theory and methodology related to the topic, courses that you have taken that relates to the topic. Describe the connection to your background, for example literature, theory and methodology related to the topic, courses that you have taken that relates to the topic.
@ -24,6 +26,7 @@
<div class="mb-3"> <div class="mb-3">
<label class="col-form-label" wicket:for="problem">Problem</label> <label class="col-form-label" wicket:for="problem">Problem</label>
<div wicket:id="problem_feedback"></div>
<textarea wicket:id="problem" class="form-control" rows="4"></textarea> <textarea wicket:id="problem" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary"> <small class="form-text text-body-secondary">
Here you describe the problem you want to address and solve by your work, preferably formulated as a research question. Here you describe the problem you want to address and solve by your work, preferably formulated as a research question.
@ -32,6 +35,7 @@
<div class="mb-3"> <div class="mb-3">
<label class="col-form-label" wicket:for="method">Method</label> <label class="col-form-label" wicket:for="method">Method</label>
<div wicket:id="method_feedback"></div>
<textarea wicket:id="method" class="form-control" rows="4"></textarea> <textarea wicket:id="method" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary"> <small class="form-text text-body-secondary">
The method you plan to use in order to solve the problem and answer the research question. The method you plan to use in order to solve the problem and answer the research question.
@ -40,6 +44,7 @@
<div class="mb-3"> <div class="mb-3">
<label class="col-form-label" wicket:for="interests">My interests</label> <label class="col-form-label" wicket:for="interests">My interests</label>
<div wicket:id="interests_feedback"></div>
<textarea wicket:id="interests" class="form-control" rows="4"></textarea> <textarea wicket:id="interests" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary"> <small class="form-text text-body-secondary">
Please note that when you propose your own topic, it is not guaranteed that your topic will be approved. In that case, you will be assigned a different topic by your supervisor. Specify which topics of interest you have, relating to the research fields or the courses that you have taken at DSV. Please note that when you propose your own topic, it is not guaranteed that your topic will be approved. In that case, you will be assigned a different topic by your supervisor. Specify which topics of interest you have, relating to the research fields or the courses that you have taken at DSV.

View File

@ -1,6 +1,7 @@
package se.su.dsv.scipro.match; package se.su.dsv.scipro.match;
import org.apache.wicket.markup.html.form.TextArea; import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel; import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LambdaModel; import org.apache.wicket.model.LambdaModel;
@ -12,36 +13,20 @@ public class IdeaTholanderCompletionPanel extends Panel {
super(id, model); super(id, model);
final IModel<TholanderBox> tholanderBox = model.map(Idea::getTholanderBox); final IModel<TholanderBox> tholanderBox = model.map(Idea::getTholanderBox);
final StringValidator lengthValidator = StringValidator.maximumLength(TholanderBox.MAX_CHARS); textField("background", LambdaModel.of(tholanderBox, TholanderBox::getBackground, TholanderBox::setBackground));
add( textField("literature", LambdaModel.of(tholanderBox, TholanderBox::getLiterature, TholanderBox::setLiterature));
new TextArea<>( textField("problem", LambdaModel.of(tholanderBox, TholanderBox::getProblem, TholanderBox::setProblem));
"background", textField("method", LambdaModel.of(tholanderBox, TholanderBox::getMethod, TholanderBox::setMethod));
LambdaModel.of(tholanderBox, TholanderBox::getBackground, TholanderBox::setBackground) textField("interests", LambdaModel.of(tholanderBox, TholanderBox::getInterests, TholanderBox::setInterests));
).add(lengthValidator) }
);
add( private void textField(String id, IModel<String> model) {
new TextArea<>( TextArea<String> textArea = new TextArea<>(id, model);
"literature", textArea.add(StringValidator.maximumLength(TholanderBox.MAX_CHARS));
LambdaModel.of(tholanderBox, TholanderBox::getLiterature, TholanderBox::setLiterature) textArea.setRequired(true);
).add(lengthValidator) add(textArea);
);
add( ComponentFeedbackPanel feedback = new ComponentFeedbackPanel(id + "_feedback", textArea);
new TextArea<>( add(feedback);
"problem",
LambdaModel.of(tholanderBox, TholanderBox::getProblem, TholanderBox::setProblem)
).add(lengthValidator)
);
add(
new TextArea<>(
"method",
LambdaModel.of(tholanderBox, TholanderBox::getMethod, TholanderBox::setMethod)
).add(lengthValidator)
);
add(
new TextArea<>(
"interests",
LambdaModel.of(tholanderBox, TholanderBox::getInterests, TholanderBox::setInterests)
).add(lengthValidator)
);
} }
} }

View File

@ -17,7 +17,14 @@
an idea if you couldn't find any suitable supervisor provided ideas. an idea if you couldn't find any suitable supervisor provided ideas.
</div> </div>
<form wicket:id="ideaForm"> <!--
Turn off all client-side validation using novalidate.
All input is validated server-side, and we want to validate it
that way to get nice error messages.
However, we also want to maintain the required/minlength/whatever
attributes on the input fields for accessibility.
-->
<form wicket:id="ideaForm" novalidate>
<div class="mb-3"> <div class="mb-3">
<label class="col-form-label" wicket:for="title">Title</label> <label class="col-form-label" wicket:for="title">Title</label>
<p class="form-text"> <p class="form-text">

View File

@ -26,7 +26,7 @@ you.are.partner.on.other.idea= You have already been added as a partner to anoth
too.many.authors= Too many authors for a ${name}-idea. May not be more than ${maxAuthors} including yourself. too.many.authors= Too many authors for a ${name}-idea. May not be more than ${maxAuthors} including yourself.
too.few.authors= Too few authors for a ${name}-idea. Must be at least ${minAuthors} including yourself. too.few.authors= Too few authors for a ${name}-idea. Must be at least ${minAuthors} including yourself.
keywordError= You need to select between 1 and 5 keywords. keywordError= You need to select between 1 and 5 keywords.
submissionFailed= Idea could not be submitted. submissionFailed= Idea could not be submitted. Correct the highlighted fields and try again.
ideaSubmitted= You have successfully submitted your ${projectType.name} student idea, for the application period \ ideaSubmitted= You have successfully submitted your ${projectType.name} student idea, for the application period \
${applicationPeriod.name}. ${applicationPeriod.name}.
ideaUpdated= You have successfully updated your ${projectType.name} student idea, in the application period \ ideaUpdated= You have successfully updated your ${projectType.name} student idea, in the application period \

View File

@ -14,8 +14,8 @@ import org.apache.wicket.injection.Injector;
import org.apache.wicket.request.resource.AbstractResource; import org.apache.wicket.request.resource.AbstractResource;
import org.apache.wicket.request.resource.IResource; import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.ResourceReference; import org.apache.wicket.request.resource.ResourceReference;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.http.PhotoResult; import se.su.dsv.scipro.daisyexternal.http.PhotoResult;
import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.data.dataobjects.Member;
import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;

View File

@ -30,8 +30,8 @@ import se.su.dsv.scipro.checklist.ChecklistCategoryRepo;
import se.su.dsv.scipro.checklist.ChecklistQuestionRepo; import se.su.dsv.scipro.checklist.ChecklistQuestionRepo;
import se.su.dsv.scipro.checklist.ChecklistService; import se.su.dsv.scipro.checklist.ChecklistService;
import se.su.dsv.scipro.checklist.ChecklistTemplateService; import se.su.dsv.scipro.checklist.ChecklistTemplateService;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.http.PhotoResult; import se.su.dsv.scipro.daisyexternal.http.PhotoResult;
import se.su.dsv.scipro.data.enums.DateStyle; import se.su.dsv.scipro.data.enums.DateStyle;
import se.su.dsv.scipro.date.DateService; import se.su.dsv.scipro.date.DateService;
import se.su.dsv.scipro.examiner.pages.ExaminerStartPage; import se.su.dsv.scipro.examiner.pages.ExaminerStartPage;