diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java index fbf2e1c..352418f 100644 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java @@ -10,8 +10,6 @@ import javax.persistence.Entity; import org.hibernate.envers.Audited; import org.libreccm.l10n.LocalizedString; import org.librecms.contentsection.ContentItem; -import org.librecms.contenttypes.AuthoringKit; -import org.librecms.contenttypes.AuthoringStep; import org.librecms.contenttypes.ContentTypeDescription; import java.io.Serializable; diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectContactModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectContactModel.java new file mode 100644 index 0000000..d7e48bc --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectContactModel.java @@ -0,0 +1,70 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.librecms.assets.ContactableEntity; +import org.scientificcms.contenttypes.sciproject.Contact; + +/** + * DTO providing the information about a {@link Contact} of a {@link SciProject} + * in an form that easy usable from a MVC template. + * + * @author Jens Pelzetter + */ +public class SciProjectContactModel { + + /** + * The ID of the {@link Contact} represented by this object. + */ + private long contactId; + + /** + * The type of the contact. + * + * @see Contact#contactType + */ + private String contactType; + + /** + * Order of contact. + */ + private long order; + + /** + * The title of the {@link ContactableEntity} + * + * @see Contact#contactable + */ + private String contactable; + + public long getContactId() { + return contactId; + } + + public void setContactId(final long contactId) { + this.contactId = contactId; + } + + public String getContactType() { + return contactType; + } + + public void setContactType(final String contactType) { + this.contactType = contactType; + } + + public long getOrder() { + return order; + } + + public void setOrder(final long order) { + this.order = order; + } + + public String getContactable() { + return contactable; + } + + public void setContactable(final String contactable) { + this.contactable = contactable; + } + +} 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 new file mode 100644 index 0000000..6c8ee42 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionContactsModel.java @@ -0,0 +1,38 @@ +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("SciProjectDescriptionContacts") +public class SciProjectDescriptionContactsModel { + + private boolean canEdit; + + private List contacts; + + public boolean getCanEdit() { + return canEdit; + } + + public List getContacts() { + return Collections.unmodifiableList(contacts); + } + + protected void setContacts(final List contacts) { + 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/SciProjectDescriptionMembersModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionMembersModel.java new file mode 100644 index 0000000..8bd188c --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionMembersModel.java @@ -0,0 +1,42 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +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("SciProjectDescriptionMembers") +public class SciProjectDescriptionMembersModel { + + private boolean canEdit; + + private List members; + + public boolean getCanEdit() { + return canEdit; + } + + public List getMembers() { + return Collections.unmodifiableList(members); + } + + protected void setMembers(final List members) { + this.members = new ArrayList<>(members); + } + + protected void setCanEdit(final boolean canEdit) { + this.canEdit = canEdit; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionModel.java new file mode 100644 index 0000000..7b788b4 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionModel.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2022 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Named; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("SciProjectDescriptionModel") +public class SciProjectDescriptionModel { + + private boolean canEdit; + + private Map descriptionValues; + + private List variants; + + private List unusedLocales; + + private String selectedLocale; + + public Map getDescriptionValues() { + return Optional + .ofNullable(descriptionValues) + .map(Collections::unmodifiableMap) + .orElse(Collections.emptyMap()); + } + + protected void setDescriptionValues( + final Map descriptionValues + ) { + this.descriptionValues = Optional + .ofNullable(descriptionValues) + .map(values -> new HashMap<>(values)) + .map(values -> (Map) values) + .orElse(Collections.emptyMap()); + } + + public List getVariants() { + return Optional + .ofNullable(variants) + .map(Collections::unmodifiableList) + .orElse(Collections.emptyList()); + } + + protected void setVariants(final List variants) { + this.variants = Optional + .ofNullable(variants) + .map(list -> new ArrayList<>(list)) + .map(list -> (List) list) + .orElse(Collections.emptyList()); + } + + public List getUnusedLocales() { + return Optional + .ofNullable(unusedLocales) + .map(Collections::unmodifiableList) + .orElse(Collections.emptyList()); + } + + protected void setUnusedLocales(final List unusedLocales) { + this.unusedLocales = Optional + .ofNullable(unusedLocales) + .map(list -> new ArrayList<>(list)) + .map(list -> (List) list) + .orElse(Collections.emptyList()); + } + + public String getSelectedLocale() { + return selectedLocale; + } + + protected void setSelectedLocale(final String selectedLocale) { + this.selectedLocale = selectedLocale; + } + + public boolean getCanEdit() { + return canEdit; + } + + 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 new file mode 100644 index 0000000..d1f53ae --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStep.java @@ -0,0 +1,610 @@ +/* + * Copyright (C) 2022 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.assets.ContactableEntity; +import org.librecms.assets.ContactableEntityRepository; +import org.librecms.assets.Person; +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.Contact; +import org.scientificcms.contenttypes.sciproject.Membership; +import org.scientificcms.contenttypes.sciproject.MembershipStatus; +import org.scientificcms.contenttypes.sciproject.SciProject; +import org.scientificcms.contenttypes.sciproject.SciProjectMananger; + +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +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-description") +@Controller +@MvcAuthoringStepDef( + bundle = SciProjectStepsConstants.BUNDLE, + descriptionKey = "authoringsteps.projectdescription.description", + labelKey = "authoringsteps.projectdescription.label", + supportedDocumentType = SciProject.class +) +public class SciProjectDescriptionStep extends AbstractMvcAuthoringStep { + + @Inject + private SciProjectMessageBundle sciProjectMessageBundle; + + @Inject + private AssetRepository assetRepo; + + @Inject + private ContactableEntityRepository contactableRepo; + + @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 SciProjectDescriptionModel descriptionModel; + + @Inject + private SciProjectDescriptionContactsModel contactsModel; + + @Inject + private SciProjectDescriptionMembersModel membersModel; + + @Override + public Class getStepClass() { + return SciProjectDescriptionStep.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-description.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @GET + @Path("/description/view/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String viewDescription( + @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())) { + descriptionModel.setSelectedLocale(new Locale(localeParam) + .toString()); + + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-description/view.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/description/add") + @Transactional(Transactional.TxType.REQUIRED) + public String addDescriptionValue( + @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().getProjectDescription().getAvailableLocales() + .isEmpty()) { + value = ""; + } else { + value = globalizationHelper.getValueFromLocalizedString( + getProject().getProjectDescription() + ); + } + final Locale locale = new Locale(localeParam); + getProject().getProjectDescription().putValue(locale, value); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @GET + @Path("/description/edit/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String editDescriptionValue( + @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())) { + descriptionModel.setSelectedLocale( + new Locale(localeParam).toString() + ); + + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-description/edit.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/description/edit/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String editDescriptionValue( + @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().getProjectDescription().putValue(locale, value); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/description/remove/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String removeDescriptionValue( + @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().getProjectDescription().removeValue(locale); + itemRepo.save(getProject()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/contacts/add") + @Transactional(Transactional.TxType.REQUIRED) + public String addContact( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("contactableUuid") + final String contactableUuid, + @FormParam("type") + final String type + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Optional result = assetRepo + .findByUuidAndType(contactableUuid, ContactableEntity.class); + + if (!result.isPresent()) { + models.put("contactableNotFound", contactableUuid); + return showStep(sectionIdentifier, documentPath); + } + + final ContactableEntity contactable = result.get(); + projectManager.addContact(contactable, getProject(), type); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/contacts/remove") + @Transactional(Transactional.TxType.REQUIRED) + public String removeContact( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("contactId") + final String contactId + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Optional result = getProject() + .getContacts() + .stream() + .filter( + contact -> Long + .toString(contact.getContactId()) + .equals(contactId) + ) + .findFirst(); + + if (result.isPresent()) { + projectManager.removeContact( + result.get().getContactable(), + getProject() + ); + } + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/members/add") + @Transactional(Transactional.TxType.REQUIRED) + public String addMember( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("personUuid") + final String personUuid, + @FormParam("role") + final String role, + @FormParam("status") + final String statusParam + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Optional result = assetRepo + .findByUuidAndType(personUuid, Person.class); + + if (!result.isPresent()) { + models.put("personNotFound", personUuid); + return showStep(sectionIdentifier, documentPath); + } + + final Person person = result.get(); + final MembershipStatus status; + try { + status = MembershipStatus.valueOf( + statusParam + ); + } catch (IllegalArgumentException ex) { + models.put("illegalStatusValue", statusParam); + return showStep(sectionIdentifier, documentPath); + } + + projectManager.addMember(person, getProject(), role, status); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getProject(), + sciProjectMessageBundle.getMessage("event.edit.denied") + ); + } + } + + @POST + @Path("/members/remove") + @Transactional(Transactional.TxType.REQUIRED) + public String removeMember( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("membershipId") + final String membershipId + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getProject())) { + final Optional result = getProject() + .getMembers() + .stream() + .filter( + member -> Long + .toString(member.getMembershipId()) + .equals(membershipId) + ) + .findFirst(); + + if (result.isPresent()) { + projectManager.removeMember( + result.get().getMember(), + 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) { + descriptionModel.setCanEdit(canEdit); + descriptionModel.setDescriptionValues( + getProject() + .getProjectDescription() + .getValues() + .entrySet() + .stream() + .collect(Collectors.toMap( + entry -> entry.getKey().toString(), + Map.Entry::getValue + )) + ); + descriptionModel.setVariants( + getProject() + .getProjectDescription() + .getValues() + .entrySet() + .stream() + .map(CmsEditorUtil::buildVariantRow) + .collect(Collectors.toList()) + ); + final Set descriptionLocales = getProject() + .getProjectDescription() + .getAvailableLocales(); + descriptionModel.setUnusedLocales( + globalizationHelper + .getAvailableLocales() + .stream() + .filter(locale -> !descriptionLocales.contains(locale)) + .map(Locale::toString) + .collect(Collectors.toList()) + ); + + contactsModel.setCanEdit(canEdit); + contactsModel.setContacts( + getProject() + .getContacts() + .stream() + .map(this::buildContactModel) + .collect(Collectors.toList()) + ); + + membersModel.setCanEdit(canEdit); + membersModel.setMembers( + getProject() + .getMembers() + .stream() + .map(this::buildMembershipModel) + .collect(Collectors.toList()) + ); + + } + } + + private SciProject getProject() { + return (SciProject) getDocument(); + } + + private SciProjectContactModel buildContactModel(final Contact contact) { + final SciProjectContactModel model = new SciProjectContactModel(); + model.setContactId(contact.getContactId()); + model.setContactType(contact.getContactType()); + model.setContactable( + contact.getContactable().getTitle().getValue( + globalizationHelper.getNegotiatedLocale() + ) + ); + model.setOrder(contact.getOrder()); + + return model; + } + + private SciProjectMembershipModel buildMembershipModel( + final Membership membership + ) { + final SciProjectMembershipModel model = new SciProjectMembershipModel(); + model.setGivenName( + membership.getMember().getPersonName().getGivenName() + ); + model.setMembershipId(membership.getMembershipId()); + model.setPrefix( + membership.getMember().getPersonName().getPrefix() + ); + model.setStatus(Objects.toString(membership.getStatus())); + model.setSuffix( + membership.getMember().getPersonName().getSuffix() + ); + model.setSurname( + membership.getMember().getPersonName().getSurname() + ); + + return model; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStepResources.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStepResources.java new file mode 100644 index 0000000..7e3f157 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingStepResources.java @@ -0,0 +1,193 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +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.ItemPermissionChecker; +import org.librecms.ui.contentsections.documents.MvcAuthoringSteps; +import org.scientificcms.contenttypes.sciproject.SciProject; + +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.transaction.Transactional; +import javax.ws.rs.ForbiddenException; +import javax.ws.rs.GET; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path(MvcAuthoringSteps.PATH_PREFIX + "sciproject-funding-resources") +public class SciProjectFundingStepResources { + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private ContentSectionsUi sectionsUi; + + @Inject + private ItemPermissionChecker itemPermissionChecker; + + @GET + @Path("/project-funding/wordcount/{locale}") + @Produces(MediaType.TEXT_HTML) + @Transactional(Transactional.TxType.REQUIRED) + public String getProjectFundingWordCount( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPathParam, + @PathParam("locale") final String localeParam + ) { + final ContentSection contentSection = sectionsUi + .findContentSection(sectionIdentifier) + .orElseThrow( + () -> new NotFoundException() + ); + + final ContentItem document = itemRepo + .findByPath(contentSection, documentPathParam) + .orElseThrow( + () -> new NotFoundException() + ); + + final SciProject project = (SciProject) document; + if (itemPermissionChecker.canEditItem(project)) { + final String text = project + .getFunding() + .getValue(new Locale(localeParam)); + final Document jsoupDoc = Jsoup.parseBodyFragment(text); + final long result = new StringTokenizer( + jsoupDoc.body().text() + ).countTokens(); + return Long.toString(result); + } else { + throw new ForbiddenException(); + } + } + + @GET + @Path("/project-funding/{locale}") + @Produces(MediaType.TEXT_HTML) + @Transactional(Transactional.TxType.REQUIRED) + public String viewFundingValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPathParam, + @PathParam("locale") final String localeParam + ) { + final ContentSection contentSection = sectionsUi + .findContentSection(sectionIdentifier) + .orElseThrow( + () -> new NotFoundException() + ); + + final ContentItem document = itemRepo + .findByPath(contentSection, documentPathParam) + .orElseThrow( + () -> new NotFoundException() + ); + + if (!(document instanceof SciProject)) { + throw new NotFoundException(); + } + + final SciProject project = (SciProject) document; + if (itemPermissionChecker.canEditItem(project)) { + return project.getFunding().getValue( + new Locale(localeParam) + ); + } else { + throw new ForbiddenException(); + } + } + + @GET + @Path("/project-fundingvolume/wordcount/{locale}") + @Produces(MediaType.TEXT_HTML) + @Transactional(Transactional.TxType.REQUIRED) + public String getFundingVolumeWordCount( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPathParam, + @PathParam("locale") final String localeParam + ) { + final ContentSection contentSection = sectionsUi + .findContentSection(sectionIdentifier) + .orElseThrow( + () -> new NotFoundException() + ); + + final ContentItem document = itemRepo + .findByPath(contentSection, documentPathParam) + .orElseThrow( + () -> new NotFoundException() + ); + + if (!(document instanceof SciProject)) { + throw new NotFoundException(); + } + + final SciProject project = (SciProject) document; + if (itemPermissionChecker.canEditItem(project)) { + return project.getFundingVolume().getValue( + new Locale(localeParam) + ); + } else { + throw new ForbiddenException(); + } + } + + @GET + @Path("/project-fundingvolume/{locale}") + @Produces(MediaType.TEXT_HTML) + @Transactional(Transactional.TxType.REQUIRED) + public String viewFundingVolumeValue( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPathParam, + @PathParam("locale") final String localeParam + ) { + final ContentSection contentSection = sectionsUi + .findContentSection(sectionIdentifier) + .orElseThrow( + () -> new NotFoundException() + ); + + final ContentItem document = itemRepo + .findByPath(contentSection, documentPathParam) + .orElseThrow( + () -> new NotFoundException() + ); + + if (!(document instanceof SciProject)) { + throw new NotFoundException(); + } + + final SciProject project = (SciProject) document; + if (itemPermissionChecker.canEditItem(project)) { + return project.getFundingVolume().getValue( + new Locale(localeParam) + ); + } else { + throw new ForbiddenException(); + } + } + +} 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 new file mode 100644 index 0000000..1d6666c --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingTextModel.java @@ -0,0 +1,96 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Named; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("SciProjectFundingText") +public class SciProjectFundingTextModel { + + private boolean canEdit; + + private Map fundingValues; + + private List variants; + + private List unusedLocales; + + private String selectedLocale; + + public Map getFundingValues() { + return Optional + .ofNullable(fundingValues) + .map(Collections::unmodifiableMap) + .orElse(Collections.emptyMap()); + } + + protected void setFundingValues( + final Map fundingValues + ) { + this.fundingValues = Optional + .ofNullable(fundingValues) + .map(values -> new HashMap<>(values)) + .map(values -> (Map) values) + .orElse(Collections.emptyMap()); + } + + public List getVariants() { + return Optional + .ofNullable(variants) + .map(Collections::unmodifiableList) + .orElse(Collections.emptyList()); + } + + protected void setVariants(final List variants) { + this.variants = Optional + .ofNullable(variants) + .map(list -> new ArrayList<>(list)) + .map(list -> (List) list) + .orElse(Collections.emptyList()); + } + + public List getUnusedLocales() { + return Optional + .ofNullable(unusedLocales) + .map(Collections::unmodifiableList) + .orElse(Collections.emptyList()); + } + + protected void setUnusedLocales(final List unusedLocales) { + this.unusedLocales = Optional + .ofNullable(unusedLocales) + .map(list -> new ArrayList<>(list)) + .map(list -> (List) list) + .orElse(Collections.emptyList()); + } + + public String getSelectedLocale() { + return selectedLocale; + } + + protected void setSelectedLocale(final String selectedLocale) { + this.selectedLocale = selectedLocale; + } + + public boolean getCanEdit() { + return canEdit; + } + + protected void setCanEdit(final boolean canEdit) { + this.canEdit = canEdit; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingVolumeModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingVolumeModel.java new file mode 100644 index 0000000..25a317b --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectFundingVolumeModel.java @@ -0,0 +1,93 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Named; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("SciProjectFundingVolume") +public class SciProjectFundingVolumeModel { + private boolean canEdit; + + private Map fundingVolumeValues; + + private List variants; + + private List unusedLocales; + + private String selectedLocale; + + public Map getFundingVolumeValues() { + return Optional + .ofNullable(fundingVolumeValues) + .map(Collections::unmodifiableMap) + .orElse(Collections.emptyMap()); + } + + protected void setFundingVolumeValues( + final Map fundingVolumeValues + ) { + this.fundingVolumeValues = Optional + .ofNullable(fundingVolumeValues) + .map(values -> new HashMap<>(values)) + .map(values -> (Map) values) + .orElse(Collections.emptyMap()); + } + public List getVariants() { + return Optional + .ofNullable(variants) + .map(Collections::unmodifiableList) + .orElse(Collections.emptyList()); + } + + protected void setVariants(final List variants) { + this.variants = Optional + .ofNullable(variants) + .map(list -> new ArrayList<>(list)) + .map(list -> (List) list) + .orElse(Collections.emptyList()); + } + + public List getUnusedLocales() { + return Optional + .ofNullable(unusedLocales) + .map(Collections::unmodifiableList) + .orElse(Collections.emptyList()); + } + + protected void setUnusedLocales(final List unusedLocales) { + this.unusedLocales = Optional + .ofNullable(unusedLocales) + .map(list -> new ArrayList<>(list)) + .map(list -> (List) list) + .orElse(Collections.emptyList()); + } + + public String getSelectedLocale() { + return selectedLocale; + } + + protected void setSelectedLocale(final String selectedLocale) { + this.selectedLocale = selectedLocale; + } + + public boolean getCanEdit() { + return canEdit; + } + + protected void setCanEdit(final boolean canEdit) { + this.canEdit = canEdit; + } +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectMembershipModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectMembershipModel.java new file mode 100644 index 0000000..00a3032 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectMembershipModel.java @@ -0,0 +1,119 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.librecms.assets.PersonName; + +import org.scientificcms.contenttypes.sciproject.Membership; +import org.scientificcms.contenttypes.sciproject.SciProject; + +/** + * DTO providing the information about a {@link Membership} of a + * {@link SciProject} in an form that easy usable from a MVC template. + * + * @author Jens Pelzetter + */ +public class SciProjectMembershipModel { + + /** + * The ID of the {@link Membership}. + */ + private long membershipId; + + /** + * The role of the member. + * + * @see Membership#role + */ + private String role; + + /** + * The status of teh membership. + * + * @see Membership#status + */ + private String status; + + /** + * The given name of the member. + * + * @see PersonName#givenName + */ + private String givenName; + + /** + * The surname of the member. + * + * @see PersonName#surname + */ + private String surname; + + /** + * An optional prefix for the name of the member. + * + * @see PersonName#prefix + */ + private String prefix; + + /** + * An optional suffix for the name of the member. + * + * @see PersonName#suffix + */ + private String suffix; + + public long getMembershipId() { + return membershipId; + } + + public void setMembershipId(final long membershipId) { + this.membershipId = membershipId; + } + + public String getRole() { + return role; + } + + public void setRole(final String role) { + this.role = role; + } + + public String getStatus() { + return status; + } + + public void setStatus(final String status) { + this.status = status; + } + + public String getGivenName() { + return givenName; + } + + public void setGivenName(final String givenName) { + this.givenName = givenName; + } + + public String getSurname() { + return surname; + } + + public void setSurname(final String surname) { + this.surname = surname; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(final String prefix) { + this.prefix = prefix; + } + + public String getSuffix() { + return suffix; + } + + public void setSuffix(final String suffix) { + this.suffix = suffix; + } + +}