From ffcdb70f985cdf1e4cdcbbb15481b2c23f330a65 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Mon, 11 Apr 2022 20:48:56 +0200 Subject: [PATCH] Second part of MVC based UI for SciProject --- .gitignore | 1 + .../sciproject/ui/ProjectCreateStep.java | 188 ------ .../sciproject/ui/SciProjectCreateStep.java | 377 +++++++++++ .../SciProjectDescriptionStepResources.java | 123 ++++ .../ui/SciProjectMessageBundle.java | 21 + .../ui/SciProjectPropertiesStep.java | 587 ++++++++++++++++++ .../ui/SciProjectPropertiesStepModel.java | 104 ++++ 7 files changed, 1213 insertions(+), 188 deletions(-) delete mode 100644 sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/ProjectCreateStep.java create mode 100644 sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectCreateStep.java create mode 100644 sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepResources.java create mode 100644 sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectMessageBundle.java create mode 100644 sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStep.java create mode 100644 sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStepModel.java diff --git a/.gitignore b/.gitignore index 9e9d241..d420165 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ node_modules /sci-publications/nbproject/ /sci-publications/target/ /scicms-bundle-devel-wildfly/target/ +/sci-types-project/nbproject/ diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/ProjectCreateStep.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/ProjectCreateStep.java deleted file mode 100644 index 1139abb..0000000 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/ProjectCreateStep.java +++ /dev/null @@ -1,188 +0,0 @@ -* 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.libreccm.l10n.LocalizedString; -import org.libreccm.security.AuthorizationRequired; -import org.libreccm.workflow.Workflow; -import org.librecms.contentsection.ContentItemManager; -import org.librecms.contentsection.ContentItemRepository; -import org.librecms.ui.contentsections.documents.AbstractMvcDocumentCreateStep; - -import org.scientificcms.contenttypes.sciproject.SciProject; - -import javax.enterprise.context.RequestScoped; -import javax.inject.Inject; -import javax.inject.Named; -import javax.transaction.Transactional; - -/** - * Create step for a {@link SciProject} - * @author Jens Pelzetter - */ - @RequestScoped - @Named("SciProjectCreateStep") - public class ProjectCreateStep - extends AbstractMvcDocumentCreateStep { - - private static final String FORM_PARAM_NAME = "name"; - - private static final String FORM_PARAM_TITLE = "title"; - - private static final String FORM_PARAM_STARTDATE = "startDate"; - - private static final String FORM_PARAM_ENDDATE = "startDate"; - - private static final String FORM_PARAM_SUMMARY = "summary"; - - private static final String FORM_PARAM_INITIAL_LOCALE = "locale"; - - private static final String FORM_PARAM_SELECTED_WORKFLOW = "workflow"; - - /** - * Provides functions for working with content items. - */ - @Inject - private ContentItemManager itemManager; - - /** - * Used to save the event. - */ - @Inject - private ContentItemRepository itemRepo; - - /** - * Provides functions for working with {@link LocalizedString}s. - */ - @Inject - private GlobalizationHelper globalizationHelper; - - /** - * Name of the project. - */ - private String name; - - /** - * Title of the project. - */ - private String title; - - /** - * The start date of the project. - */ - private String startDate; - - /** - * The end date of the project - */ - private String endDate; - - /** - * The short description of the project. - */ - private String shortDescription; - - /** - * The initial locale of the project. - */ - private String initialLocale; - - /** - * The workflow to use for the new project. - */ - private String selectedWorkflow; - - @Override - public String getDocumentType() { - return SciProject.class.getName(); - } - - @Override - public String getDescription() { - return globalizationHelper - .getLocalizedTextsUtil(getBundle()) - .getText("createstep.description"); - } - - @Override - public String getBundle() { - return SciProjectStepsConstants.BUNDLE; - } - - public String getName() { - return name; - } - - public String getTitle() { - return getTitle(); - } - - public String getStartDate() { - return startDate; - } - - public String getEndDate() { - return endDate; - } - - public String getShortDescription() { - return shortDescription; - } - - public String getInitialLocale() { - return initialLocale; - } - - @Transactional(Transactional.TxType.REQUIRED) - public String getSelectedWorkflow() { - if (selectedWorkflow == null || selectedWorkflow.isEmpty()) { - return getContentSection() - .getContentTypes() - .stream() - .filter( - type -> type.getContentItemClass().equals( - Event.class.getName() - ) - ) - .findAny() - .map(type -> type.getDefaultWorkflow()) - .map( - workflow -> globalizationHelper.getValueFromLocalizedString( - workflow.getName() - ) - ) - .orElse(""); - } else { - return selectedWorkflow; - } - } - - @Override - public String showCreateStep() { - return "org/scientificcms/contenttypes/sciproject/ui/create-sciproject.xhtml"; - } - - @AuthorizationRequired - @Transactional(Transactional.TxType.REQUIRED) - @Override - public String createItem(final Map formParams) { - // ToDo - } - } - diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectCreateStep.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectCreateStep.java new file mode 100644 index 0000000..0e758cd --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectCreateStep.java @@ -0,0 +1,377 @@ +/* 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.libreccm.l10n.LocalizedString; +import org.libreccm.security.AuthorizationRequired; +import org.libreccm.workflow.Workflow; +import org.librecms.contentsection.ContentItemManager; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.ui.contentsections.documents.AbstractMvcDocumentCreateStep; + +import org.scientificcms.contenttypes.sciproject.SciProject; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.inject.Named; +import javax.transaction.Transactional; + +/** + * Create step for a {@link SciProject} + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("SciProjectCreateStep") +public class SciProjectCreateStep + extends AbstractMvcDocumentCreateStep { + + private static final String FORM_PARAM_NAME = "name"; + + private static final String FORM_PARAM_TITLE = "title"; + + private static final String FORM_PARAM_BEGIN = "begin"; + + private static final String FORM_PARAM_END = "end"; + + private static final String FORM_PARAM_SUMMARY = "summary"; + + private static final String FORM_PARAM_INITIAL_LOCALE = "locale"; + + private static final String FORM_PARAM_SELECTED_WORKFLOW = "workflow"; + + /** + * Provides functions for working with content items. + */ + @Inject + private ContentItemManager itemManager; + + /** + * Used to save the event. + */ + @Inject + private ContentItemRepository itemRepo; + + /** + * Provides functions for working with {@link LocalizedString}s. + */ + @Inject + private GlobalizationHelper globalizationHelper; + + /** + * Name of the project. + */ + private String name; + + /** + * Title of the project. + */ + private String title; + + /** + * The start date of the project. + */ + private String beginParam; + + /** + * The end date of the project + */ + private String endParam; + + /** + * The short description of the project. + */ + private String shortDescription; + + /** + * The initial locale of the project. + */ + private String initialLocale; + + /** + * The workflow to use for the new project. + */ + private String selectedWorkflow; + + @Override + public String getDocumentType() { + return SciProject.class.getName(); + } + + @Override + public String getDescription() { + return globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.description"); + } + + @Override + public String getBundle() { + return SciProjectStepsConstants.BUNDLE; + } + + public String getName() { + return name; + } + + public String getTitle() { + return title; + } + + public String getBeginParam() { + return beginParam; + } + + public String getEndParam() { + return endParam; + } + + public String getShortDescription() { + return shortDescription; + } + + public String getInitialLocale() { + return initialLocale; + } + + @Transactional(Transactional.TxType.REQUIRED) + public String getSelectedWorkflow() { + if (selectedWorkflow == null || selectedWorkflow.isEmpty()) { + return getContentSection() + .getContentTypes() + .stream() + .filter( + type -> type.getContentItemClass().equals( + SciProject.class.getName() + ) + ) + .findAny() + .map(type -> type.getDefaultWorkflow()) + .map( + workflow -> globalizationHelper.getValueFromLocalizedString( + workflow.getName() + ) + ) + .orElse(""); + } else { + return selectedWorkflow; + } + } + + @Override + public String showCreateStep() { + return "org/scientificcms/contenttypes/sciproject/ui/create-sciproject.xhtml"; + } + + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + @Override + public String createItem(final Map formParams) { + if (!formParams.containsKey(FORM_PARAM_NAME) + || formParams.get(FORM_PARAM_NAME) == null + || formParams.get(FORM_PARAM_NAME).length == 0) { + addMessage( + "danger", + globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.name.error.missing") + ); + return showCreateStep(); + } + + name = formParams.get(FORM_PARAM_NAME)[0]; + if (!name.matches("^([a-zA-Z0-9_-]*)$")) { + addMessage( + "danger", + globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.name.error.invalid") + ); + return showCreateStep(); + } + + if (!formParams.containsKey(FORM_PARAM_TITLE) + || formParams.get(FORM_PARAM_TITLE) == null + || formParams.get(FORM_PARAM_TITLE).length == 0) { + addMessage( + "danger", + globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.title.error.missing") + ); + return showCreateStep(); + } + title = formParams.get(FORM_PARAM_TITLE)[0]; + + if (!formParams.containsKey(FORM_PARAM_BEGIN) + || formParams.get(FORM_PARAM_BEGIN) == null + || formParams.get(FORM_PARAM_BEGIN).length == 0) { + addMessage( + "danger", + globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.startdate.error.missing") + ); + return showCreateStep(); + } + beginParam = formParams.get(FORM_PARAM_BEGIN)[0]; + final DateTimeFormatter isoDateFormatter = DateTimeFormatter.ISO_DATE + .withZone(ZoneId.systemDefault()); + + final LocalDate begin; + try { + begin = LocalDate.parse( + beginParam, + isoDateFormatter + ); + } catch (DateTimeParseException ex) { + addMessage( + "danger", + globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.begindate.error.malformed") + ); + return showCreateStep(); + } + + final LocalDate end = readEndDate(formParams); + + if (!formParams.containsKey(FORM_PARAM_SUMMARY) + || formParams.get(FORM_PARAM_SUMMARY) == null + || formParams.get(FORM_PARAM_SUMMARY).length == 0) { + addMessage( + "danger", + globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.summary.error.missing") + ); + return showCreateStep(); + } + shortDescription = formParams.get(FORM_PARAM_SUMMARY)[0]; + + if (!formParams.containsKey(FORM_PARAM_INITIAL_LOCALE) + || formParams.get(FORM_PARAM_INITIAL_LOCALE) == null + || formParams.get(FORM_PARAM_INITIAL_LOCALE).length == 0) { + addMessage( + "danger", + globalizationHelper.getLocalizedTextsUtil( + getBundle() + ).getText("createstep.initial_locale.error.missing") + ); + return showCreateStep(); + } + final Locale locale = new Locale( + formParams.get(FORM_PARAM_INITIAL_LOCALE)[0] + ); + + if (!formParams.containsKey(FORM_PARAM_SELECTED_WORKFLOW) + || formParams.get(FORM_PARAM_SELECTED_WORKFLOW) == null + || formParams.get(FORM_PARAM_SELECTED_WORKFLOW).length == 0) { + addMessage( + "danger", + globalizationHelper.getLocalizedTextsUtil( + getBundle() + ).getText("createstep.workflow.none_selected") + ); + return showCreateStep(); + } + + selectedWorkflow = formParams.get(FORM_PARAM_SELECTED_WORKFLOW)[0]; + + final Optional workflowResult = getContentSection() + .getWorkflowTemplates() + .stream() + .filter(template -> template.getUuid().equals(selectedWorkflow)) + .findAny(); + + if (!workflowResult.isPresent()) { + addMessage( + "danger", + globalizationHelper.getLocalizedTextsUtil( + getBundle() + ).getText("createstep.workflow.error.not_available") + ); + return showCreateStep(); + } + + if (!getMessages().isEmpty()) { + return showCreateStep(); + } + + final SciProject project = itemManager.createContentItem( + name, + getContentSection(), + getFolder(), + workflowResult.get(), + SciProject.class, + locale + ); + + project.getTitle().putValue(locale, title); + project.setBegin(begin); + if (end != null) { + project.setEnd(end); + } + project.getShortDescription().putValue(locale, shortDescription); + itemRepo.save(project); + + return String.format( + "redirect:/%s/documents/%s/%s/@sciproject-basicproperties", + getContentSectionLabel(), + getFolderPath(), + name + ); + } + + private LocalDate readEndDate(final Map formParams) { + if (formParams.containsKey(FORM_PARAM_END) + && formParams.get(FORM_PARAM_END) != null + && formParams.get(FORM_PARAM_END).length > 0) { + endParam = formParams.get(FORM_PARAM_END)[0]; + if (endParam != null) { + try { + return LocalDate.parse( + endParam, + DateTimeFormatter.ISO_DATE + ); + } catch (DateTimeParseException ex) { + addMessage( + "danger", + globalizationHelper + .getLocalizedTextsUtil(getBundle()) + .getText("createstep.enddate.error.malformed") + ); + return null; + } + } else { + return null; + } + } else { + return null; + } + } +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepResources.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepResources.java new file mode 100644 index 0000000..1bda97c --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectDescriptionStepResources.java @@ -0,0 +1,123 @@ +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-description-resources") +public class SciProjectDescriptionStepResources { + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private ContentSectionsUi sectionsUi; + + @Inject + private ItemPermissionChecker itemPermissionChecker; + + @GET + @Path("/project-description/wordcount/{locale}") + @Produces(MediaType.TEXT_HTML) + @Transactional(Transactional.TxType.REQUIRED) + public String getProjectDescriptionWordCount( + @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)) { + final String text = project + .getProjectDescription() + .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-description/{locale}") + @Produces(MediaType.TEXT_HTML) + @Transactional(Transactional.TxType.REQUIRED) + public String viewProjectDescriptionValue( + @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.getProjectDescription().getValue( + new Locale(localeParam) + ); + } else { + throw new ForbiddenException(); + } + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectMessageBundle.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectMessageBundle.java new file mode 100644 index 0000000..c48ec92 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectMessageBundle.java @@ -0,0 +1,21 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.libreccm.ui.AbstractMessagesBean; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Named; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("SciProjectMessageBundle") +public class SciProjectMessageBundle extends AbstractMessagesBean { + + @Override + protected String getMessageBundle() { + return SciProjectStepsConstants.BUNDLE; + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStep.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStep.java new file mode 100644 index 0000000..847ec9a --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStep.java @@ -0,0 +1,587 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.l10n.LocalizedString; +import org.libreccm.security.AuthorizationRequired; +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.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 java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +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.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 + "sciproject-basicproperties") +@Controller +@MvcAuthoringStepDef( + bundle = SciProjectStepsConstants.BUNDLE, + descriptionKey = "authoringsteps.basicproperties.description", + labelKey = "authoringsteps.basicproperties.label", + supportedDocumentType = SciProject.class +) +public class SciProjectPropertiesStep extends AbstractMvcAuthoringStep { + + @Inject + private SciProjectMessageBundle sciProjectMessageBundle; + + /** + * Used for retrieving and saving the projects. + */ + @Inject + private ContentItemRepository itemRepo; + + + + @Inject + private DocumentUi documentUi; + + + + /** + * Provides functions for working with {@link LocalizedString}s. + */ + @Inject + private GlobalizationHelper globalizationHelper; + + @Inject + private ItemPermissionChecker itemPermissionChecker; + + @Inject + private SciProjectPropertiesStepModel sciProjectPropertiesStepModel; + + @Inject + private Models models; + + @Override + public Class getStepClass() { + return SciProjectPropertiesStep.class; + } + + @Override + @Transactional(Transactional.TxType.REQUIRED) + protected void init() throws ContentSectionNotFoundException, + DocumentNotFoundException { + super.init(); + + sciProjectPropertiesStepModel.setName(getDocument().getDisplayName()); + + final Set titleLocales = getDocument() + .getTitle() + .getAvailableLocales(); + + sciProjectPropertiesStepModel.setTitleValues( + getDocument() + .getTitle() + .getValues() + .entrySet() + .stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toString(), + entry -> entry.getValue() + ) + ) + ); + + sciProjectPropertiesStepModel.setUnusedTitleLocales( + globalizationHelper + .getAvailableLocales() + .stream() + .filter(locale -> !titleLocales.contains(locale)) + .map(Locale::toString) + .collect(Collectors.toList()) + ); + + final SciProject project = (SciProject) getDocument(); + + sciProjectPropertiesStepModel.setShortDescriptionValues( + project + .getShortDescription() + .getValues() + .entrySet() + .stream() + .collect( + Collectors.toMap( + entry -> entry.getKey().toString(), + entry -> entry.getValue() + ) + ) + ); + final Set shortDescriptionLocales = project + .getShortDescription() + .getAvailableLocales(); + + sciProjectPropertiesStepModel.setUnusedShortDescriptionLocales( + globalizationHelper + .getAvailableLocales() + .stream() + .filter(locale -> !shortDescriptionLocales.contains(locale)) + .map(Locale::toString) + .collect(Collectors.toList()) + ); + + final DateTimeFormatter isoDateFormatter = DateTimeFormatter.ISO_DATE + .withZone(ZoneId.systemDefault()); + + sciProjectPropertiesStepModel.setBegin( + Optional + .ofNullable(project.getBegin()) + .map(isoDateFormatter::format) + .orElse("") + ); + + sciProjectPropertiesStepModel.setEndDate( + Optional + .ofNullable(project.getEnd()) + .map(isoDateFormatter::format) + .orElse("") + ); + } + + @GET + @Path("/") + @AuthorizationRequired + @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(getDocument())) { + return "org/scientificcms/contenttypes/sciproject/ui/sciproject-basic-properties.xhtml"; + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + sciProjectMessageBundle.getMessage("project.edit.denied") + ); + } + } + + /** + * Updates the name of the current project. + * + * @param sectionIdentifier + * @param documentPath + * @param name + * + * @return A redirect to this authoring step. + */ + @POST + @Path("/name") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + 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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + if (name.isBlank()) { + models.put("nameMissing", true); + + return showStep(sectionIdentifier, documentPath); + } + + getDocument().setDisplayName(name); + itemRepo.save(getDocument()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + @POST + @Path("/begin") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String updateBegin( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("begin") + final String begin + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final SciProject project = (SciProject) getDocument(); + final DateTimeFormatter isoDateFormatter + = DateTimeFormatter.ISO_DATE + .withZone(ZoneId.systemDefault()); + project.setBegin(LocalDate.parse(begin, isoDateFormatter)); + + itemRepo.save(project); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + @POST + @Path("/end") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String updateEnd( + @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) + final String sectionIdentifier, + @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) + final String documentPath, + @FormParam("end") + final String end + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final SciProject project = (SciProject) getDocument(); + final DateTimeFormatter isoDateFormatter + = DateTimeFormatter.ISO_DATE + .withZone(ZoneId.systemDefault()); + project.setEnd(LocalDate.parse(end, isoDateFormatter)); + + itemRepo.save(project); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + /** + * Updates a localized title of the project. + * + * @param sectionIdentifier + * @param documentPath + * @param localeParam The locale to update. + * @param value The updated title value. + * + * @return A redirect to this authoring step. + */ + @POST + @Path("/title/@add") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + 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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final Locale locale = new Locale(localeParam); + getDocument().getTitle().putValue(locale, value); + itemRepo.save(getDocument()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + /** + * Updates a localized title of the project. + * + * @param sectionIdentifier + * @param documentPath + * @param localeParam The locale to update. + * @param value The updated title value. + * + * @return A redirect to this authoring step. + */ + @POST + @Path("/title/@edit/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + 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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final Locale locale = new Locale(localeParam); + getDocument().getTitle().putValue(locale, value); + itemRepo.save(getDocument()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + /** + * Removes a localized title of the project. + * + * @param sectionIdentifier + * @param documentPath + * @param localeParam The locale to remove. + * + * @return A redirect to this authoring step. + */ + @POST + @Path("/title/@remove/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + 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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final Locale locale = new Locale(localeParam); + getDocument().getTitle().removeValue(locale); + itemRepo.save(getDocument()); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + /** + * Adds a localized short description to the project. + * + * @param sectionIdentifier + * @param documentPath + * @param localeParam The locale of the description. + * @param value The description value. + * + * @return A redirect to this authoring step. + */ + @POST + @Path("/short-description/@add") + @Transactional(Transactional.TxType.REQUIRED) + 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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final Locale locale = new Locale(localeParam); + final SciProject project = (SciProject) getDocument(); + project.getShortDescription().putValue(locale, value); + + itemRepo.save(project); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + /** + * Updates a localized short description to the project. + * + * @param sectionIdentifier + * @param documentPath + * @param localeParam The locale to update. + * @param value The description value. + * + * @return A redirect to this authoring step. + */ + @POST + @Path("/short-description/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + 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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final Locale locale = new Locale(localeParam); + final SciProject project = (SciProject) getDocument(); + project.getShortDescription().putValue(locale, value); + + itemRepo.save(project); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + + /** + * Removes a localized short description from the project. + * + * @param sectionIdentifier + * @param documentPath + * @param localeParam The locale to remove. + * + * @return A redirect to this authoring step. + */ + 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 + ) { + try { + init(); + } catch (ContentSectionNotFoundException ex) { + return ex.showErrorMessage(); + } catch (DocumentNotFoundException ex) { + return ex.showErrorMessage(); + } + + if (itemPermissionChecker.canEditItem(getDocument())) { + final Locale locale = new Locale(localeParam); + final SciProject project = (SciProject) getDocument(); + project.getShortDescription().removeValue(locale); + itemRepo.save(project); + + return buildRedirectPathForStep(); + } else { + return documentUi.showAccessDenied( + getContentSection(), + getDocument(), + getLabel() + ); + } + } + +} diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStepModel.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStepModel.java new file mode 100644 index 0000000..b438e74 --- /dev/null +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/ui/SciProjectPropertiesStepModel.java @@ -0,0 +1,104 @@ +package org.scientificcms.contenttypes.sciproject.ui; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Named; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Named("SciProjectPropertiesStep") +public class SciProjectPropertiesStepModel { + + private String name; + + private Map titleValues; + + private List unusedTitleLocales; + + private Map shortDescriptionValues; + + private List unusedShortDescriptionLocales; + + private String begin; + + private String endDate; + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public Map getTitleValues() { + return Collections.unmodifiableMap(titleValues); + } + + public void setTitleValues(final Map titleValues) { + this.titleValues = new HashMap<>(titleValues); + } + + public List getUnusedTitleLocales() { + return Collections.unmodifiableList(unusedTitleLocales); + } + + public void setUnusedTitleLocales(final List unusedTitleLocales) { + this.unusedTitleLocales = new ArrayList<>(unusedTitleLocales); + } + + public Map getShortDescriptionValues() { + return Collections.unmodifiableMap(shortDescriptionValues); + } + + public void setShortDescriptionValues( + final Map shortDescriptionValues + ) { + this.shortDescriptionValues = new HashMap<>(shortDescriptionValues); + } + + public List getUnusedShortDescriptionLocales() { + return Collections.unmodifiableList(unusedShortDescriptionLocales); + } + + public void setUnusedShortDescriptionLocales( + final List unusedShortDescriptionLocales + ) { + this.unusedShortDescriptionLocales = new ArrayList<>( + unusedShortDescriptionLocales + ); + } + + public String getBegin() { + return begin; + } + + public void setBegin(final String begin) { + this.begin = begin; + } + + public boolean getHasStartDate() { + return !begin.isBlank(); + } + + public String getEndDate() { + return endDate; + } + + public void setEndDate(final String endDate) { + this.endDate = endDate; + } + + public boolean getHasEndDate() { + return !endDate.isBlank(); + } + +}