Allow supervisors to request improvements from final seminar opponents #78
@ -20,7 +20,11 @@ import se.su.dsv.scipro.file.FileUpload;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminar;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition;
|
||||
import se.su.dsv.scipro.match.ApplicationPeriod;
|
||||
import se.su.dsv.scipro.match.Idea;
|
||||
import se.su.dsv.scipro.match.IdeaService;
|
||||
import se.su.dsv.scipro.match.Keyword;
|
||||
import se.su.dsv.scipro.match.Target;
|
||||
import se.su.dsv.scipro.match.TholanderBox;
|
||||
import se.su.dsv.scipro.milestones.dataobjects.MilestoneActivityTemplate;
|
||||
import se.su.dsv.scipro.milestones.dataobjects.MilestonePhaseTemplate;
|
||||
import se.su.dsv.scipro.milestones.service.MilestoneActivityTemplateService;
|
||||
@ -37,6 +41,7 @@ import se.su.dsv.scipro.reviewing.ReviewerAssignmentService;
|
||||
import se.su.dsv.scipro.reviewing.RoughDraftApprovalService;
|
||||
import se.su.dsv.scipro.security.auth.roles.Roles;
|
||||
import se.su.dsv.scipro.system.*;
|
||||
import se.su.dsv.scipro.util.Pair;
|
||||
|
||||
public class DataInitializer implements Lifecycle {
|
||||
|
||||
@ -51,6 +56,9 @@ public class DataInitializer implements Lifecycle {
|
||||
@Inject
|
||||
private PasswordService passwordService;
|
||||
|
||||
@Inject
|
||||
private IdeaService ideaService;
|
||||
|
||||
@Inject
|
||||
private MilestoneActivityTemplateService milestoneActivityTemplateService;
|
||||
|
||||
@ -94,14 +102,19 @@ public class DataInitializer implements Lifecycle {
|
||||
private User stina_student;
|
||||
private User sid_student;
|
||||
private User simon_student;
|
||||
private ProjectType bachelorClass;
|
||||
private User sofia_student;
|
||||
private Set<ResearchArea> researchAreas;
|
||||
private Long researchAreaId = RESEARCH_AREA_ID;
|
||||
private Set<Language> languages;
|
||||
private Set<Language> languages = Set.of(Language.SWEDISH, Language.ENGLISH);
|
||||
private Program program;
|
||||
private ResearchArea researchArea1;
|
||||
private ResearchArea researchArea2;
|
||||
private Keyword keyword1;
|
||||
private Keyword keyword2;
|
||||
private ProjectType bachelorClass;
|
||||
private ProjectType masterClass;
|
||||
private ProjectType magisterClass;
|
||||
private ApplicationPeriod applicationPeriod;
|
||||
private Project project1;
|
||||
private Project project2;
|
||||
|
||||
@ -111,13 +124,17 @@ public class DataInitializer implements Lifecycle {
|
||||
if (profile.getCurrentProfile() == Profiles.DEV && noUsers()) {
|
||||
createDefaultProjectTypesIfNotDone();
|
||||
createDefaultChecklistCategoriesIfNotDone();
|
||||
createProgram();
|
||||
createApplicationPeriodIfNotDone();
|
||||
createGradingCriterionTemplateIfNotDone();
|
||||
createResearchAreasForDemo();
|
||||
createKeywordsIfNotDone();
|
||||
createMilestonesIfNotDone();
|
||||
createUsers();
|
||||
createMatchedIdea();
|
||||
createProjects();
|
||||
createTarget();
|
||||
createStudentIdea();
|
||||
createRoughDraftApproval();
|
||||
createPastFinalSeminar();
|
||||
setUpNotifications();
|
||||
@ -175,27 +192,36 @@ public class DataInitializer implements Lifecycle {
|
||||
return userService.findByUsername(ADMIN + MAIL) == null;
|
||||
}
|
||||
|
||||
private void createProgram() {
|
||||
program = new Program();
|
||||
program.setCode("AppCompSci");
|
||||
program.setName("Tillämpad Datavetenskap");
|
||||
program.setExternalId(123);
|
||||
program.setNameEn("Applied Computer Science");
|
||||
program = save(program);
|
||||
}
|
||||
|
||||
private void createApplicationPeriodIfNotDone() {
|
||||
ApplicationPeriod applicationPeriod = new ApplicationPeriod("HT 2014");
|
||||
applicationPeriod = new ApplicationPeriod("HT 2014");
|
||||
applicationPeriod.setStartDate(LocalDate.now().minusDays(APPLICATION_PERIOD_START_MINUS_DAYS));
|
||||
applicationPeriod.setEndDate(LocalDate.now().plusDays(APPLICATION_PERIOD_END_PLUS_DAYS));
|
||||
applicationPeriod.setCourseStartDate(LocalDate.now().plusDays(APPLICATION_PERIOD_COURSE_START_PLUS_DAYS));
|
||||
applicationPeriod.setCourseStartTime(LocalTime.of(8, 0));
|
||||
applicationPeriod = save(applicationPeriod);
|
||||
applicationPeriod.setProjectTypes(new HashSet<>(Collections.singletonList(bachelorClass)));
|
||||
applicationPeriod.setProjectTypes(new HashSet<>(Set.of(bachelorClass, masterClass)));
|
||||
save(applicationPeriod);
|
||||
}
|
||||
|
||||
private void createKeywordsIfNotDone() {
|
||||
Keyword keyword1 = new Keyword("IT");
|
||||
keyword1 = new Keyword("IT");
|
||||
keyword1.addResearchArea(researchArea1);
|
||||
keyword1.addResearchArea(researchArea2);
|
||||
save(keyword1);
|
||||
keyword1 = save(keyword1);
|
||||
|
||||
Keyword keyword2 = new Keyword("Computers");
|
||||
keyword2 = new Keyword("Computers");
|
||||
keyword2.addResearchArea(researchArea1);
|
||||
keyword2.addResearchArea(researchArea2);
|
||||
save(keyword2);
|
||||
keyword2 = save(keyword2);
|
||||
}
|
||||
|
||||
private void createResearchAreasForDemo() {
|
||||
@ -251,6 +277,11 @@ public class DataInitializer implements Lifecycle {
|
||||
// can not be used as author on any idea
|
||||
// can not be used as author on any project
|
||||
createStudent("Stig");
|
||||
|
||||
// Used to test assign supervisor to student idea
|
||||
// this student has a submitted idea, which has not assigned supervisor
|
||||
// don't use this student for anything else
|
||||
sofia_student = createStudent("Sofia");
|
||||
}
|
||||
|
||||
private User createStudent(String firstName) {
|
||||
@ -269,8 +300,11 @@ public class DataInitializer implements Lifecycle {
|
||||
user.setUnit(u);
|
||||
user.setResearchAreas(researchAreas);
|
||||
user.setLanguages(languages);
|
||||
user.setActiveAsSupervisor(true);
|
||||
|
||||
createBeta(user);
|
||||
return user;
|
||||
|
||||
return save(user);
|
||||
}
|
||||
|
||||
private User createUser(String firstName, String lastName) {
|
||||
@ -322,12 +356,54 @@ public class DataInitializer implements Lifecycle {
|
||||
return u;
|
||||
}
|
||||
|
||||
private void createMatchedIdea() {
|
||||
Idea idea = new Idea();
|
||||
idea.setApplicationPeriod(applicationPeriod);
|
||||
idea.setType(Idea.Type.SUPERVISOR);
|
||||
idea.setProjectType(masterClass);
|
||||
idea.setTitle("Idea without first meeting");
|
||||
idea.setDescription("Explore the deep sea");
|
||||
idea.setPrerequisites("Diving experience");
|
||||
idea.setResearchArea(researchArea1);
|
||||
idea.setPublished(true);
|
||||
Idea saved = ideaService.saveSupervisorIdea(idea, eve_employee, new ArrayList<>(Set.of(keyword1)), true);
|
||||
Pair<Boolean, String> validated = ideaService.validateAdminAddAuthors(saved, Set.of(sid_student));
|
||||
assert validated.getHead();
|
||||
ideaService.setAuthors(saved, Set.of(sid_student), eve_employee);
|
||||
}
|
||||
|
||||
private void createGradingCriterionTemplateIfNotDone() {
|
||||
save(getBachelorTemplate());
|
||||
save(getMasterTemplate());
|
||||
save(getMagisterTemplate());
|
||||
}
|
||||
|
||||
private void createTarget() {
|
||||
Target target = new Target(eric_employee, applicationPeriod, bachelorClass);
|
||||
target.setTarget(10);
|
||||
save(target);
|
||||
}
|
||||
|
||||
private void createStudentIdea() {
|
||||
Idea idea = new Idea();
|
||||
idea.setTitle("Fundamental Math Concepts of AI");
|
||||
idea.setType(Idea.Type.STUDENT);
|
||||
|
||||
TholanderBox box = new TholanderBox();
|
||||
box.setLiterature("Math AI Literature");
|
||||
box.setBackground("Math AI Background");
|
||||
box.setProblem("Math AI Problem");
|
||||
box.setMethod("Math AI Method");
|
||||
box.setInterests("Math AI Interests");
|
||||
idea.setTholanderBox(box);
|
||||
|
||||
idea.setProjectType(bachelorClass);
|
||||
idea.setApplicationPeriod(applicationPeriod);
|
||||
|
||||
List<Keyword> keywords = List.of(keyword1, keyword2);
|
||||
ideaService.saveStudentIdea(idea, sofia_student, program, new HashSet<User>(), keywords, true);
|
||||
}
|
||||
|
||||
private GradingReportTemplate getBachelorTemplate() {
|
||||
GradingReportTemplate gradingReportTemplate = new GradingReportTemplate(
|
||||
bachelorClass,
|
||||
|
@ -169,7 +169,11 @@ public class FirstMeetingPanel extends GenericPanel<Idea> {
|
||||
}
|
||||
|
||||
private void saveAndNotify() {
|
||||
firstMeetingRepository.save(getModelObject());
|
||||
FirstMeeting saved = firstMeetingRepository.save(getModelObject());
|
||||
// After saving the first meeting we have to populate it on the already loaded idea to
|
||||
// make sure that other places that want to render the first meeting get the correct data.
|
||||
// An alternative would be to detach the idea model to force a database refresh.
|
||||
FirstMeetingPanel.this.getModelObject().setFirstMeeting(saved);
|
||||
NotificationSource source = new NotificationSource();
|
||||
String date = dateService.format(getModelObject().getFirstMeetingDate(), DateStyle.DATETIME);
|
||||
String room = getModelObject().getRoom();
|
||||
|
@ -205,17 +205,34 @@ public abstract class AbstractAdminIdeaPanel extends Panel {
|
||||
ideaService.adminUnmatchIdea(idea, SciProSession.get().getUser());
|
||||
info("Unmatched idea: " + idea.getTitle());
|
||||
} else {
|
||||
if (
|
||||
targetService.hasTargetsLeft(
|
||||
idea.getApplicationPeriod(),
|
||||
newSelection,
|
||||
idea.getProjectType()
|
||||
)
|
||||
) {
|
||||
ideaService.changeSupervisor(idea, newSelection, SciProSession.get().getUser());
|
||||
info("Supervisor changed");
|
||||
ideaService.changeSupervisor(idea, newSelection, SciProSession.get().getUser());
|
||||
|
||||
Target currentTarget = targetService.findOne(
|
||||
idea.getApplicationPeriod(),
|
||||
newSelection,
|
||||
idea.getProjectType()
|
||||
);
|
||||
Long countMatched = ideaService.countMatched(
|
||||
idea.getApplicationPeriod(),
|
||||
newSelection,
|
||||
idea.getProjectType()
|
||||
);
|
||||
|
||||
int targetCounter = (currentTarget == null) ? 0 : currentTarget.getTarget();
|
||||
|
||||
String msg =
|
||||
"Supervisor changed: matched/target -> " +
|
||||
countMatched +
|
||||
" / " +
|
||||
targetCounter +
|
||||
" (" +
|
||||
idea.getProjectType().getName() +
|
||||
")";
|
||||
|
||||
if (countMatched > targetCounter) {
|
||||
warn(msg);
|
||||
} else {
|
||||
error("The supervisor have reached current target numbers");
|
||||
info(msg);
|
||||
}
|
||||
}
|
||||
target.addListener(new AjaxFeedbackPanelUpdater());
|
||||
|
@ -337,29 +337,26 @@ public class SupervisorMyIdeasPanel extends Panel {
|
||||
if (idea.getMatch() == null) {
|
||||
return "-";
|
||||
}
|
||||
switch (idea.getMatchStatus()) {
|
||||
case UNMATCHED:
|
||||
return getString("status.unmatched");
|
||||
case COMPLETED:
|
||||
return getString("status.completed");
|
||||
case INACTIVE:
|
||||
return getString("status.inactive");
|
||||
case MATCHED:
|
||||
return switch (idea.getMatchStatus()) {
|
||||
case UNMATCHED -> getString("status.unmatched");
|
||||
case COMPLETED -> getString("status.completed");
|
||||
case INACTIVE -> getString("status.inactive");
|
||||
case MATCHED -> {
|
||||
if (applicationPeriodService.courseStartHasPassed(idea.getApplicationPeriod())) {
|
||||
if (idea.isExported()) {
|
||||
if (idea.wasExportSuccessful()) {
|
||||
return getString("status.project.created");
|
||||
yield getString("status.project.created");
|
||||
} else {
|
||||
return getString("status.export.failed");
|
||||
yield getString("status.export.failed");
|
||||
}
|
||||
} else {
|
||||
return getString("status.awaiting.project.creation");
|
||||
yield getString("status.awaiting.project.creation");
|
||||
}
|
||||
} else {
|
||||
return getString("status.awaiting.course.start", Model.of(idea.getApplicationPeriod()));
|
||||
yield getString("status.awaiting.course.start", Model.of(idea.getApplicationPeriod()));
|
||||
}
|
||||
}
|
||||
return "-"; // can't happen
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -129,6 +129,12 @@ footer a:hover { color: #d95e00;}
|
||||
border-color: #EBCCD1;
|
||||
}
|
||||
|
||||
.feedbackPanelWARNING {
|
||||
color: #000000;
|
||||
background-color: #FFD105;
|
||||
border-color: #EBCCD1;
|
||||
}
|
||||
|
||||
.feedbackPanelINFO {
|
||||
color: #3C763D;
|
||||
background-color: #DFF0D8;
|
||||
|
@ -9,6 +9,7 @@ spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.Ph
|
||||
# We also need to set the implicit strategy to be JPA compliant, as we rely on this naming strategy for certain
|
||||
# join tables (idea_Keyword vs idea_keyword)
|
||||
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
|
||||
spring.jpa.show-sql=false
|
||||
|
||||
spring.mvc.servlet.path=/api
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user