diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java
index 9fc5aea8f..a226b7e31 100644
--- a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java
+++ b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java
@@ -26,6 +26,10 @@ import org.hibernate.envers.Audited;
import org.libreccm.l10n.LocalizedString;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
+import org.librecms.ui.contentsections.documents.MvcAuthoringKit;
+import org.librecms.ui.contenttypes.mpa.MvcMpaCreateStep;
+import org.librecms.ui.contenttypes.mpa.MvcMpaPropertiesStep;
+import org.librecms.ui.contenttypes.mpa.MvcMpaSectionsStep;
import java.io.Serializable;
import java.util.ArrayList;
@@ -77,6 +81,13 @@ import static org.librecms.CmsConstants.*;
)
}
)
+@MvcAuthoringKit(
+ createStep = MvcMpaCreateStep.class,
+ authoringSteps = {
+ MvcMpaPropertiesStep.class,
+ MvcMpaSectionsStep.class
+ }
+)
public class MultiPartArticle extends ContentItem implements Serializable {
private static final long serialVersionUID = -587374085831420868L;
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleMessageBundle.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleMessageBundle.java
index 188f4b747..d8e6fee3a 100644
--- a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleMessageBundle.java
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleMessageBundle.java
@@ -25,7 +25,7 @@ import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
/**
- * Message bundle fo the authoring steps for editing an {@link Article}.
+ * Message bundle for the authoring steps for editing an {@link Article}.
*
* @author Jens Pelzetter
*/
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleStepsConstants.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleStepsConstants.java
index abe8367b6..7a9d90c17 100644
--- a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleStepsConstants.java
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/ArticleStepsConstants.java
@@ -26,7 +26,7 @@ package org.librecms.ui.contenttypes.article;
public final class ArticleStepsConstants {
private ArticleStepsConstants() {
-
+ // Nothing
}
public static final String BUNDLE
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleCreateStep.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleCreateStep.java
index d11e8d4c4..c7659f0b3 100644
--- a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleCreateStep.java
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleCreateStep.java
@@ -77,12 +77,6 @@ public class MvcArticleCreateStep
@Inject
private GlobalizationHelper globalizationHelper;
- /**
- * Used to provided data for the views without a named bean.
- */
- @Inject
- private Models models;
-
/**
* Name of the article.
*/
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticlePropertiesStep.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticlePropertiesStep.java
index 329a5d469..6afe011e8 100644
--- a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticlePropertiesStep.java
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticlePropertiesStep.java
@@ -41,7 +41,6 @@ import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
-import javax.inject.Named;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.transaction.Transactional;
@@ -52,7 +51,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.PathParam;
/**
- * Authoring step for editing the basic properties of an a {@link Article}.
+ * Authoring step for editing the basic properties of an {@link Article}.
*
* @author Jens Pelzetter
*/
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleTextBodyStep.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleTextBodyStep.java
index fac3b101f..4a6ad528e 100644
--- a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleTextBodyStep.java
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/article/MvcArticleTextBodyStep.java
@@ -192,11 +192,6 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
return ex.showErrorMessage();
}
- final KernelConfig kernelConfig = confManager.findConfiguration(
- KernelConfig.class
- );
- final Locale defaultLocale = kernelConfig.getDefaultLocale();
-
if (itemPermissionChecker.canEditItem(getArticle())) {
final String value;
if (getArticle().getText().getAvailableLocales().isEmpty()) {
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaMessageBundle.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaMessageBundle.java
new file mode 100644
index 000000000..a15d51ab5
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaMessageBundle.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+import org.libreccm.ui.AbstractMessagesBean;
+import org.librecms.contenttypes.MultiPartArticle;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ * Message bundle for the authoring steps for editing a
+ * {@link MultiPartArticle}.
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("CmsMpaMessageBundle")
+public class MpaMessageBundle extends AbstractMessagesBean {
+
+ @Override
+ protected String getMessageBundle() {
+ return MpaStepsConstants.BUNDLE;
+ }
+
+}
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaPropertiesStepModel.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaPropertiesStepModel.java
new file mode 100644
index 000000000..1de1f44a3
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaPropertiesStepModel.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+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("CmsMpaPropertiesStep")
+public class MpaPropertiesStepModel {
+
+ private String name;
+
+ private Map titleValues;
+
+ private List unusedTitleLocales;
+
+ private Map descriptionValues;
+
+ private List unusedDescriptionLocales;
+
+ 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(List unusedTitleLocales) {
+ this.unusedTitleLocales = new ArrayList<>(unusedTitleLocales);
+ }
+
+ public Map getDescriptionValues() {
+ return Collections.unmodifiableMap(descriptionValues);
+ }
+
+ public void setDescriptionValues(
+ final Map descriptionValues
+ ) {
+ this.descriptionValues = new HashMap<>(descriptionValues);
+ }
+
+ public List getUnusedDescriptionLocales() {
+ return Collections.unmodifiableList(unusedDescriptionLocales);
+ }
+
+ public void setUnusedDescriptionLocales(
+ final List unusedDescriptionLocales
+ ) {
+ this.unusedDescriptionLocales = new ArrayList<>(
+ unusedDescriptionLocales
+ );
+ }
+
+}
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaSectionStepService.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaSectionStepService.java
new file mode 100644
index 000000000..8c8697612
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaSectionStepService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
+
+import java.util.List;
+
+import javax.enterprise.context.RequestScoped;
+import javax.transaction.Transactional;
+import javax.ws.rs.Consumes;
+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 + "mpa-sections-service")
+public class MpaSectionStepService {
+
+ @POST
+ @Path("/save-order")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Response saveOrder(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ final List sectionsOrder
+ ) {
+ // ToDo
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaSectionsStepModel.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaSectionsStepModel.java
new file mode 100644
index 000000000..ed0bb9ebf
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaSectionsStepModel.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("CmsMpaSectionsStep")
+public class MpaSectionsStepModel {
+
+ private boolean canEdit;
+
+ public boolean getCanEdit() {
+ return canEdit;
+ }
+
+ protected void setCanEdit(final boolean canEdit) {
+ this.canEdit = canEdit;
+ }
+
+}
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaStepsConstants.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaStepsConstants.java
new file mode 100644
index 000000000..ddcf6acee
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MpaStepsConstants.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+import org.librecms.contenttypes.MultiPartArticle;
+
+/**
+ * Constants for the authoring steps for editing a {@link MultiPartArticle}.
+ *
+ * @author Jens Pelzetter
+ */
+public final class MpaStepsConstants {
+
+ private MpaStepsConstants() {
+ // Nothing
+ }
+
+ public static final String BUNDLE
+ = "org.librecms.ui.contenttypes.MpaBundle";
+
+}
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaCreateStep.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaCreateStep.java
new file mode 100644
index 000000000..6dbcdb495
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaCreateStep.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+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.contenttypes.Article;
+import org.librecms.contenttypes.MultiPartArticle;
+import org.librecms.ui.contentsections.documents.AbstractMvcDocumentCreateStep;
+
+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.mvc.Models;
+import javax.transaction.Transactional;
+
+/**
+ * Describes the create step for an {@link MultiPartArticle}.
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Named("CmsMpaCreateStep")
+public class MvcMpaCreateStep
+ extends AbstractMvcDocumentCreateStep {
+
+ private static final String FORM_PARAM_NAME = "name";
+
+ private static final String FORM_PARAM_TITLE = "title";
+
+ 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 article.
+ */
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ /**
+ * Provides functions for working with {@link LocalizedString}s.
+ */
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ /**
+ * Name of the article.
+ */
+ private String name;
+
+ /**
+ * Title of the article.
+ */
+ private String title;
+
+ /**
+ * Summary of the article.
+ */
+ private String summary;
+
+ /**
+ * The initial locale of the article.
+ */
+ private String initialLocale;
+
+ /**
+ * The workflow to use for the new article.
+ */
+ private String selectedWorkflow;
+
+ @Override
+ public String getDocumentType() {
+ return MultiPartArticle.class.getName();
+ }
+
+ @Override
+ public String getDescription() {
+ return globalizationHelper
+ .getLocalizedTextsUtil(getBundle())
+ .getText("createstep.description");
+ }
+
+ @Override
+ public String getBundle() {
+ return MpaStepsConstants.BUNDLE;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getSummary() {
+ return summary;
+ }
+
+ 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(
+ Article.class.getName()
+ )
+ )
+ .findAny()
+ .map(type -> type.getDefaultWorkflow())
+ .map(
+ workflow -> globalizationHelper.getValueFromLocalizedString(
+ workflow.getName()
+ )
+ )
+ .orElse("");
+ } else {
+ return selectedWorkflow;
+ }
+ }
+
+ @Override
+ public String showCreateStep() {
+ return "org/librecms/ui/contenttypes/mpa/create-mpa.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_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();
+ }
+ summary = 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 Article article = itemManager.createContentItem(
+ name,
+ getContentSection(),
+ getFolder(),
+ workflowResult.get(),
+ Article.class,
+ locale
+ );
+
+ article.getTitle().addValue(locale, title);
+ article.getDescription().addValue(locale, summary);
+ itemRepo.save(article);
+
+ return String.format(
+ "redirect:/%s/documents/%s/%s/@article-basicproperties",
+ getContentSectionLabel(),
+ getFolderPath(),
+ name
+ );
+ }
+
+}
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaPropertiesStep.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaPropertiesStep.java
new file mode 100644
index 000000000..970a000f4
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaPropertiesStep.java
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+import org.libreccm.l10n.GlobalizationHelper;
+import org.libreccm.l10n.LocalizedString;
+import org.libreccm.security.AuthorizationRequired;
+import org.librecms.contentsection.ContentItemManager;
+import org.librecms.contentsection.ContentItemRepository;
+import org.librecms.contentsection.FolderManager;
+import org.librecms.contenttypes.MultiPartArticle;
+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 java.util.Locale;
+import java.util.Map;
+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;
+
+/**
+ * Authoring Step for editing the basic properties of a
+ * {@link MultiPartArticle}.
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path(MvcAuthoringSteps.PATH_PREFIX + "mpa-basicproperties")
+@Controller
+@MvcAuthoringStepDef(
+ bundle = MpaStepsConstants.BUNDLE,
+ descriptionKey = "authoringsteps.basicproperties.description",
+ labelKey = "authoringsteps.basicproperties.label",
+ supportedDocumentType = MultiPartArticle.class
+)
+public class MvcMpaPropertiesStep extends AbstractMvcAuthoringStep {
+
+ @Inject
+ private MpaMessageBundle mpaMessageBundle;
+
+ /**
+ * Used for retrieving and saving the article.
+ */
+ @Inject
+ private ContentItemRepository itemRepo;
+
+ /**
+ * Provides functions for working with content items.
+ */
+ @Inject
+ private ContentItemManager itemManager;
+
+ @Inject
+ private DocumentUi documentUi;
+
+ /**
+ * Provides functions for working with folders.
+ */
+ @Inject
+ private FolderManager folderManager;
+
+ /**
+ * Provides functions for working with {@link LocalizedString}s.
+ */
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ @Inject
+ private ItemPermissionChecker itemPermissionChecker;
+
+ @Inject
+ private MpaPropertiesStepModel mpaPropertiesStepModel;
+
+ @Inject
+ private Models models;
+
+ @Override
+ public Class getStepClass() {
+ return MvcMpaPropertiesStep.class;
+ }
+
+ @Override
+ @Transactional(Transactional.TxType.REQUIRED)
+ protected void init() throws ContentSectionNotFoundException,
+ DocumentNotFoundException {
+ super.init();
+
+ mpaPropertiesStepModel.setName(getDocument().getDisplayName());
+
+ final Set titleLocales = getDocument()
+ .getTitle()
+ .getAvailableLocales();
+
+ mpaPropertiesStepModel.setTitleValues(
+ getDocument()
+ .getTitle()
+ .getValues()
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ entry -> entry.getKey().toString(),
+ Map.Entry::getValue
+ )
+ )
+ );
+
+ mpaPropertiesStepModel.setUnusedTitleLocales(
+ globalizationHelper
+ .getAvailableLocales()
+ .stream()
+ .filter(locale -> !titleLocales.contains(locale))
+ .map(Locale::toString)
+ .collect(Collectors.toList())
+ );
+
+ mpaPropertiesStepModel.setDescriptionValues(
+ getDocument()
+ .getDescription()
+ .getValues()
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ entry -> entry.getKey().toString(),
+ Map.Entry::getValue
+ )
+ )
+ );
+
+ final Set descriptionLocales = getDocument()
+ .getDescription()
+ .getAvailableLocales();
+
+ mpaPropertiesStepModel.setUnusedDescriptionLocales(
+ globalizationHelper
+ .getAvailableLocales()
+ .stream()
+ .filter(locale -> !descriptionLocales.contains(locale))
+ .map(Locale::toString)
+ .collect(Collectors.toList())
+ );
+ }
+
+ @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/librecms/ui/contenttypes/mpa/mpa-basicproperties.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ mpaMessageBundle.getMessage("mpa.edit.denied")
+ );
+ }
+ }
+
+ /**
+ * Updates the name of the current multipart article.
+ *
+ * @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());
+
+ updateDocumentPath();
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Updates a localized title of the multipart article.
+ *
+ * @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().addValue(locale, value);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+
+ }
+
+ /**
+ * Updates a localized title of the multipart article.
+ *
+ * @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().addValue(locale, value);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Removes a localized title of the multipart article.
+ *
+ * @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 description to the multipart article.
+ *
+ * @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("/description/@add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String addDescription(
+ @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().getDescription().addValue(locale, value);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Updates a localized description of the multipart article.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale to update.
+ * @param value The updated description value.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/description/@edit/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String editDescription(
+ @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().getDescription().addValue(locale, value);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+ /**
+ * Removes a localized description of the multipart article.
+ *
+ * @param sectionIdentifier
+ * @param documentPath
+ * @param localeParam The locale to remove.
+ *
+ * @return A redirect to this authoring step.
+ */
+ @POST
+ @Path("/description/@remove/{locale}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String removeDescription(
+ @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().getDescription().removeValue(locale);
+ itemRepo.save(getDocument());
+
+ return buildRedirectPathForStep();
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getDocument(),
+ getLabel()
+ );
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaSectionsStep.java b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaSectionsStep.java
new file mode 100644
index 000000000..aa5be86b6
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/ui/contenttypes/mpa/MvcMpaSectionsStep.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2021 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.librecms.ui.contenttypes.mpa;
+
+import org.librecms.contenttypes.MultiPartArticle;
+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 javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.mvc.Controller;
+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;
+
+/**
+ * Authoring step for managing the sections of a {@link MultiPartArticle}.
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path(MvcAuthoringSteps.PATH_PREFIX + "mpa-sections")
+@Controller
+@MvcAuthoringStepDef(
+ bundle = MpaStepsConstants.BUNDLE,
+ descriptionKey = "authoringsteps.sections.description",
+ labelKey = "authoringsteps.sections.description",
+ supportedDocumentType = MultiPartArticle.class
+)
+public class MvcMpaSectionsStep extends AbstractMvcAuthoringStep {
+
+ @Inject
+ private MpaMessageBundle mpaMessageBundle;
+
+ @Inject
+ private DocumentUi documentUi;
+
+ @Inject
+ private ItemPermissionChecker itemPermissionChecker;
+
+ @Inject
+ private MpaSectionsStepModel mpaSectionsStepModel;
+
+ @Override
+ public Class getStepClass() {
+ return MvcMpaSectionsStep.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(getMpa())) {
+ return "org/librecms/ui/contenttypes/mpa/mpa-sections.xhtml";
+ } else {
+ return documentUi.showAccessDenied(
+ getContentSection(),
+ getMpa(),
+ mpaMessageBundle.getMessage("mpa.edit.denied")
+ );
+ }
+ }
+
+ @POST
+ @Path("/add")
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String addSection(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @FormParam("initialLocal")
+ final String initialLocaleParam,
+ @FormParam("title")
+ final String title,
+ @FormParam("text")
+ final String text
+ ) {
+ // ToDo
+ throw new UnsupportedOperationException();
+ }
+
+ @POST
+ @Path("/remove/{sectionId}")
+ @Transactional(Transactional.TxType.REQUIRED)
+ public String removeSection(
+ @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
+ final String sectionIdentifier,
+ @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
+ final String documentPath,
+ @PathParam("sectionId")
+ final String sectionIdParam
+ ) {
+ // ToDo
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void init() throws ContentSectionNotFoundException,
+ DocumentNotFoundException {
+ super.init();
+
+ if (itemPermissionChecker.canEditItem(getMpa())) {
+ mpaSectionsStepModel.setCanEdit(
+ itemPermissionChecker.canEditItem(getMpa())
+ );
+ // ToDo Set sections in model
+ }
+ }
+
+ private MultiPartArticle getMpa() {
+ return (MultiPartArticle) getDocument();
+ }
+
+}
diff --git a/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/ArticleBundle_de.properties b/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/ArticleBundle_de.properties
index 40ff8fac4..4f1aa4485 100644
--- a/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/ArticleBundle_de.properties
+++ b/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/ArticleBundle_de.properties
@@ -10,7 +10,7 @@ createstep.name.error.invalid=Der Name des neuen Artikels ist nicht zul\u00e4ssi
createstep.title.error.missing=Der Titel des neuen Artikels fehlt.
createstep.initial_locale.error.missing=Es wurde keine initiale Sprache angegeben.
createstep.workflow.error.not_available=Der ausgew\u00e4hlte Arbeitsablauf ist nicht verf\u00fcgbar.
-article.edit.denied=Ihnen wurden nicht die erforderlichen Berechtigungen zugeteilt, um diesen Artikel zu bearbeiten.
+article.edit.denied=Ihnen wurden nicht die erforderlichen Berechtigungen erteilt, um diesen Artikel zu bearbeiten.
createform.name.help=Der Name des Artikels. Darf nur die Buchstaben A bis Z und a bis z, Zahlen, den Bindestrich und den Unterstrich enthalten.
createform.name.label=Name
createform.initial_locale.help=Die initiale Sprache des Artikels. Lokaliserbare Eigenschaften, die in diesem Formualar angegeben werden, werden f\u00fcr diese Sprache dem Artikel hinzugef\u00fcgt.
diff --git a/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/MpaStepsBundle.properties b/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/MpaStepsBundle.properties
new file mode 100644
index 000000000..bf65e5a08
--- /dev/null
+++ b/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/MpaStepsBundle.properties
@@ -0,0 +1,14 @@
+
+createstep.label=Multipart Article
+createstep.description=Creates a multipart article with a summary a main text split into multipe sections.
+authoringsteps.basicproperties.label=Basic Properties
+authoringsteps.basicproperties.description=Edit the basic properties
+createstep.name.error.missing=Name is missing.
+createstep.name.error.invalid=The name of the article is invalid.
+createstep.title.error.missing=The title of the new article is missing.
+createstep.summary.error.missing=No summary for the new article has been submitted.
+createstep.initial_locale.error.missing=The initial locale of the article was not submitted.
+createstep.workflow.none_selected=The selected workflow is not available.
+createstep.workflow.error.not_available=The selected workflow is not available.
+mpa.edit.denied=You have not been granted the required permissions to edit the article.
+authoringsteps.sections.description=Manage the sections of a multipart article.
diff --git a/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/MpaStepsBundle_de.properties b/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/MpaStepsBundle_de.properties
new file mode 100644
index 000000000..931da3890
--- /dev/null
+++ b/ccm-cms/src/main/resources/org/librecms/ui/contenttypes/MpaStepsBundle_de.properties
@@ -0,0 +1,14 @@
+
+createstep.label=Mehrteiliger Artikel
+createstep.description=Legt einen mehrteiligen Artikel mit einer Zusammenfassung und einem Haupttext, unterteilt in mehrere Abschnitte, an.
+authoringsteps.basicproperties.label=Basiseigenschaften
+authoringsteps.basicproperties.description=Bearbeiten der Basiseigenschaften
+createstep.name.error.missing=Der Name des neuen Artikels fehlt.
+createstep.name.error.invalid=Der Name des neuen Artikels ist nicht zul\u00e4ssig.
+createstep.title.error.missing=Der Titel des neuen Artikels fehlt.
+createstep.summary.error.missing=Es wurde keine Zusammenfassung f\u00fcr den neuen Artikel angegeben.
+createstep.initial_locale.error.missing=Es wurde keine initiale Sprache angegeben.
+createstep.workflow.none_selected=Der ausgew\u00e4hlte Arbeitsablauf ist nicht verf\u00fcgbar.
+createstep.workflow.error.not_available=Der ausgew\u00e4hlte Arbeitsablauf ist nicht verf\u00fcgbar.
+mpa.edit.denied=Ihnen wurden nicht die erforderlichen Berechtigungen erteilt, um diesen Artikel zu bearbeiten.
+authoringsteps.sections.description=Die Sektionen eines mehrteiligen Artikels verwalten.