diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ContactRepository.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ContactRepository.java new file mode 100644 index 0000000..1ede221 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ContactRepository.java @@ -0,0 +1,42 @@ +package org.scientificcms.contenttypes.sciproject; + +import org.libreccm.auditing.AbstractAuditedEntityRepository; + +import javax.enterprise.context.RequestScoped; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class ContactRepository + extends AbstractAuditedEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Long getEntityId(final Contact contact) { + return contact.getContactId(); + } + + @Override + public Class getEntityClass() { + return Contact.class; + } + + @Override + public String getIdAttributeName() { + return "contactId"; + } + + @Override + public Long getIdOfEntity(final Contact contact) { + return contact.getContactId(); + } + + @Override + public boolean isNew(final Contact contact) { + return contact.getContactId() == 0; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/MembershipRepository.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/MembershipRepository.java new file mode 100644 index 0000000..87e9f70 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/MembershipRepository.java @@ -0,0 +1,42 @@ +package org.scientificcms.contenttypes.sciproject; + +import org.libreccm.auditing.AbstractAuditedEntityRepository; + +import javax.enterprise.context.RequestScoped; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class MembershipRepository + extends AbstractAuditedEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Long getEntityId(final Membership membership) { + return membership.getMembershipId(); + } + + @Override + public Class getEntityClass() { + return Membership.class; + } + + @Override + public String getIdAttributeName() { + return "membershipId"; + } + + @Override + public Long getIdOfEntity(final Membership membership) { + return membership.getMembershipId(); + } + + @Override + public boolean isNew(final Membership membership) { + return membership.getMembershipId() == 0; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectMananger.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectMananger.java index f256a1d..06f1424 100644 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectMananger.java +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectMananger.java @@ -9,6 +9,7 @@ import org.librecms.assets.ContactableEntity; import org.librecms.assets.Organization; import org.librecms.assets.Person; import org.librecms.contentsection.ContentItemRepository; +import org.librecms.ui.contentsections.ContentSectionsUi; import java.io.Serializable; import java.util.Objects; @@ -28,10 +29,16 @@ public class SciProjectMananger implements Serializable { private static final long serialVersionUID = 1L; @Inject - private ContentItemRepository contentItemRepository; - + private ContactRepository contactRepo; + @Inject - private SciProjectRepository sciProjectRepository; + private ContentItemRepository itemRepo; + + @Inject + private MembershipRepository membershipRepo; + + @Inject + private SponsoringRepository sponsoringRepo; @Transactional(Transactional.TxType.REQUIRED) public void addContact(final ContactableEntity contactable, @@ -50,8 +57,9 @@ public class SciProjectMananger implements Serializable { contact.setOrder(toProject.getContacts().size()); toProject.addContact(contact); + contactRepo.save(contact); - contentItemRepository.save(toProject); + itemRepo.save(toProject); } @Transactional(Transactional.TxType.REQUIRED) @@ -74,7 +82,8 @@ public class SciProjectMananger implements Serializable { if (result.isPresent()) { final Contact remove = result.get(); fromProject.removeContact(remove); - contentItemRepository.save(fromProject); + itemRepo.save(fromProject); + contactRepo.delete(remove); } } @@ -101,7 +110,8 @@ public class SciProjectMananger implements Serializable { toProject.addMember(membership); - contentItemRepository.save(toProject); + membershipRepo.save(membership); + itemRepo.save(toProject); } @Transactional(Transactional.TxType.REQUIRED) @@ -128,7 +138,8 @@ public class SciProjectMananger implements Serializable { if (result.isPresent()) { final Membership remove = result.get(); fromProject.removeMembership(remove); - contentItemRepository.save(fromProject); + itemRepo.save(fromProject); + membershipRepo.delete(remove); } } @@ -149,7 +160,8 @@ public class SciProjectMananger implements Serializable { toProject.addSponsor(sponsoring); - contentItemRepository.save(toProject); + sponsoringRepo.save(sponsoring); + itemRepo.save(toProject); } @Transactional(Transactional.TxType.REQUIRED) @@ -169,7 +181,8 @@ public class SciProjectMananger implements Serializable { if (result.isPresent()) { final Sponsoring sponsoring = result.get(); fromProject.removeSponsor(sponsoring); - contentItemRepository.save(fromProject); + sponsoringRepo.delete(sponsoring); + itemRepo.save(fromProject); } } diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SponsoringRepository.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SponsoringRepository.java new file mode 100644 index 0000000..eb70f8b --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SponsoringRepository.java @@ -0,0 +1,42 @@ +package org.scientificcms.contenttypes.sciproject; + +import org.libreccm.auditing.AbstractAuditedEntityRepository; + +import javax.enterprise.context.RequestScoped; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class SponsoringRepository + extends AbstractAuditedEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Long getEntityId(final Sponsoring sponsoring) { + return sponsoring.getSponsoringId(); + } + + @Override + public Class getEntityClass() { + return Sponsoring.class; + } + + @Override + public String getIdAttributeName() { + return "sponsoringId"; + } + + @Override + public Long getIdOfEntity(final Sponsoring sponsoring) { + return sponsoring.getSponsoringId(); + } + + @Override + public boolean isNew(final Sponsoring sponsoring) { + return sponsoring.getSponsoringId() == 0; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionContactsModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionContactsModel.java index 6c8ee42..5577bf1 100644 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionContactsModel.java +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionContactsModel.java @@ -23,6 +23,10 @@ public class SciProjectDescriptionContactsModel { return canEdit; } + protected void setCanEdit(final boolean canEdit) { + this.canEdit = canEdit; + } + public List getContacts() { return Collections.unmodifiableList(contacts); } @@ -31,8 +35,4 @@ public class SciProjectDescriptionContactsModel { this.contacts = new ArrayList<>(contacts); } - protected void setCanEdit(final boolean canEdit) { - this.canEdit = canEdit; - } - } diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStep.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStep.java index d1f53ae..b5a02c9 100644 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStep.java +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStep.java @@ -77,9 +77,6 @@ public class SciProjectDescriptionStep extends AbstractMvcAuthoringStep { @Inject private AssetRepository assetRepo; - @Inject - private ContactableEntityRepository contactableRepo; - @Inject private ContentItemRepository itemRepo; @@ -135,7 +132,7 @@ public class SciProjectDescriptionStep extends AbstractMvcAuthoringStep { return documentUi.showAccessDenied( getContentSection(), getProject(), - sciProjectMessageBundle.getMessage("event.edit.denied") + sciProjectMessageBundle.getMessage("sciproject.edit.denied") ); } } @@ -520,10 +517,12 @@ public class SciProjectDescriptionStep extends AbstractMvcAuthoringStep { .getValues() .entrySet() .stream() - .collect(Collectors.toMap( - entry -> entry.getKey().toString(), - Map.Entry::getValue - )) + .collect( + Collectors.toMap( + entry -> entry.getKey().toString(), + Map.Entry::getValue + ) + ) ); descriptionModel.setVariants( getProject() @@ -558,10 +557,10 @@ public class SciProjectDescriptionStep extends AbstractMvcAuthoringStep { membersModel.setCanEdit(canEdit); membersModel.setMembers( getProject() - .getMembers() - .stream() - .map(this::buildMembershipModel) - .collect(Collectors.toList()) + .getMembers() + .stream() + .map(this::buildMembershipModel) + .collect(Collectors.toList()) ); } diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepService.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepService.java new file mode 100644 index 0000000..ae66eac --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepService.java @@ -0,0 +1,132 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.ui.contentsections.ContentSectionsUi; +import org.librecms.ui.contentsections.documents.MvcAuthoringSteps; +import org.scientificcms.contenttypes.sciproject.Contact; +import org.scientificcms.contenttypes.sciproject.ContactRepository; +import org.scientificcms.contenttypes.sciproject.MembershipRepository; +import org.scientificcms.contenttypes.sciproject.SciProject; +import org.scientificcms.contenttypes.sciproject.SciProjectRepository; + +import java.util.List; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.transaction.Transactional; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.Consumes; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path(MvcAuthoringSteps.PATH_PREFIX + "sciproject-description-service") +public class SciProjectDescriptionStepService { + + @Inject + private ContactRepository contactRepo; + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private ContentSectionsUi sectionsUi; + + @POST + @Path("/contacts/save-order") + @Consumes(MediaType.APPLICATION_JSON) + @Transactional(Transactional.TxType.REQUIRED) + public Response saveContactsOrder( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + final List contactsOrder + ) { + final ContentSection contentSection = sectionsUi + .findContentSection(sectionIdentifier) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No content identifed by %s found.", + sectionIdentifier + ) + ) + ); + + final ContentItem document = itemRepo + .findByPath(contentSection, documentPath) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No document for path %s in section %s.", + documentPath, + contentSection.getLabel() + ) + ) + ); + + if ((document instanceof SciProject)) { + throw new BadRequestException( + String.format( + "Document %s is not a %s.", + documentPath, + SciProject.class.getSimpleName() + ) + ); + } + + final SciProject project = (SciProject) document; + + final List contacts = project.getContacts(); + + if (contactsOrder.size() != contacts.size()) { + throw new BadRequestException( + String.format( + "Number of contacts of the SciProject %s does " + + "not match the number of values in the order " + + "list. Number of contactas: %d, number of values in " + + "the contacts order list: %d", + documentPath, + contacts.size(), + contactsOrder.size() + ) + ); + } + + for (int i = 0; i < contactsOrder.size(); i++) { + final String contactIdParam = contactsOrder.get(i); + final long contactId = Long.parseLong(contactIdParam); + final Contact contact = contacts + .stream() + .filter(con -> con.getContactId() == contactId) + .findAny() + .orElseThrow( + () -> new BadRequestException( + String.format( + "contactsOrder has an entry for contact with " + + "ID %d, but there is not contact with that " + + "ID.", + contactId + ) + ) + ); + + contact.setOrder(i); + contactRepo.save(contact); + } + + return Response.ok().build(); + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingSponsoringModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingSponsoringModel.java new file mode 100644 index 0000000..af8b0eb --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingSponsoringModel.java @@ -0,0 +1,41 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +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("SciProjectFundingSponsoring") +public class SciProjectFundingSponsoringModel { + + private boolean canEdit; + + private List sponsoring; + + public boolean getCanEdit() { + return canEdit; + } + + protected void setCanEdit(final boolean canEdit) { + this.canEdit = canEdit; + } + + public List getSponsoring() { + return Collections.unmodifiableList(sponsoring); + } + + protected void setSponsoring( + final List sponsoring + ) { + this.sponsoring = new ArrayList<>(sponsoring); + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStep.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStep.java new file mode 100644 index 0000000..3ce370f --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStep.java @@ -0,0 +1,661 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.assets.Organization; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.ui.contentsections.ContentSectionNotFoundException; +import org.librecms.ui.contentsections.ItemPermissionChecker; +import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep; +import org.librecms.ui.contentsections.documents.CmsEditorUtil; +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.contenttypes.sciproject.SciProject; +import org.scientificcms.contenttypes.sciproject.SciProjectMananger; +import org.scientificcms.contenttypes.sciproject.Sponsoring; + +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +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.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 + "sciproject-funding") +@Controller +@MvcAuthoringStepDef( + bundle = SciProjectStepsConstants.BUNDLE, + descriptionKey = "authoringsteps.projectfunding.description", + labelKey = "authoringsteps.projectfunding.label", + supportedDocumentType = SciProject.class +) +public class SciProjectFundingStep extends AbstractMvcAuthoringStep { + + @Inject + private SciProjectMessageBundle sciProjectMessageBundle; + + @Inject + private AssetRepository assetRepo; + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private DocumentUi documentUi; + + @Inject + private GlobalizationHelper globalizationHelper; + + @Inject + private ItemPermissionChecker itemPermissionChecker; + + @Inject + private Models models; + + @Inject + private SciProjectMananger projectManager; + + @Inject + private SciProjectFundingTextModel fundingTextModel; + + @Inject + private SciProjectFundingVolumeModel fundingVolumeModel; + + @Inject + private SciProjectFundingSponsoringModel sponsoringModel; + + @Override + public Class getStepClass() { + return SciProjectFundingStep.class; + } + + @GET + @Path("/") + @Transactional(Transactional.TxType.REQUIRED) + public String showStep( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-funding.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @GET + @Path("/funding-text/view/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String viewFundingText( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + fundingTextModel.setSelectedLocale( + new Locale(localeParam).toString() + ); + + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-fundingtext/view.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/funding-text/add") + @Transactional(Transactional.TxType.REQUIRED) + public String addFundingTextValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final String value; + if (getProject().getFunding().getAvailableLocales().isEmpty()) { + value = ""; + } else { + value = globalizationHelper.getValueFromLocalizedString( + getProject().getFunding() + ); + } + final Locale locale = new Locale(localeParam); + getProject().getFunding().putValue(locale, value); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @GET + @Path("/funding-text/edit") + @Transactional(Transactional.TxType.REQUIRED) + public String editFundingTextValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + fundingTextModel.setSelectedLocale( + new Locale(localeParam).toString() + ); + + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-fundingtext/edit.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/funding-text/edit/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String editFundingTextValue( + @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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Locale locale = new Locale(localeParam); + getProject().getFunding().putValue(locale, value); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/funding-text/remove/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String removeFundingTextValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Locale locale = new Locale(localeParam); + getProject().getFunding().removeValue(locale); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @GET + @Path("/funding-volume/view/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String viewFundingVolume( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + fundingVolumeModel.setSelectedLocale( + new Locale(localeParam).toString() + ); + + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-fundingvolume/view.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/funding-volume/add") + @Transactional(Transactional.TxType.REQUIRED) + public String addFundingVolumeValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final String value; + if (getProject().getFundingVolume().getAvailableLocales().isEmpty()) { + value = ""; + } else { + value = globalizationHelper.getValueFromLocalizedString( + getProject().getFundingVolume() + ); + } + final Locale locale = new Locale(localeParam); + getProject().getFundingVolume().putValue(locale, value); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @GET + @Path("/funding-volume/edit") + @Transactional(Transactional.TxType.REQUIRED) + public String editFundingVolumeValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + fundingVolumeModel.setSelectedLocale( + new Locale(localeParam).toString() + ); + + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-fundingtext/edit.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/funding-volume/edit/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String editFundingVolumeValue( + @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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Locale locale = new Locale(localeParam); + getProject().getFundingVolume().putValue(locale, value); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/funding-volume/remove/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String removeFundingVolumeValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @PathParam("locale") final String localeParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Locale locale = new Locale(localeParam); + getProject().getFundingVolume().removeValue(locale); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/sponsoring/add") + @Transactional(Transactional.TxType.REQUIRED) + public String addSponsoring( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("sponsorUuid") + final String sponsorUuid, + @FormParam("fundingCode") + final String fundingCode + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Optional result = assetRepo + .findByUuidAndType(sponsorUuid, Organization.class); + + if (!result.isPresent()) { + models.put("sponsorNotFound", sponsorUuid); + return showStep(sectionIdentifier, documentPath); + } + + final Organization sponsor = result.get(); + projectManager.addSponsor(sponsor, getProject(), fundingCode); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/sponsoring/remove") + @Transactional(Transactional.TxType.REQUIRED) + public String removeSponsor( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("sponsoringId") + final String sponsoringId + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Optional result = getProject() + .getSponsoring() + .stream() + .filter( + sponsoring -> Long + .toString(sponsoring.getSponsoringId()) + .equals(sponsoringId) + ) + .findFirst(); + + if (result.isPresent()) { + projectManager.removeSponsor( + result.get().getSponsor(), + getProject() + ); + } + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @Override + public void init() throws ContentSectionNotFoundException, + DocumentNotFoundException { + super.init(); + + final boolean canEdit = itemPermissionChecker.canEditItem(getProject()); + if (canEdit) { + fundingTextModel.setCanEdit(canEdit); + fundingTextModel.setFundingTextValues( + getProject() + .getFunding() + .getValues() + .entrySet() + .stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toString(), + Map.Entry::getValue + ) + ) + ); + fundingTextModel.setVariants( + getProject() + .getFunding() + .getValues() + .entrySet() + .stream() + .map(CmsEditorUtil::buildVariantRow) + .collect(Collectors.toList()) + ); + final Set fundingTextLocales = getProject() + .getFunding() + .getAvailableLocales(); + fundingTextModel.setUnusedLocales( + globalizationHelper + .getAvailableLocales() + .stream() + .filter(locale -> !fundingTextLocales.contains(locale)) + .map(Locale::toString) + .collect(Collectors.toList()) + ); + + fundingVolumeModel.setCanEdit(canEdit); + fundingVolumeModel.setFundingVolumeValues( + getProject() + .getFundingVolume() + .getValues() + .entrySet() + .stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toString(), + Map.Entry::getValue + ) + ) + ); + fundingVolumeModel.setVariants( + getProject() + .getFundingVolume() + .getValues() + .entrySet() + .stream() + .map(CmsEditorUtil::buildVariantRow) + .collect(Collectors.toList()) + ); + final Set fundingVolumeLocales = getProject() + .getProjectDescription() + .getAvailableLocales(); + fundingVolumeModel.setUnusedLocales( + globalizationHelper + .getAvailableLocales() + .stream() + .filter(locale -> !fundingVolumeLocales.contains(locale)) + .map(Locale::toString) + .collect(Collectors.toList()) + ); + + sponsoringModel.setCanEdit(canEdit); + sponsoringModel.setSponsoring( + getProject() + .getSponsoring() + .stream() + .map(this::buildSponsoringModel) + .collect(Collectors.toList()) + ); + } + } + + private SciProject getProject() { + return (SciProject) getDocument(); + } + + private SciProjectSponsoringModel buildSponsoringModel( + final Sponsoring sponsoring + ) { + final SciProjectSponsoringModel model = new SciProjectSponsoringModel(); + model.setFundingCode(sponsoring.getFundingCode()); + model.setOrder(sponsoring.getOrder()); + model.setSponsor(sponsoring.getSponsor().getTitle().getValue( + globalizationHelper.getNegotiatedLocale() + )); + model.setSponsoringId(sponsoring.getSponsoringId()); + + return model; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStepService.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStepService.java new file mode 100644 index 0000000..0d9b496 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStepService.java @@ -0,0 +1,127 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.ui.contentsections.ContentSectionsUi; +import org.librecms.ui.contentsections.documents.MvcAuthoringSteps; +import org.scientificcms.contenttypes.sciproject.SciProject; +import org.scientificcms.contenttypes.sciproject.Sponsoring; +import org.scientificcms.contenttypes.sciproject.SponsoringRepository; + +import java.util.List; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.transaction.Transactional; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Response; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path(MvcAuthoringSteps.PATH_PREFIX + "sciproject-funding-service") +public class SciProjectFundingStepService { + + @Inject + private SponsoringRepository sponsoringRepo; + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private ContentSectionsUi sectionsUi; + + @POST + @Path("/sponsoring/save-order") + @Transactional(Transactional.TxType.REQUIRED) + public Response saveSponsoringOrder( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + final List sponsoringOrder + ) { + final ContentSection contentSection = sectionsUi + .findContentSection(sectionIdentifier) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No content identifed by %s found.", + sectionIdentifier + ) + ) + ); + + final ContentItem document = itemRepo + .findByPath(contentSection, documentPath) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No document for path %s in section %s.", + documentPath, + contentSection.getLabel() + ) + ) + ); + + if ((document instanceof SciProject)) { + throw new BadRequestException( + String.format( + "Document %s is not a %s.", + documentPath, + SciProject.class.getSimpleName() + ) + ); + } + + final SciProject project = (SciProject) document; + + final List sponsorings = project.getSponsoring(); + + if (sponsoringOrder.size() != sponsorings.size()) { + throw new BadRequestException( + String.format( + "Number of sponsorings of the SciProject %s does " + + "not match the number of values in the order " + + "list. Number of sponsoringas: %d, number of values in " + + "the sponsorings order list: %d", + documentPath, + sponsorings.size(), + sponsoringOrder.size() + ) + ); + } + + for (int i = 0; i < sponsoringOrder.size(); i++) { + final String sponsoringIdParam = sponsoringOrder.get(i); + final long sponsoringId = Long.parseLong(sponsoringIdParam); + final Sponsoring sponsoring = sponsorings + .stream() + .filter(sponsor -> sponsor.getSponsoringId() == sponsoringId) + .findAny() + .orElseThrow( + () -> new BadRequestException( + String.format( + "sponsoringsOrder has an entry for sponsoring with " + + "ID %d, but there is not sponsoring with that " + + "ID.", + sponsoringId + ) + ) + ); + + sponsoring.setOrder(i); + sponsoringRepo.save(sponsoring); + } + + return Response.ok().build(); + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingTextModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingTextModel.java index 1d6666c..bef4065 100644 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingTextModel.java +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingTextModel.java @@ -37,7 +37,7 @@ public class SciProjectFundingTextModel { .orElse(Collections.emptyMap()); } - protected void setFundingValues( + protected void setFundingTextValues( final Map fundingValues ) { this.fundingValues = Optional diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectSponsoringModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectSponsoringModel.java new file mode 100644 index 0000000..2a4e208 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectSponsoringModel.java @@ -0,0 +1,51 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +/** + * DTO providing the information about a {@link Sponsoring} of a + * {@link SciProject} in an form that easy usable from a MVC template. + * + * @author Jens Pelzetter + */ +public class SciProjectSponsoringModel { + + private long sponsoringId; + + private String fundingCode; + + private long order; + + private String sponsor; + + public long getSponsoringId() { + return sponsoringId; + } + + public void setSponsoringId(final long sponsoringId) { + this.sponsoringId = sponsoringId; + } + + public String getFundingCode() { + return fundingCode; + } + + public void setFundingCode(final String fundingCode) { + this.fundingCode = fundingCode; + } + + public long getOrder() { + return order; + } + + public void setOrder(final long order) { + this.order = order; + } + + public String getSponsor() { + return sponsor; + } + + public void setSponsor(final String sponsor) { + this.sponsor = sponsor; + } + +}