Merge branch 'develop' into 1584-abstract-keywords

This commit is contained in:
Andreas Svanberg 2023-10-09 12:39:44 +02:00
commit 0105f6a490
20 changed files with 90 additions and 20 deletions

@ -53,6 +53,9 @@ public class FinalSeminar extends LazyDeletableDomainObject {
@Column(name = "extra_info")
private String extraInfo;
@Basic
private Boolean manualParticipants = false;
@OneToMany(mappedBy = FINAL_SEMINAR, orphanRemoval = true, cascade = CascadeType.ALL)
private Set<FinalSeminarActiveParticipation> activeParticipations = new HashSet<>();
@ -96,6 +99,14 @@ public class FinalSeminar extends LazyDeletableDomainObject {
this.project = project;
}
public Boolean getManualParticipants() {
return manualParticipants;
}
public void setManualParticipants(Boolean manualParticipants) {
this.manualParticipants = manualParticipants;
}
public void setStartDate(Date startDate) {
this.startDate = (Date) startDate.clone();
}

@ -4,6 +4,7 @@ import se.su.dsv.scipro.system.Language;
public record FinalSeminarDetails(
String location,
Boolean manualParticipants,
int maxParticipants,
int maxOpponents,
Language presentationLanguage,

@ -3,7 +3,10 @@ package se.su.dsv.scipro.finalseminar;
import org.springframework.data.domain.Pageable;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.system.*;
import se.su.dsv.scipro.system.DegreeType;
import se.su.dsv.scipro.system.FilteredService;
import se.su.dsv.scipro.system.GenericService;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.util.Either;
import java.io.Serializable;
@ -58,6 +61,7 @@ public interface FinalSeminarService extends GenericService<FinalSeminar, Long>,
private Boolean onlyActiveOrCompletedProjects;
private User headSupervisor;
private DegreeType degreeType;
private Boolean onlyNonManualParticipants;
public Date getFromDate() {
return this.fromDate;
@ -123,6 +127,14 @@ public interface FinalSeminarService extends GenericService<FinalSeminar, Long>,
this.degreeType = degreeType;
}
public Boolean getOnlyNonManualParticipants() {
return onlyNonManualParticipants;
}
public void setOnlyNonManualParticipants(Boolean onlyNonManualParticipants) {
this.onlyNonManualParticipants = onlyNonManualParticipants;
}
@Override
public boolean equals(final Object o) {
if (o == this) return true;
@ -136,7 +148,8 @@ public interface FinalSeminarService extends GenericService<FinalSeminar, Long>,
&& Objects.equals(this.getOnlyActiveProjects(), other.getOnlyActiveProjects())
&& Objects.equals(this.getOnlyActiveOrCompletedProjects(), other.getOnlyActiveOrCompletedProjects())
&& Objects.equals(this.getHeadSupervisor(), other.getHeadSupervisor())
&& Objects.equals(this.getDegreeType(), other.getDegreeType());
&& Objects.equals(this.getDegreeType(), other.getDegreeType())
&& Objects.equals(this.onlyNonManualParticipants, other.onlyNonManualParticipants);
}
protected boolean canEqual(final Object other) {
@ -153,12 +166,22 @@ public interface FinalSeminarService extends GenericService<FinalSeminar, Long>,
this.getOnlyActiveProjects(),
this.getOnlyActiveOrCompletedProjects(),
this.getHeadSupervisor(),
this.getDegreeType());
this.getDegreeType(),
this.getOnlyNonManualParticipants());
}
@Override
public String toString() {
return "FinalSeminarService.Filter(fromDate=" + this.getFromDate() + ", toDate=" + this.getToDate() + ", lazyDeleted=" + this.getLazyDeleted() + ", exempted=" + this.getExempted() + ", onlyActiveProjects=" + this.getOnlyActiveProjects() + ", onlyActiveOrCompletedProjects=" + this.getOnlyActiveOrCompletedProjects() + ", headSupervisor=" + this.getHeadSupervisor() + ", degreeType=" + this.getDegreeType() + ")";
return "FinalSeminarService.Filter(" +
"fromDate=" + this.getFromDate()
+ ", toDate=" + this.getToDate()
+ ", lazyDeleted=" + this.getLazyDeleted()
+ ", exempted=" + this.getExempted()
+ ", onlyActiveProjects=" + this.getOnlyActiveProjects()
+ ", onlyActiveOrCompletedProjects=" + this.getOnlyActiveOrCompletedProjects()
+ ", headSupervisor=" + this.getHeadSupervisor()
+ ", degreeType=" + this.getDegreeType()
+ ", onlyNonManualParticipants=" + this.getOnlyNonManualParticipants() + ")";
}
}
}

