2874 Allow authors to give consent to publish their thesis
This commit is contained in:
parent
973addf196
commit
4fc1a661f7
core/src/main/java
modules
se/su/dsv/scipro
daisyExternal/http
finalthesis
daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy
view/src
main/java/se/su/dsv/scipro
test/java/se/su/dsv/scipro
@ -2,6 +2,7 @@ package modules;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.multibindings.OptionalBinder;
|
||||
import se.su.dsv.scipro.activityplan.*;
|
||||
import se.su.dsv.scipro.checklist.*;
|
||||
import se.su.dsv.scipro.date.DateService;
|
||||
@ -10,6 +11,8 @@ import se.su.dsv.scipro.events.EventModule;
|
||||
import se.su.dsv.scipro.finalseminar.*;
|
||||
import se.su.dsv.scipro.finalthesis.FinalThesisService;
|
||||
import se.su.dsv.scipro.finalthesis.FinalThesisServiceImpl;
|
||||
import se.su.dsv.scipro.finalthesis.PublishingConsentService;
|
||||
import se.su.dsv.scipro.finalthesis.PublishingConsentUnavailable;
|
||||
import se.su.dsv.scipro.firstmeeting.FirstMeetingService;
|
||||
import se.su.dsv.scipro.firstmeeting.FirstMeetingServiceImpl;
|
||||
import se.su.dsv.scipro.forum.ForumModule;
|
||||
@ -110,6 +113,8 @@ public class CoreModule extends AbstractModule {
|
||||
bind(PeerReviewService.class).to(PeerReviewServiceImpl.class);
|
||||
bind(MilestoneActivityTemplateService.class).to(MilestoneActivityTemplateServiceImpl.class);
|
||||
bind(FinalThesisService.class).to(FinalThesisServiceImpl.class);
|
||||
OptionalBinder.newOptionalBinder(binder(), PublishingConsentService.class)
|
||||
.setDefault().to(PublishingConsentUnavailable.class);
|
||||
bind(ChecklistTemplateService.class).to(ChecklistTemplateServiceImpl.class);
|
||||
bind(PeerPortal.class).to(PeerPortalImpl.class);
|
||||
bind(FinalSeminarRespondentService.class).to(FinalSeminarRespondentServiceImpl.class);
|
||||
|
@ -71,4 +71,8 @@ public interface DaisyAPI {
|
||||
List<Employee> listEmployees(int departmentId);
|
||||
|
||||
OrganisationalUnit orgunit(int unitId);
|
||||
|
||||
PublishingConsent getPublishingConsent(int projectId, int personId);
|
||||
|
||||
boolean setPublishingConsent(int projectId, int personId, PublishingConsentLevel publishingConsentLevel);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import jakarta.ws.rs.ProcessingException;
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.client.Invocation;
|
||||
import jakarta.ws.rs.client.WebTarget;
|
||||
import jakarta.ws.rs.core.GenericType;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
@ -407,6 +408,32 @@ public class DaisyAPIImpl implements DaisyAPI {
|
||||
.get(new GenericType<>() {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublishingConsent getPublishingConsent(int projectId, int personId) {
|
||||
return thesis()
|
||||
.path(Integer.toString(projectId))
|
||||
.path("author")
|
||||
.path(Integer.toString(personId))
|
||||
.path("publishingConsent")
|
||||
.request(MediaType.APPLICATION_XML_TYPE)
|
||||
.get(PublishingConsent.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPublishingConsent(int projectId, int personId, PublishingConsentLevel publishingConsentLevel) {
|
||||
final Invocation.Builder request = thesis()
|
||||
.path(Integer.toString(projectId))
|
||||
.path("author")
|
||||
.path(Integer.toString(personId))
|
||||
.path("publishingConsent")
|
||||
.request(MediaType.APPLICATION_XML_TYPE);
|
||||
|
||||
// For some reason XML does not work
|
||||
try (Response response = request.post(Entity.json(publishingConsentLevel))) {
|
||||
return response.getStatus() == Response.Status.OK.getStatusCode();
|
||||
}
|
||||
}
|
||||
|
||||
private WebTarget program() {
|
||||
return target()
|
||||
.path(PROGRAM);
|
||||
|
@ -7,7 +7,7 @@ import se.su.dsv.scipro.system.FilteredService;
|
||||
import se.su.dsv.scipro.system.GenericService;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.*;
|
||||
|
||||
public interface FinalThesisService extends GenericService<FinalThesis, Long>,
|
||||
FilteredService<FinalThesis, Long, FinalThesisService.Filter> {
|
||||
|
@ -0,0 +1,20 @@
|
||||
package se.su.dsv.scipro.finalthesis;
|
||||
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PublishingConsentService {
|
||||
|
||||
boolean setPublishingConsent(Project project, User author, Level publishingConsent);
|
||||
|
||||
PublishingConsent getPublishingConsent(Project project, User author);
|
||||
|
||||
record PublishingConsent(Level selected, List<Level> available) {}
|
||||
enum Level {
|
||||
DO_NOT_PUBLISH,
|
||||
PUBLISH_INTERNALLY,
|
||||
PUBLISH
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package se.su.dsv.scipro.finalthesis;
|
||||
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PublishingConsentUnavailable implements PublishingConsentService {
|
||||
@Override
|
||||
public boolean setPublishingConsent(Project project, User author, Level publishingConsent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublishingConsent getPublishingConsent(Project project, User author) {
|
||||
return new PublishingConsent(null, List.of());
|
||||
}
|
||||
}
|
58
daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyConsentService.java
Normal file
58
daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyConsentService.java
Normal file
@ -0,0 +1,58 @@
|
||||
package se.su.dsv.scipro.integration.daisy;
|
||||
|
||||
import jakarta.ws.rs.ProcessingException;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
|
||||
import se.su.dsv.scipro.finalthesis.PublishingConsentService;
|
||||
import se.su.dsv.scipro.io.dto.PublishingConsentLevel;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class DaisyConsentService implements PublishingConsentService {
|
||||
private static final PublishingConsent UNAVAILABLE = new PublishingConsent(null, List.of());
|
||||
|
||||
private final DaisyAPI daisyAPI;
|
||||
|
||||
@Inject
|
||||
DaisyConsentService(DaisyAPI daisyAPI) {
|
||||
this.daisyAPI = daisyAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPublishingConsent(Project project, User author, Level publishingConsent) {
|
||||
final PublishingConsentLevel publishingConsentLevel = switch (publishingConsent) {
|
||||
case DO_NOT_PUBLISH -> PublishingConsentLevel.DO_NOT_PUBLISH;
|
||||
case PUBLISH_INTERNALLY -> PublishingConsentLevel.PUBLISH_INTERNALLY;
|
||||
case PUBLISH -> PublishingConsentLevel.PUBLIC;
|
||||
};
|
||||
return daisyAPI.setPublishingConsent(project.getIdentifier(), author.getIdentifier(), publishingConsentLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublishingConsent getPublishingConsent(Project project, User author) {
|
||||
try {
|
||||
final se.su.dsv.scipro.io.dto.PublishingConsent publishingConsent = daisyAPI.getPublishingConsent(project.getIdentifier(), author.getIdentifier());
|
||||
final Level selected = fromDaisyLevel(publishingConsent.getSelected());
|
||||
final List<Level> available = publishingConsent.getAvailables()
|
||||
.stream()
|
||||
.map(DaisyConsentService::fromDaisyLevel)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
return new PublishingConsent(selected, available);
|
||||
} catch (ProcessingException | WebApplicationException e) {
|
||||
return UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
private static Level fromDaisyLevel(final PublishingConsentLevel level) {
|
||||
return switch (level) {
|
||||
case DO_NOT_PUBLISH -> Level.DO_NOT_PUBLISH;
|
||||
case PUBLISH_INTERNALLY -> Level.PUBLISH_INTERNALLY;
|
||||
case PUBLIC -> Level.PUBLISH;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
package se.su.dsv.scipro.integration.daisy;
|
||||
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.multibindings.OptionalBinder;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
import se.su.dsv.scipro.daisyExternal.ExternalImporter;
|
||||
import se.su.dsv.scipro.daisyExternal.ImporterTransactions;
|
||||
import se.su.dsv.scipro.daisyExternal.impl.ExternalImporterDaisyImpl;
|
||||
import se.su.dsv.scipro.daisyExternal.impl.ImporterTransactionsImpl;
|
||||
import se.su.dsv.scipro.finalthesis.PublishingConsentService;
|
||||
import se.su.dsv.scipro.integration.daisy.workers.ProjectExporter;
|
||||
import se.su.dsv.scipro.integration.daisy.workers.UserImportWorker;
|
||||
import se.su.dsv.scipro.io.ExternalExporter;
|
||||
@ -33,6 +35,9 @@ public class DaisyModule extends ServletModule {
|
||||
|
||||
Multibinder.newSetBinder(binder(), UserSearchService.class)
|
||||
.addBinding().to(DaisyUserSearchService.class);
|
||||
|
||||
OptionalBinder.newOptionalBinder(binder(), PublishingConsentService.class)
|
||||
.setBinding().to(DaisyConsentService.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,23 @@
|
||||
<div wicket:id="revisionPanel"></div>
|
||||
<div wicket:id="approvedPanel"></div>
|
||||
<div wicket:id="formPanel"></div>
|
||||
<wicket:enclosure child="consent_form">
|
||||
<h5 class="mt-3">Publishing consent</h5>
|
||||
<form wicket:id="consent_form">
|
||||
<div wicket:id="feedback"></div>
|
||||
<p>
|
||||
Giving consent to publish does not mean the thesis <em>will</em> be published,
|
||||
only that it <em>may</em> be published.
|
||||
</p>
|
||||
<div class="mb-3">
|
||||
<label wicket:for="consent_level" class="col-form-label">
|
||||
How may your thesis be published
|
||||
</label>
|
||||
<select wicket:id="consent_level" class="form-select"></select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success btn-sm">Select</button>
|
||||
</form>
|
||||
</wicket:enclosure>
|
||||
</wicket:panel>
|
||||
</body>
|
||||
</html>
|
@ -1,7 +1,11 @@
|
||||
package se.su.dsv.scipro.finalthesis;
|
||||
|
||||
import org.apache.wicket.feedback.FencedFeedbackPanel;
|
||||
import org.apache.wicket.markup.html.WebMarkupContainer;
|
||||
import org.apache.wicket.markup.html.basic.EnumLabel;
|
||||
import org.apache.wicket.markup.html.form.DropDownChoice;
|
||||
import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
|
||||
import org.apache.wicket.markup.html.form.Form;
|
||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
||||
import org.apache.wicket.markup.html.panel.GenericPanel;
|
||||
import org.apache.wicket.markup.html.panel.Panel;
|
||||
@ -15,12 +19,16 @@ import se.su.dsv.scipro.finalseminar.FinalSeminarService;
|
||||
import se.su.dsv.scipro.forum.pages.ProjectForumBasePage;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.project.pages.ProjectFinalSurveyPage;
|
||||
import se.su.dsv.scipro.reflection.ReflectionService;
|
||||
import se.su.dsv.scipro.security.auth.ProjectModuleComponent;
|
||||
import se.su.dsv.scipro.session.SciProSession;
|
||||
import se.su.dsv.scipro.system.ProjectModule;
|
||||
import se.su.dsv.scipro.util.PageParameterKeys;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static se.su.dsv.scipro.finalthesis.FinalThesis.Status;
|
||||
|
||||
@ProjectModuleComponent(ProjectModule.GRADING)
|
||||
@ -38,6 +46,10 @@ public class FinalThesisPanel extends GenericPanel<Project> {
|
||||
private FinalThesisService finalThesisService;
|
||||
@Inject
|
||||
private FinalSeminarService finalSeminarService;
|
||||
@Inject
|
||||
private PublishingConsentService publishingConsentService;
|
||||
@Inject
|
||||
private ReflectionService reflectionService;
|
||||
|
||||
public FinalThesisPanel(String id, IModel<Project> project) {
|
||||
super(id, project);
|
||||
@ -64,6 +76,7 @@ public class FinalThesisPanel extends GenericPanel<Project> {
|
||||
setResponsePage(ProjectFinalSurveyPage.class, ProjectFinalSurveyPage.getPageParameters(getModelObject()));
|
||||
}
|
||||
});
|
||||
add(new ConsentForm("consent_form", project));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -125,4 +138,47 @@ public class FinalThesisPanel extends GenericPanel<Project> {
|
||||
};
|
||||
}
|
||||
|
||||
private class ConsentForm extends Form<Project> {
|
||||
final IModel<PublishingConsentService.Level> levelModel;
|
||||
private final IModel<List<PublishingConsentService.Level>> availableLevels;
|
||||
|
||||
public ConsentForm(final String id, IModel<Project> project) {
|
||||
super(id, project);
|
||||
IModel<PublishingConsentService.PublishingConsent> publishingConsent = LoadableDetachableModel.of(
|
||||
() -> publishingConsentService.getPublishingConsent(project.getObject(), SciProSession.get().getUser()));
|
||||
|
||||
availableLevels = publishingConsent.map(PublishingConsentService.PublishingConsent::available);
|
||||
levelModel = LoadableDetachableModel.of(() -> publishingConsent.getObject().selected());
|
||||
|
||||
add(new DropDownChoice<>(
|
||||
"consent_level",
|
||||
levelModel,
|
||||
availableLevels,
|
||||
new EnumChoiceRenderer<>(this)));
|
||||
|
||||
add(new FencedFeedbackPanel("feedback", this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
boolean submittedReflection = !reflectionService.hasToFillInReflection(getModelObject(), SciProSession.get().getUser());
|
||||
setVisibilityAllowed(finalThesisService.hasFinalThesis(getModelObject()) && !availableLevels.getObject().isEmpty() && submittedReflection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSubmit() {
|
||||
super.onSubmit();
|
||||
final boolean success = publishingConsentService.setPublishingConsent(
|
||||
getModelObject(),
|
||||
SciProSession.get().getUser(),
|
||||
levelModel.getObject());
|
||||
if (success) {
|
||||
success(getString("publishing_consent_level_changed"));
|
||||
} else {
|
||||
error(getString("failed_to_update_consent_level"));
|
||||
levelModel.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,3 @@
|
||||
notYet= Final seminar must be conducted first.
|
||||
notYet= Final seminar must be conducted first.
|
||||
publishing_consent_level_changed=Publishing consent updated.
|
||||
failed_to_update_consent_level=Failed to change publishing consent
|
||||
|
@ -32,6 +32,12 @@
|
||||
</label>
|
||||
<textarea class="form-control" wicket:id="reflection" id="reflection" rows="10" required></textarea>
|
||||
</div>
|
||||
<fieldset class="mb-3">
|
||||
<legend>
|
||||
<wicket:message key="publishing_consent"/>
|
||||
</legend>
|
||||
<wicket:container wicket:id="publishingConsentLevel"></wicket:container>
|
||||
</fieldset>
|
||||
<button type="submit" class="btn btn-success btn-sm"><wicket:message key="submit">[Submit]</wicket:message></button>
|
||||
</form>
|
||||
</wicket:panel>
|
||||
|
@ -2,22 +2,30 @@ package se.su.dsv.scipro.project.panels;
|
||||
|
||||
import org.apache.wicket.feedback.FencedFeedbackPanel;
|
||||
import org.apache.wicket.markup.html.basic.Label;
|
||||
import org.apache.wicket.markup.html.form.DropDownChoice;
|
||||
import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
|
||||
import org.apache.wicket.markup.html.form.Form;
|
||||
import org.apache.wicket.markup.html.form.FormComponent;
|
||||
import org.apache.wicket.markup.html.form.TextArea;
|
||||
import org.apache.wicket.markup.html.panel.GenericPanel;
|
||||
import org.apache.wicket.model.IModel;
|
||||
import org.apache.wicket.model.LoadableDetachableModel;
|
||||
import org.apache.wicket.model.Model;
|
||||
import se.su.dsv.scipro.components.BootstrapRadioChoice;
|
||||
import se.su.dsv.scipro.finalthesis.PublishingConsentService;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.reflection.ReflectionService;
|
||||
import se.su.dsv.scipro.session.SciProSession;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ReflectionPanel extends GenericPanel<Project> {
|
||||
|
||||
@Inject
|
||||
private ReflectionService reflectionService;
|
||||
@Inject
|
||||
private PublishingConsentService publishingConsentService;
|
||||
|
||||
public ReflectionPanel(String id, IModel<Project> projectModel) {
|
||||
super(id, projectModel);
|
||||
@ -39,6 +47,7 @@ public class ReflectionPanel extends GenericPanel<Project> {
|
||||
|
||||
private class ReflectionForm extends Form<Project> {
|
||||
private IModel<String> reflectionModel;
|
||||
private IModel<PublishingConsentService.Level> levelModel;
|
||||
|
||||
public ReflectionForm(String id, IModel<Project> projectModel) {
|
||||
super(id, projectModel);
|
||||
@ -48,6 +57,18 @@ public class ReflectionPanel extends GenericPanel<Project> {
|
||||
TextArea<String> reflectionTextArea = new TextArea<>("reflection", reflectionModel);
|
||||
reflectionTextArea.setRequired(true);
|
||||
add(reflectionTextArea);
|
||||
|
||||
IModel<PublishingConsentService.PublishingConsent> publishingConsent = LoadableDetachableModel.of(() ->
|
||||
publishingConsentService.getPublishingConsent(getModelObject(), SciProSession.get().getUser()));
|
||||
|
||||
levelModel = new Model<>();
|
||||
FormComponent<PublishingConsentService.Level> publishingConsentLevel = new BootstrapRadioChoice<>(
|
||||
"publishingConsentLevel",
|
||||
levelModel,
|
||||
publishingConsent.map(PublishingConsentService.PublishingConsent::available),
|
||||
new EnumChoiceRenderer<>(this));
|
||||
publishingConsentLevel.setRequired(true);
|
||||
add(publishingConsentLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,6 +81,7 @@ public class ReflectionPanel extends GenericPanel<Project> {
|
||||
protected void onSubmit() {
|
||||
super.onSubmit();
|
||||
reflectionService.submitReflection(getModelObject(), SciProSession.get().getUser(), reflectionModel.getObject());
|
||||
publishingConsentService.setPublishingConsent(getModelObject(), SciProSession.get().getUser(), levelModel.getObject());
|
||||
success(getString("reflection_submitted"));
|
||||
}
|
||||
}
|
||||
|
@ -2,3 +2,5 @@ reflection_submitted = Reflection submitted
|
||||
explain_reflection = You've had your final seminar, and it is now time to reflect back on the entire thesis process.
|
||||
reflection = Reflection
|
||||
submit = Submit
|
||||
publishing_consent=How may your thesis be published
|
||||
publishingConsentLevel.Required=You must decide how your thesis may be published.
|
||||
|
@ -115,3 +115,7 @@ nullValid=Choose one
|
||||
|
||||
research_area_inactive=${title} (inactive)
|
||||
research_area_active=${title}
|
||||
|
||||
Level.DO_NOT_PUBLISH=Do not publish
|
||||
Level.PUBLISH_INTERNALLY=Available to students within the department
|
||||
Level.PUBLISH=Public
|
||||
|
@ -42,6 +42,7 @@ import se.su.dsv.scipro.finalseminar.FinalSeminarService;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminarSettingsService;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminarUploadController;
|
||||
import se.su.dsv.scipro.finalthesis.FinalThesisService;
|
||||
import se.su.dsv.scipro.finalthesis.PublishingConsentService;
|
||||
import se.su.dsv.scipro.forum.BasicForumService;
|
||||
import se.su.dsv.scipro.forum.GroupForumService;
|
||||
import se.su.dsv.scipro.forum.ProjectForumService;
|
||||
@ -342,6 +343,8 @@ public abstract class SciProTest {
|
||||
protected Reporter reporter;
|
||||
@Mock
|
||||
protected ReflectionService reflectionService;
|
||||
@Mock
|
||||
protected PublishingConsentService publishingConsentService;
|
||||
|
||||
protected WicketTester tester;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user