diff --git a/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/CollectedVolumePropertiesStep.java b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/CollectedVolumePropertiesStep.java
index bfaad8b..710c67e 100644
--- a/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/CollectedVolumePropertiesStep.java
+++ b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/CollectedVolumePropertiesStep.java
@@ -15,7 +15,6 @@ import org.scientificcms.publications.CollectedVolume;
import org.scientificcms.publications.CollectedVolumeManager;
import org.scientificcms.publications.PublicationRepository;
import org.scientificcms.publications.contenttypes.CollectedVolumeItem;
-import org.scientificcms.publications.contenttypes.MonographItem;
import org.scientificcms.publications.ui.SciPublicationsUiConstants;
import org.scientificcms.publications.ui.SciPublicationsUiMessageBundle;
diff --git a/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/InProcedingsRow.java b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/InProcedingsRow.java
new file mode 100644
index 0000000..303c3c4
--- /dev/null
+++ b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/InProcedingsRow.java
@@ -0,0 +1,64 @@
+package org.scientificcms.publications.ui.contenttypes;
+
+import java.util.Comparator;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class InProcedingsRow implements Comparable{
+
+ private String inProceedingsUuid;
+
+ private String title;
+
+ private Integer startPage;
+
+ private Integer endPage;
+
+ public String getInProceedingsUuid() {
+ return inProceedingsUuid;
+ }
+
+ public void setInProceedingsUuid(final String inProceedingsUuid) {
+ this.inProceedingsUuid = inProceedingsUuid;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+ public Integer getStartPage() {
+ return startPage;
+ }
+
+ public void setStartPage(final Integer startPage) {
+ this.startPage = startPage;
+ }
+
+ public Integer getEndPage() {
+ return endPage;
+ }
+
+ public void setEndPage(final Integer endPage) {
+ this.endPage = endPage;
+ }
+
+ @Override
+ public int compareTo(final InProcedingsRow other) {
+ return Comparator
+ .nullsFirst(
+ Comparator.comparing(InProcedingsRow::getStartPage)
+ .thenComparing(InProcedingsRow::getEndPage)
+ .thenComparing(InProcedingsRow::getTitle)
+ )
+ .compare(this, other);
+ }
+
+
+
+}
diff --git a/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/ProceedingsPropertiesStep.java b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/ProceedingsPropertiesStep.java
new file mode 100644
index 0000000..73f6f97
--- /dev/null
+++ b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/ProceedingsPropertiesStep.java
@@ -0,0 +1,555 @@
+package org.scientificcms.publications.ui.contenttypes;
+
+import freemarker.template.utility.DateUtil;
+import org.libreccm.api.IdentifierParser;
+import org.libreccm.l10n.GlobalizationHelper;
+import org.libreccm.security.AuthorizationRequired;
+import org.librecms.ui.contentsections.ContentSectionNotFoundException;
+import org.librecms.ui.contentsections.ItemPermissionChecker;
+import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
+import org.librecms.ui.contentsections.documents.DocumentUi;
+import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
+import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
+import org.scientificcms.publications.InProceedings;
+import org.scientificcms.publications.Proceedings;
+import org.scientificcms.publications.ProceedingsManager;
+import org.scientificcms.publications.PublicationRepository;
+import org.scientificcms.publications.contenttypes.ProceedingsItem;
+import org.scientificcms.publications.ui.SciPublicationsUiConstants;
+import org.scientificcms.publications.ui.SciPublicationsUiMessageBundle;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.mvc.Controller;
+import javax.mvc.Models;
+import javax.transaction.Transactional;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path(
+ MvcAuthoringSteps.PATH_PREFIX
+ + ProceedingsPropertiesStep.EDIT_STEP_URL_FRAGMENT
+)
+@Controller
+@MvcAuthoringStepDef(
+ bundle = SciPublicationsUiConstants.BUNDLE,
+ descriptionKey = "authoringsteps.basicproperties.description",
+ labelKey = "authoringsteps.basicproperties.label",
+ supportedDocumentType = ProceedingsItem.class
+)
+public class ProceedingsPropertiesStep
+ extends AbstractPublicationWithPublisherPropertiesStep {
+
+ public static final String EDIT_STEP_URL_FRAGMENT
+ = "proceedings-basicproperties";
+
+ @Inject
+ private DocumentUi documentUi;
+
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ @Inject
+ private IdentifierParser identifierParser;
+
+ @Inject
+ private ItemPermissionChecker itemPermissionChecker;
+
+ @Inject
+ private ProceedingsManager proceedingsManager;
+
+ @Inject
+ private ProceedingsPropertiesStepModel propertiesStepModel;
+
+ @Inject
+ private Models models;
+
+ @Inject
+ private PublicationRepository publicationRepo;
+
+ @Inject
+ private SciPublicationsUiMessageBundle messageBundle;
+
+ @Override
+ public Class getStepClass() {
+ return ProceedingsPropertiesStep.class;
+ }
+
+ @Override
+ protected String getEditStepUrlFragment() {
+ return EDIT_STEP_URL_FRAGMENT;
+ }
+
+ @Override
+ public Class getPublicationClass() {
+ return Proceedings.class;
+ }
+
+ @Override
+ protected String getStepTemplatePath() {
+ return "org/scientificcms/contenttypes/ui/proceedings/edit-proceedings.xhtml";
+ }
+
+ @Override
+ @Transactional(Transactional.TxType.REQUIRED)
+ protected void init() throws ContentSectionNotFoundException,
+ DocumentNotFoundException {
+ super.init();
+
+ final DateTimeFormatter isoDateFormatter = DateTimeFormatter.ISO_DATE
+ .withZone(ZoneId.systemDefault());
+
+ propertiesStepModel.setEndDate(
+ Optional
+ .ofNullable(getPublication().getEndDate())
+ .map(endDate -> isoDateFormatter.format(endDate))
+ .orElse(null)
+ );
+ propertiesStepModel.setInProceedings(
+ getPublication()
+ .getPapers()
+ .stream()
+ .map(this::buildInProcedingsRow)
+ .collect(Collectors.toList())
+ );
+ propertiesStepModel.setNameOfConference(
+ getPublication().getNameOfConference()
+ );
+ propertiesStepModel.setOrganizer(
+ Optional
+ .ofNullable(getPublication().getOrganizer())
+ .map(organizer -> organizer.getName())
+ .orElse(null)
+ );
+ propertiesStepModel.setPlaceOfConference(
+ getPublication().getPlaceOfConference()
+ );
+ propertiesStepModel.setStartDate(
+ Optional
+ .ofNullable(getPublication().getStartDate())
+ .map(startDate -> isoDateFormatter.format(startDate))
+ .orElse(null)
+ );
+ }
+
+ @GET
+ @Path("/")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String showStep(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath
+ ) {
+ return super.showStep(sectionIdentifier, documentPath);
+ }
+
+ @POST
+ @Path("/name")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String updateName(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("name") @DefaultValue("")
+ final String name
+ ) {
+ return super.updateName(sectionIdentifier, documentPath, name);
+ }
+
+ @POST
+ @Path("/title/@add")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String addTitle(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ return super.addTitle(
+ sectionIdentifier,
+ documentPath,
+ localeParam,
+ value
+ );
+ }
+
+ @POST
+ @Path("/title/@edit/{locale}")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String editTitle(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ return super.editTitle(
+ sectionIdentifier,
+ documentPath,
+ localeParam,
+ value
+ );
+ }
+
+ @POST
+ @Path("/title/@remove/{locale}")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String removeTitle(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam
+ ) {
+ return super.removeTitle(sectionIdentifier, documentPath, localeParam);
+ }
+
+ @POST
+ @Path("/shortdescription/@add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String addShortDescription(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ return super.addShortDescription(
+ sectionIdentifier,
+ documentPath,
+ localeParam,
+ value
+ );
+ }
+
+ @POST
+ @Path("/shortdescription/@edit/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String editShortDescription(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam,
+ @FormParam("value") final String value
+ ) {
+ return super.editShortDescription(
+ sectionIdentifier,
+ documentPath,
+ localeParam,
+ value
+ );
+ }
+
+ @POST
+ @Path("/shortdescription/@remove/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String removeShortDescription(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("locale") final String localeParam
+ ) {
+ return super.removeShortDescription(
+ sectionIdentifier,
+ documentPath,
+ localeParam
+ );
+ }
+
+ @POST
+ @Path("/authors")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String addAuthor(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("authorIdentifier")
+ final String authorIdentifier,
+ @FormParam("editor")
+ final String editorParam
+ ) {
+ return super.addAuthor(
+ sectionIdentifier,
+ documentPath,
+ authorIdentifier,
+ editorParam
+ );
+ }
+
+ @POST
+ @Path("/authors/{authorshipUuid}")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String editAuthorship(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("authorshipUuid")
+ final String authorshipUuid,
+ @FormParam("editor")
+ final String editorParam
+ ) {
+ return super.editAuthorship(
+ sectionIdentifier,
+ documentPath,
+ authorshipUuid,
+ editorParam
+ );
+ }
+
+ @POST
+ @Path("/authors/{authorshipUuid}/remove")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String removeAuthorship(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("authorshipUuid")
+ final String authorshipUuid
+ ) {
+ return super.removeAuthorship(
+ sectionIdentifier,
+ documentPath,
+ authorshipUuid
+ );
+ }
+
+ @POST
+ @Path("/publisher")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String setPublisher(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("publisherIdentifier")
+ final String publisherIdentifier
+ ) {
+ return super.setPublisher(
+ sectionIdentifier,
+ documentPath,
+ publisherIdentifier
+ );
+ }
+
+ @POST
+ @Path("/publisher/@remove")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ public String removePublisher(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath
+ ) {
+ return super.removePublisher(sectionIdentifier, documentPath);
+ }
+
+ @POST()
+ @Path("/properties")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String updateProperties(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("yearOfPublication")
+ final String yearOfPublicationParam,
+ @FormParam("nameOfConference")
+ final String nameOfConference,
+ @FormParam("placeOfConference")
+ final String placeOfConference,
+ @FormParam("startDate")
+ final String startDateParam,
+ @FormParam("endDateParam")
+ final String endDateParam
+ ) {
+ super.updateProperties(
+ sectionIdentifier,
+ documentPath,
+ yearOfPublicationParam
+ );
+
+ final DateTimeFormatter isoDateFormatter = DateTimeFormatter.ISO_DATE
+ .withZone(ZoneId.systemDefault());
+
+ final LocalDate startDate;
+ try {
+ startDate = Optional
+ .ofNullable(startDateParam)
+ .filter(param -> !param.isBlank())
+ .map(param -> LocalDate.parse(param, isoDateFormatter))
+ .orElse(null);
+ } catch (DateTimeParseException ex) {
+ return showInvalidStartDate(
+ sectionIdentifier,
+ documentPath,
+ startDateParam
+ );
+ }
+
+ final LocalDate endDate;
+ try {
+ endDate = Optional
+ .ofNullable(endDateParam)
+ .filter(param -> !param.isBlank())
+ .map(param -> LocalDate.parse(param, isoDateFormatter))
+ .orElse(null);
+ } catch (DateTimeParseException ex) {
+ return showInvalidEndDate(
+ sectionIdentifier,
+ documentPath,
+ endDateParam
+ );
+ }
+
+ getPublication().setEndDate(endDate);
+ getPublication().setNameOfConference(nameOfConference);
+ getPublication().setPlaceOfConference(placeOfConference);
+ getPublication().setStartDate(startDate);
+
+ return buildRedirectPathForStep();
+ }
+
+ @POST
+ @Path("/papers")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String addPaper(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("paperIdentifier")
+ final String paperIdentifier
+ ) {
+ throw new UnsupportedOperationException();
+ }
+
+ @POST
+ @Path("/papers/{paperUuid}/remove")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String removePaper(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("paperUuid")
+ final String paperUuid
+ ) {
+ throw new UnsupportedOperationException();
+ }
+
+ @POST
+ @Path("/organizer")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String setOrganizer(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("organizerIdentifier")
+ final String organizerIdentifier
+ ) {
+ throw new UnsupportedOperationException();
+ }
+
+ @POST
+ @Path("/organizer/@remove")
+ @AuthorizationRequired
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String removeOrganizer(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath
+ ) {
+ throw new UnsupportedOperationException();
+ }
+
+ private String showInvalidStartDate(
+ final String sectionIdentifier,
+ final String documentPath,
+ final String startDateParam
+ ) {
+ models.put("invalidStartDate", startDateParam);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ private String showInvalidEndDate(
+ final String sectionIdentifier,
+ final String documentPath,
+ final String endDateParam
+ ) {
+ models.put("invalidEndDate", endDateParam);
+ return showStep(sectionIdentifier, documentPath);
+ }
+
+ private InProcedingsRow buildInProcedingsRow(
+ final InProceedings inProceedings
+ ) {
+ final InProcedingsRow row = new InProcedingsRow();
+ row.setEndPage(inProceedings.getEndPage());
+ row.setInProceedingsUuid(inProceedings.getUuid());
+ row.setStartPage(inProceedings.getStartPage());
+ row.setTitle(
+ globalizationHelper.getValueFromLocalizedString(
+ inProceedings.getTitle()
+ )
+ );
+
+ return row;
+ }
+
+}
diff --git a/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/ProceedingsPropertiesStepModel.java b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/ProceedingsPropertiesStepModel.java
new file mode 100644
index 0000000..114ac42
--- /dev/null
+++ b/sci-publications/src/main/java/org/scientificcms/publications/ui/contenttypes/ProceedingsPropertiesStepModel.java
@@ -0,0 +1,84 @@
+package org.scientificcms.publications.ui.contenttypes;
+
+import org.scientificcms.publications.InProceedings;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("SciCmsProceedingsStepModel")
+public class ProceedingsPropertiesStepModel {
+
+ private String nameOfConference;
+
+ private String placeOfConference;
+
+ private String startDate;
+
+ private String endDate;
+
+ private String organizer;
+
+ private List inProceedings;
+
+ public String getInProceedingsType() {
+ return InProceedings.class.getName();
+ }
+
+ public String getNameOfConference() {
+ return nameOfConference;
+ }
+
+ public void setNameOfConference(final String nameOfConference) {
+ this.nameOfConference = nameOfConference;
+ }
+
+ public String getPlaceOfConference() {
+ return placeOfConference;
+ }
+
+ public void setPlaceOfConference(final String placeOfConference) {
+ this.placeOfConference = placeOfConference;
+ }
+
+ public String getStartDate() {
+ return startDate;
+ }
+
+ public void setStartDate(final String startDate) {
+ this.startDate = startDate;
+ }
+
+ public String getEndDate() {
+ return endDate;
+ }
+
+ public void setEndDate(final String endDate) {
+ this.endDate = endDate;
+ }
+
+ public String getOrganizer() {
+ return organizer;
+ }
+
+ public void setOrganizer(final String organizer) {
+ this.organizer = organizer;
+ }
+
+ public List getInProceedings() {
+ return Collections.unmodifiableList(inProceedings);
+ }
+
+ public void setInProceedings(final List inProceedings) {
+ this.inProceedings = new ArrayList<>(inProceedings);
+ }
+
+}