@ -154,6 +154,7 @@ public class FinalSeminarServiceImpl extends AbstractServiceImpl<FinalSeminar, L
public FinalSeminar updateDetails(FinalSeminar finalSeminar, FinalSeminarDetails finalSeminarDetails) {
finalSeminar.setRoom(finalSeminarDetails.location());
finalSeminar.setExtraInfo(finalSeminarDetails.extraInfo());
finalSeminar.setManualParticipants(finalSeminarDetails.manualParticipants());
finalSeminar.setMaxOpponents(finalSeminarDetails.maxOpponents());
finalSeminar.setMaxParticipants(finalSeminarDetails.maxParticipants());
finalSeminar.setPresentationLanguage(finalSeminarDetails.presentationLanguage());
@ -342,6 +343,9 @@ public class FinalSeminarServiceImpl extends AbstractServiceImpl<FinalSeminar, L
if (params.getOnlyActiveOrCompletedProjects() != null) {
bb.and(onlyActiveOrCompletedProjectsFilter());
}
if (params.getOnlyNonManualParticipants() != null){
bb.and(onlyNonManualParticipantsFilter());
}
if (params.getDegreeType() != null) {
bb.and(QFinalSeminar.finalSeminar.project.projectType.degreeType.eq(params.getDegreeType()));
}
@ -360,6 +364,10 @@ public class FinalSeminarServiceImpl extends AbstractServiceImpl<FinalSeminar, L
return QFinalSeminar.finalSeminar.project.projectStatus.eq(ProjectStatus.ACTIVE);
}
private BooleanExpression onlyNonManualParticipantsFilter() {
return QFinalSeminar.finalSeminar.manualParticipants.isFalse();
}
private BooleanExpression onlyActiveOrCompletedProjectsFilter() {
return QFinalSeminar.finalSeminar.project.projectStatus.in(ProjectStatus.ACTIVE, ProjectStatus.COMPLETED);
}

@ -0,0 +1 @@
ALTER TABLE final_seminar ADD COLUMN manualParticipants BOOLEAN NOT NULL DEFAULT FALSE;

@ -155,7 +155,7 @@ public class FinalSeminarSchedulingTest extends IntegrationTest {
}
private static FinalSeminarDetails detailsAt() {
return new FinalSeminarDetails("Zoom", 5, 5, Language.SWEDISH, Language.ENGLISH, null);
return new FinalSeminarDetails("Zoom", false, 5, 5, Language.SWEDISH, Language.ENGLISH, null);
}
private void approveRoughDraftApproval(Project project) {

@ -103,7 +103,7 @@ public class ReflectionServiceTest extends IntegrationTest {
private LocalDate scheduleSeminar() {
project.setFinalSeminarRuleExempted(true); // to bypass rough draft approval
FinalSeminarDetails details = new FinalSeminarDetails("Zoom", 1, 1, Language.SWEDISH, Language.ENGLISH, "zoom id 123");
FinalSeminarDetails details = new FinalSeminarDetails("Zoom", false, 1, 1, Language.SWEDISH, Language.ENGLISH, "zoom id 123");
LocalDate seminarDate = finalSeminarService.getEarliestSeminarDate();
Either<SchedulingError, FinalSeminar> schedule = finalSeminarService.schedule(project, seminarDate.atStartOfDay(), details);
assertTrue(schedule.isRight(), "Failed to schedule seminar: " + schedule);

@ -50,7 +50,6 @@ public class SystemMaintenancePage extends AbstractAdminSystemPage {
runningContainer.setOutputMarkupId(true);
scheduledContainer.setOutputMarkupId(true);
runningContainer.add(new AjaxSelfUpdatingTimerBehavior(Duration.ofSeconds(REFRESH_TIMER)) {
@Override
@ -126,7 +125,7 @@ public class SystemMaintenancePage extends AbstractAdminSystemPage {
private static class SystemNoticeForm extends Form<Void> {
private IModel<String> noticeModel = Model.of(getApplication().getMetaData(SystemNoticePanel.SYSTEM_NOTICE));
private final IModel<String> noticeModel = Model.of(getApplication().getMetaData(SystemNoticePanel.SYSTEM_NOTICE));
public SystemNoticeForm(String id) {
super(id);
@ -135,7 +134,11 @@ public class SystemMaintenancePage extends AbstractAdminSystemPage {
@Override
protected void onSubmit() {
getApplication().setMetaData(SystemNoticePanel.SYSTEM_NOTICE, noticeModel.getObject());
if (noticeModel.getObject() == null) {
getApplication().setMetaData(SystemNoticePanel.SYSTEM_NOTICE, "");
} else {
getApplication().setMetaData(SystemNoticePanel.SYSTEM_NOTICE, noticeModel.getObject());
}
}
}
}

@ -6,6 +6,7 @@ import java.io.Serializable;
public class FinalSeminarDetailsParameters implements Serializable {
private String room;
private Boolean manualParticipants;
private int maxParticipants;
private int maxOpponents;
private Language presentationLanguage;
@ -15,6 +16,7 @@ public class FinalSeminarDetailsParameters implements Serializable {
static FinalSeminarDetailsParameters from(FinalSeminar finalSeminar) {
FinalSeminarDetailsParameters finalSeminarDetailsParameters = new FinalSeminarDetailsParameters();
finalSeminarDetailsParameters.setRoom(finalSeminar.getRoom());
finalSeminarDetailsParameters.setManualParticipants(finalSeminar.getManualParticipants());
finalSeminarDetailsParameters.setMaxOpponents(finalSeminar.getMaxOpponents());
finalSeminarDetailsParameters.setMaxParticipants(finalSeminar.getMaxParticipants());
finalSeminarDetailsParameters.setPresentationLanguage(finalSeminar.getPresentationLanguage());
@ -24,13 +26,21 @@ public class FinalSeminarDetailsParameters implements Serializable {
}
FinalSeminarDetails asDetails() {
return new FinalSeminarDetails(room, maxParticipants, maxOpponents, presentationLanguage, reportLanguage, extraInfo);
return new FinalSeminarDetails(room, manualParticipants, maxParticipants, maxOpponents, presentationLanguage, reportLanguage, extraInfo);
}
public String getRoom() {
return room;
}
public Boolean getManualParticipants() {
return manualParticipants;
}
public void setManualParticipants(Boolean manualParticipants) {
this.manualParticipants = manualParticipants;
}
public void setRoom(String room) {
this.room = room;
}

@ -25,8 +25,15 @@
<select id="reportLanguage" class="form-select mb-3" wicket:id="reportLanguage"></select>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" wicket:id="manualParticipants"/>
<label class="form-check-label" wicket:for="manualParticipants">
Supervisor manually chooses opponents and active participants
</label>
</div>
<div class="mb-3">
<label for="maxOpponents" wicket:for="maxOpponents" class="col-form-label">Max oppositions</label>
<label for="maxOpponents" wicket:for="maxOpponents" class="col-form-label">Max opponents</label>
<input id="maxOpponents" wicket:id="maxOpponents" class="form-control"/>
</div>

@ -1,9 +1,6 @@
package se.su.dsv.scipro.finalseminar;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.*;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.model.IModel;
@ -48,6 +45,11 @@ public class FinalSeminarDetailsParametersPanel extends GenericPanel<FinalSemina
}
});
add(new CheckBox("manualParticipants",
LambdaModel.of(model,
FinalSeminarDetailsParameters::getManualParticipants,
FinalSeminarDetailsParameters::setManualParticipants)).setOutputMarkupId(true));
RequiredTextField<Integer> maxParticipants = new RequiredTextField<>("maxParticipants",
LambdaModel.of(model,
FinalSeminarDetailsParameters::getMaxParticipants,

@ -55,6 +55,7 @@ public class ProjectOppositionPage extends AbstractProjectDetailsPage implements
filter.setLazyDeleted(Boolean.FALSE);
filter.setDegreeType(getActiveProject().getProjectType().getDegreeType());
filter.setOnlyActiveProjects(Boolean.TRUE);
filter.setOnlyNonManualParticipants(Boolean.TRUE);
add(new FeedbackPanel("feedback"));

@ -74,7 +74,10 @@ public class DaisyPicture extends ResourceReference {
final int userId = attributes.getParameters().get(USER_ID).toInt(0);
final boolean alwaysShow = projectRelations.contains(userId) || seminarRelations.contains(userId);
Integer requesterDaisyId = session.getUser().getIdentifier();
Integer requesterDaisyId = null;
if(session.getUser() != null){
requesterDaisyId = session.getUser().getIdentifier();
}
final PhotoResult photo = daisyAPI.getPhoto(userId, requesterDaisyId == null ? -1 : requesterDaisyId, alwaysShow);
return photo.fold(this::noPhoto, this::noPhoto, this::showPhoto);
}

@ -30,7 +30,7 @@ public class SupervisorApplicationPeriodStatisticsPanel extends GenericPanel<Use
upcomingPeriods().stream()
.flatMap(period -> period.getProjectTypes().stream()
.map(projectType -> {
final Target target = targetService.findOne(period, supervisorModel.getObject(), projectType);
final Target target = targetService.findOne(period, getModelObject(), projectType);
return new PeriodTypeTarget(period, projectType, target);
}))
.filter(ptt -> ptt.getTarget().getTarget() > 0)

@ -28,7 +28,7 @@ public class SupervisorStatisticsPanel extends Panel {
ideaPanel = new SupervisorIdeaStatisticsPanel(IDEAS_PANEL);
ideaPanel.setOutputMarkupPlaceholderTag(true);
add(ideaPanel);
periodStatisticsPanel = new SupervisorApplicationPeriodStatisticsPanel("periods", new Model<>()) {
periodStatisticsPanel = new SupervisorApplicationPeriodStatisticsPanel("periods", new DetachableServiceModel<>(userService)) {
@Override
protected void onConfigure() {
super.onConfigure();
@ -47,7 +47,7 @@ public class SupervisorStatisticsPanel extends Panel {
protected void action(AjaxRequestTarget pTarget, User newSelection) {
projectPanel.updateSupervisor(newSelection);
ideaPanel.updateSupervisor(newSelection);
periodStatisticsPanel.setModel(getModel());
periodStatisticsPanel.setModelObject(getModelObject());
pTarget.add(projectPanel);
pTarget.add(ideaPanel);
pTarget.add(periodStatisticsPanel);

@ -55,7 +55,7 @@
<band height="50">
<textField textAdjust="StretchHeight">
<reportElement style="titleStyle" x="0" y="0" width="495" height="30" uuid="b0bf7adc-8731-42ed-8e5d-8ab64653ba32"/>
<textFieldExpression><![CDATA[($F{swedish} ? "Handledarens underlag till examinator för betygssättning av " : "Supervisor's grading basis to the examiner for grading of ") + $F{authorName}]]></textFieldExpression>
<textFieldExpression><![CDATA[($F{swedish} ? "Handledarens underlag till examinator för betygsättning av " : "Supervisor's grading basis to the examiner for grading of ") + $F{authorName}]]></textFieldExpression>
</textField>
</band>
</title>