Base class for all authoring steps

pull/10/head
Jens Pelzetter 2021-05-01 11:38:25 +02:00
parent 0baaefa543
commit b140923d86
14 changed files with 869 additions and 680 deletions

View File

@ -0,0 +1,312 @@
/*
* 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.contentsections.documents;
import org.hibernate.LazyInitializationException;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.ui.contentsections.ContentSectionModel;
import org.librecms.ui.contentsections.ContentSectionsUi;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.mvc.Models;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.UriBuilder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
@Inject
private DocumentUi documentUi;
@Inject
private ContentItemManager itemManager;
@Inject
private ContentItemRepository itemRepo;
@Inject
private ContentSectionModel sectionModel;
@Inject
private ContentSectionsUi sectionsUi;
@Inject
private GlobalizationHelper globalizationHelper;
@Inject
private HttpServletRequest request;
@Inject
private Models models;
@Inject
private SelectedDocumentModel documentModel;
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
private String sectionIdentifier;
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
private String documentPathParam;
private ContentSection contentSection;
private ContentItem document;
private String documentPath;
/**
* Inits the step. This method MUST be called by all resource methods (all
* methods annotated with {@link Path} in an authoring step. This is
* neccessary to keep all JPA operations inside a transaction to avoid
* {@link LazyInitializationException}s.
*
*
* @throws ContentSectionNotFoundException
* @throws DocumentNotFoundException
*/
protected void init()
throws ContentSectionNotFoundException, DocumentNotFoundException {
contentSection = sectionsUi
.findContentSection(sectionIdentifier)
.orElseThrow(
() -> new ContentSectionNotFoundException(
sectionsUi.showContentSectionNotFound(sectionIdentifier),
String.format(
"ContentSection %s not found.",
sectionIdentifier)
)
);
sectionModel.setSection(contentSection);
document = itemRepo
.findByPath(contentSection, documentPathParam)
.orElseThrow(
() -> new DocumentNotFoundException(
documentUi.showDocumentNotFound(
contentSection, documentPathParam),
String.format(
"Not document for path %s in section %s.",
documentPathParam,
contentSection.getLabel()
)
)
);
documentModel.setContentItem(document);
this.documentPath = itemManager.getItemPath(document);
models.put("activeDocumentTab", "editTab");
}
@Override
public ContentSection getContentSection() {
return Optional
.ofNullable(contentSection)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Authoring Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAuthoringStep.class.getName()
)
)
);
}
@Override
public ContentItem getDocument() {
return Optional
.ofNullable(document)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Authoring Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAuthoringStep.class.getName()
)
)
);
}
@Override
public String getDocumentPath() {
return Optional
.ofNullable(documentPath)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Authoring Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAuthoringStep.class.getName()
)
)
);
}
@Override
public String getLabel() {
return Optional
.ofNullable(
getStepClass().getAnnotation(MvcAuthoringStepDef.class)
)
.map(
annotation -> globalizationHelper.getLocalizedTextsUtil(
annotation.bundle()
).getText(annotation.labelKey())
)
.orElse("???");
}
@Override
public String getDescription() {
return Optional
.ofNullable(
getStepClass().getAnnotation(MvcAuthoringStepDef.class)
)
.map(
annotation -> globalizationHelper.getLocalizedTextsUtil(
annotation.bundle()
).getText(annotation.descriptionKey())
)
.orElse("");
}
@Override
public void updateDocumentPath() {
documentPath = itemManager.getItemPath(document).substring(1); // Without leading slash
}
@Override
public String buildRedirectPathForStep() {
final ContentSection section = Optional
.ofNullable(contentSection)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Authoring Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAuthoringStep.class.getName()
)
)
);
final String docPath = Optional
.ofNullable(documentPath)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Authoring Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAuthoringStep.class.getName()
)
)
);
final Map<String, String> values = new HashMap<>();
values.put(
MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM,
section.getLabel()
);
values.put(
MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME,
docPath
);
return Optional
.ofNullable(getStepClass().getAnnotation(Path.class))
.map(Path::value)
.map(
path -> UriBuilder
.fromPath(path)
.buildFromMap(values)
)
.map(path -> String.format("redirect:%s", path))
.orElse("");
}
@Override
public String buildRedirectPathForStep(final String subPath) {
final ContentSection section = Optional
.ofNullable(contentSection)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Authoring Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAuthoringStep.class.getName()
)
)
);
final String docPath = Optional
.ofNullable(documentPath)
.orElseThrow(
() -> new WebApplicationException(
String.format(
"Authoring Step %s was not initalized properly. "
+ "Did you forget to call %s#init()?",
getStepClass().getName(),
AbstractMvcAuthoringStep.class.getName()
)
)
);
final Map<String, String> values = new HashMap<>();
values.put(
MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM,
section.getLabel()
);
values.put(
MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME,
docPath
);
return Optional
.ofNullable(getStepClass().getAnnotation(Path.class))
.map(Path::value)
.map(
path -> UriBuilder
.fromPath(path)
.path(subPath)
.buildFromMap(values)
)
.map(path -> String.format("redirect:%s", path))
.orElse("");
}
}

View File

@ -71,12 +71,12 @@ public class AuthoringStepsValidator {
); );
} }
if (stepClass.getAnnotation(MvcAuthoringStep.class) == null) { if (stepClass.getAnnotation(MvcAuthoringStepDef.class) == null) {
LOGGER.warn( LOGGER.warn(
"Class {} is part of a set of authoring steps, but is not " "Class {} is part of a set of authoring steps, but is not "
+ "annotated with {}. The class will be ignored.", + "annotated with {}. The class will be ignored.",
stepClass.getName(), stepClass.getName(),
MvcAuthoringStep.class MvcAuthoringStepDef.class
); );
} }
@ -86,8 +86,7 @@ public class AuthoringStepsValidator {
public boolean supportsItem( public boolean supportsItem(
final Class<?> stepClass, final ContentItem item final Class<?> stepClass, final ContentItem item
) { ) {
final MvcAuthoringStep stepAnnotation = stepClass.getAnnotation( final MvcAuthoringStepDef stepAnnotation = stepClass.getAnnotation(MvcAuthoringStepDef.class
MvcAuthoringStep.class
); );
if (stepAnnotation == null) { if (stepAnnotation == null) {

View File

@ -58,13 +58,13 @@ import javax.ws.rs.PathParam;
@Path(MvcAuthoringSteps.PATH_PREFIX + "categorization") @Path(MvcAuthoringSteps.PATH_PREFIX + "categorization")
@Controller @Controller
@Named("CmsCategorizationStep") @Named("CmsCategorizationStep")
@MvcAuthoringStep( @MvcAuthoringStepDef(
bundle = DefaultAuthoringStepConstants.BUNDLE, bundle = DefaultAuthoringStepConstants.BUNDLE,
descriptionKey = "authoringsteps.categorization.description", descriptionKey = "authoringsteps.categorization.description",
labelKey = "authoringsteps.categorization.label", labelKey = "authoringsteps.categorization.label",
supportedDocumentType = ContentItem.class supportedDocumentType = ContentItem.class
) )
public class CategorizationStep { public class CategorizationStep extends AbstractMvcAuthoringStep {
@Inject @Inject
private CategoryManager categoryManager; private CategoryManager categoryManager;
@ -84,9 +84,10 @@ public class CategorizationStep {
@Inject @Inject
private PermissionChecker permissionChecker; private PermissionChecker permissionChecker;
@Inject public Class<CategorizationStep> getStepClass() {
private MvcAuthoringStepService stepService; return CategorizationStep.class;
}
@GET @GET
@Path("/") @Path("/")
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@ -97,7 +98,7 @@ public class CategorizationStep {
final String documentPath final String documentPath
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
@ -105,14 +106,14 @@ public class CategorizationStep {
} }
if (permissionChecker.isPermitted( if (permissionChecker.isPermitted(
ItemPrivileges.CATEGORIZE, stepService.getDocument() ItemPrivileges.CATEGORIZE, getDocument()
)) { )) {
return "org/librecms/ui/documents/categorization.xhtml"; return "org/librecms/ui/documents/categorization.xhtml";
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(getClass()) getLabel()
); );
} }
} }
@ -128,8 +129,7 @@ public class CategorizationStep {
*/ */
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public List<CategorizationTree> getCategorizationTrees() { public List<CategorizationTree> getCategorizationTrees() {
return stepService return getContentSection()
.getContentSection()
.getDomains() .getDomains()
.stream() .stream()
.map(DomainOwnership::getDomain) .map(DomainOwnership::getDomain)
@ -139,12 +139,11 @@ public class CategorizationStep {
/** /**
* Update the categorization of the current item. * Update the categorization of the current item.
*
* @param parameterPath The identifier for category system to use.
* @param parameters The parameters of the request. The map must contain
* a value with the key {@code assignedCategories}.
* *
* *
* @param domainParam
* @param assignedCategoriesParam
* @return A redirect to the categorization step. * @return A redirect to the categorization step.
*/ */
@MvcAuthoringAction( @MvcAuthoringAction(
@ -159,14 +158,21 @@ public class CategorizationStep {
@FormParam("assignedCategories") @FormParam("assignedCategories")
final Set<String> assignedCategoriesParam final Set<String> assignedCategoriesParam
) { ) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) {
return ex.showErrorMessage();
}
final Identifier domainIdentifier = identifierParser.parseIdentifier( final Identifier domainIdentifier = identifierParser.parseIdentifier(
domainParam domainParam
); );
final Optional<Domain> domainResult; final Optional<Domain> domainResult;
switch (domainIdentifier.getType()) { switch (domainIdentifier.getType()) {
case ID: case ID:
domainResult = stepService domainResult = getContentSection()
.getContentSection()
.getDomains() .getDomains()
.stream() .stream()
.map(DomainOwnership::getDomain) .map(DomainOwnership::getDomain)
@ -176,8 +182,7 @@ public class CategorizationStep {
).findAny(); ).findAny();
break; break;
case UUID: case UUID:
domainResult = stepService domainResult = getContentSection()
.getContentSection()
.getDomains() .getDomains()
.stream() .stream()
.map(DomainOwnership::getDomain) .map(DomainOwnership::getDomain)
@ -188,8 +193,7 @@ public class CategorizationStep {
).findAny(); ).findAny();
break; break;
default: default:
domainResult = stepService domainResult = getContentSection()
.getContentSection()
.getDomains() .getDomains()
.stream() .stream()
.map(DomainOwnership::getDomain) .map(DomainOwnership::getDomain)
@ -201,7 +205,7 @@ public class CategorizationStep {
} }
if (!domainResult.isPresent()) { if (!domainResult.isPresent()) {
models.put("section", stepService.getContentSection().getLabel()); models.put("section", getContentSection().getLabel());
models.put("domainIdentifier", domainIdentifier); models.put("domainIdentifier", domainIdentifier);
return "org/librecms/ui/documents/categorization-domain-not-found.xhtml"; return "org/librecms/ui/documents/categorization-domain-not-found.xhtml";
} }
@ -210,7 +214,7 @@ public class CategorizationStep {
domainResult.get().getRoot(), assignedCategoriesParam domainResult.get().getRoot(), assignedCategoriesParam
); );
return stepService.buildRedirectPathForStep(getClass()); return buildRedirectPathForStep();
} }
/** /**
@ -230,7 +234,7 @@ public class CategorizationStep {
final Category category, final Category category,
final Set<String> assignedCategoriesParam final Set<String> assignedCategoriesParam
) { ) {
final ContentItem document = stepService.getDocument(); final ContentItem document = getDocument();
if (assignedCategoriesParam.contains(category.getUuid()) if (assignedCategoriesParam.contains(category.getUuid())
&& !categoryManager.isAssignedToCategory(category, document)) { && !categoryManager.isAssignedToCategory(category, document)) {
categoryManager.addObjectToCategory(document, category); categoryManager.addObjectToCategory(document, category);
@ -327,7 +331,7 @@ public class CategorizationStep {
final Category category final Category category
) { ) {
final CategorizationTreeNode node = new CategorizationTreeNode(); final CategorizationTreeNode node = new CategorizationTreeNode();
final ContentItem document = stepService.getDocument(); final ContentItem document = getDocument();
node.setAssigned(categoryManager.isAssignedToCategory( node.setAssigned(categoryManager.isAssignedToCategory(
category, document) category, document)
); );

View File

@ -114,11 +114,11 @@ public class DocumentController {
private ContentItemRepository itemRepo; private ContentItemRepository itemRepo;
/** /**
* All available {@link MvcAuthoringStep}s. * All available {@link MvcAuthoringStepDef}s.
*/ */
@Inject @Inject
@Any @Any
private Instance<MvcAuthoringStep> authoringSteps; private Instance<MvcAuthoringStepDef> authoringSteps;
/** /**
* All available {@link MvcDocumentCreateStep}s. * All available {@link MvcDocumentCreateStep}s.
@ -451,7 +451,7 @@ public class DocumentController {
// models.put("authoringStep", authoringStepIdentifier); // models.put("authoringStep", authoringStepIdentifier);
// return showAuthoringStepNotAvailable(authoringStepIdentifier); // return showAuthoringStepNotAvailable(authoringStepIdentifier);
// } // }
// final MvcAuthoringStep authoringStep = instance.get(); // final MvcAuthoringStepDef authoringStep = instance.get();
// //
// if (!authoringStep.supportedDocumentType().isAssignableFrom(item // if (!authoringStep.supportedDocumentType().isAssignableFrom(item
// .getClass())) { // .getClass())) {

View File

@ -18,61 +18,92 @@
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import java.lang.annotation.ElementType; import javax.ws.rs.Path;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Named;
/** /**
* Metadata of an authoring step for documents (content items). * Base interface for authoring steps. For buidling authoring steps it is
* * recommanned to use the {@link AbstractMvcAuthoringStep} as base that
* An authoring step for a document (content item). Implementing classes are * implements most of the methods defined by this interface.
* used as subresources by {@link DocumentController#editDocument(java.lang.String, java.lang.String, java.lang.String)
* }. An implementation must be a named CDI bean (annotated with {@link Named},
* annotated with the {@link AuthoringStepPathFragment} qualifier annotation.
*
* An implementation may contain multiple subresource paths for for displaying
* forms and apply changes from these forms.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@Target(ElementType.TYPE) public interface MvcAuthoringStep {
@Retention(RetentionPolicy.RUNTIME)
public @interface MvcAuthoringStep { Class<? extends MvcAuthoringStep> getStepClass();
ContentSection getContentSection() throws ContentSectionNotFoundException;
ContentItem getDocument() throws ContentSectionNotFoundException,
DocumentNotFoundException;
String getDocumentPath() throws ContentSectionNotFoundException,
DocumentNotFoundException;
/** /**
* The name of the resource bundle providing the localized values for * Gets the label for an authoring step.
* {@link #labelKey} and {@link descriptionKey}.
* *
* @return The resource bundle providing the localized labelKey and * @return The label for the authoring step. If the implementing class is
* descriptionKey. * not annotated with {@link MvcAuthoringStepDef} the string
* {@code ???} is returned.
*/ */
String bundle(); String getLabel();
/** /**
* The key for the localized description of the step. * Gets the description for an authoring step.
* *
* @return The key for the localized description of the step. * @return The label for the authoring step. If the implementing class is
* not annotated with {@link MvcAuthoringStepDef} an empty stringis
* returned.
*/ */
String descriptionKey(); String getDescription();
/** /**
* The key for the localized label of the authoring step.. * If an authoring step alters the name of the content item and therefore
* the path of the item, the step MUST call this method to update the
* document path used by the step.
* *
* @return The key for the localized label of the authoring step... * @throws
* org.librecms.ui.contentsections.documents.ContentSectionNotFoundException
* @throws
* org.librecms.ui.contentsections.documents.DocumentNotFoundException
*/ */
String labelKey(); void updateDocumentPath() throws ContentSectionNotFoundException,
DocumentNotFoundException;
/** /**
* Authoring steps only support a specific type, and all subtypes. * Builds the redirect path of the authoring step.This path is most often
* used to implement the redirect after post pattern.
* *
* @return The document type supported by the authoring step. * @return The redirect path. If the the implementing class is not annotated
* with {@link Path} an empty string is returned.
*
* @throws
* org.librecms.ui.contentsections.documents.ContentSectionNotFoundException
* @throws
* org.librecms.ui.contentsections.documents.DocumentNotFoundException
*/ */
Class<? extends ContentItem> supportedDocumentType(); String buildRedirectPathForStep() throws ContentSectionNotFoundException,
DocumentNotFoundException;
/**
* Builds the redirect path of the authoring step.This path is most often
* used to implement the redirect after post pattern.
*
* @param subPath additional path elements that are appended to the path of
* the authoring step.
*
* @return The redirect path. If the the implemeting class is not annotated
* with {@link Path} an empty string is returned.
*
* @throws
* org.librecms.ui.contentsections.documents.ContentSectionNotFoundException
* @throws
* org.librecms.ui.contentsections.documents.DocumentNotFoundException
*/
String buildRedirectPathForStep(final String subPath) throws
ContentSectionNotFoundException, DocumentNotFoundException;
} }

View File

@ -0,0 +1,77 @@
/*
* 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.contentsections.documents;
import org.librecms.contentsection.ContentItem;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Named;
/**
* Metadata of an authoring step for documents (content items).
*
* An authoring step for a document (content item). Implementing classes are
* used as subresources by {@link DocumentController#editDocument(java.lang.String, java.lang.String, java.lang.String)
* }. An implementation must be a named CDI bean (annotated with {@link Named},
* annotated with the {@link AuthoringStepPathFragment} qualifier annotation.
*
* An implementation may contain multiple subresource paths for for displaying
* forms and apply changes from these forms.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MvcAuthoringStepDef {
/**
* The name of the resource bundle providing the localized values for
* {@link #labelKey} and {@link descriptionKey}.
*
* @return The resource bundle providing the localized labelKey and
* descriptionKey.
*/
String bundle();
/**
* The key for the localized description of the step.
*
* @return The key for the localized description of the step.
*/
String descriptionKey();
/**
* The key for the localized label of the authoring step..
*
* @return The key for the localized label of the authoring step...
*/
String labelKey();
/**
* Authoring steps only support a specific type, and all subtypes.
*
* @return The document type supported by the authoring step.
*/
Class<? extends ContentItem> supportedDocumentType();
}

View File

@ -1,266 +0,0 @@
/*
* 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.contentsections.documents;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.ui.contentsections.ContentSectionModel;
import org.librecms.ui.contentsections.ContentSectionsUi;
import java.util.Objects;
import java.util.Optional;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.mvc.Models;
import javax.ws.rs.Path;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Dependent
public class MvcAuthoringStepService {
@Inject
private DocumentUi documentUi;
@Inject
private ContentItemManager itemManager;
@Inject
private ContentItemRepository itemRepo;
@Inject
private ContentSectionModel sectionModel;
@Inject
private ContentSectionsUi sectionsUi;
@Inject
private GlobalizationHelper globalizationHelper;
@Inject
private Models models;
@Inject
private SelectedDocumentModel documentModel;
private ContentSection section;
private ContentItem document;
private String documentPath;
public ContentSection getContentSection() {
return section;
}
public ContentItem getDocument() {
return document;
}
public String getDocumentPath() {
return documentPath;
}
/**
* Gets the label for an authoring step.
*
* @param step The authoring step class.
*
* @return The label for the authoring step. If the provided class is not
* annotated with {@link MvcAuthoringStep} the string {@code ???} is
* returned.
*/
public String getLabel(final Class<?> step) {
return Optional
.ofNullable(step.getAnnotation(MvcAuthoringStep.class))
.map(
annotation -> globalizationHelper.getLocalizedTextsUtil(
annotation.bundle()
).getText(annotation.labelKey())
)
.orElse("???");
}
/**
* Gets the description for an authoring step.
*
* @param step The authoring step class.
*
* @return The label for the authoring step. If the provided class is not
* annotated with {@link MvcAuthoringStep} an empty stringis
* returned.
*/
public String getDescription(final Class<?> step) {
return Optional
.ofNullable(step.getAnnotation(MvcAuthoringStep.class))
.map(
annotation -> globalizationHelper.getLocalizedTextsUtil(
annotation.bundle()
).getText(annotation.descriptionKey())
)
.orElse("");
}
/**
* Sets the properties {@link #section}, {@link #document} and
* {@link #documentPath} to content section and the document/content item
* identified by the provided parameters.
*
* @param sectionIdentifier The identifier of the content section.
* @param documentPath The identifier of the document/content item.
*
* @throws ContentSectionNotFoundException If there is no content section
* identified by
* {@code sectionIdentifier}.
* @throws DocumentNotFoundException If there is not document/content
* item with the path
* {@code documentPath} in the
* content section.
*/
public void setSectionAndDocument(
final String sectionIdentifier, final String documentPath
) throws ContentSectionNotFoundException, DocumentNotFoundException {
section = sectionsUi
.findContentSection(sectionIdentifier)
.orElseThrow(
() -> new ContentSectionNotFoundException(
sectionsUi.showContentSectionNotFound(sectionIdentifier),
String.format(
"ContentSection %s not found.",
sectionIdentifier)
)
);
sectionModel.setSection(section);
document = itemRepo
.findByPath(section, documentPath)
.orElseThrow(
() -> new DocumentNotFoundException(
documentUi.showDocumentNotFound(
section, documentPath),
String.format(
"Not document for path %s in section %s.",
documentPath,
section.getLabel()
)
)
);
documentModel.setContentItem(document);
this.documentPath = itemManager.getItemPath(document);
models.put("activeDocumentTab", "editTab");
}
public void updateDocumentPath() {
documentPath = itemManager.getItemPath(document);
}
/**
* Builds the redirect path of the authoring step provided by the class
* {@code step}. This path is most often used to implement the redirect
* after post pattern.
*
* @param step The authoring step class.
*
* @return The redirect path. If the the provided class is not annotated
* with {@link Path} an empty string is returned.
*/
public String buildRedirectPathForStep(final Class<?> step) {
Objects.requireNonNull(step);
return Optional
.ofNullable(step.getAnnotation(Path.class))
.map(Path::value)
.map(
path -> path
.replace(
String.format(
"{%s}",
MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM
),
section.getLabel()
)
.replace(
String.format(
"{%s}",
MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM
),
documentPath
)
)
.map(path -> String.format("redirect:%s", path))
.orElse("");
}
/**
* Builds the redirect path of the authoring step provided by the class
* {@code step}.This path is most often used to implement the redirect after
* post pattern.
*
* @param step The authoring step class.
* @param subPath additional path fragment(s) that are appended to the path
* of the authoring step.
*
* @return The redirect path. If the the provided class is not annotated
* with {@link Path} an empty string is returned.
*/
public String buildRedirectPathForStep(
final Class<?> step, final String subPath
) {
Objects.requireNonNull(step);
Objects.requireNonNull(subPath);
final String subPathNormalized;
if (subPath.startsWith("/")) {
subPathNormalized = subPath.substring(1);
} else {
subPathNormalized = subPath;
}
return Optional
.ofNullable(step.getAnnotation(Path.class))
.map(Path::value)
.map(
path -> path
.replace(
String.format(
"{%s}",
MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM
),
section.getLabel()
)
.replace(
String.format("{%s}",
MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME
),
documentPath
)
)
.map(
path -> String.format(
"redirect:%s/%s", path, subPathNormalized)
).orElse("");
}
}

View File

@ -60,13 +60,13 @@ import javax.ws.rs.PathParam;
@Path(MvcAuthoringSteps.PATH_PREFIX + "publish") @Path(MvcAuthoringSteps.PATH_PREFIX + "publish")
@Controller @Controller
@Named("CmsPublishStep") @Named("CmsPublishStep")
@MvcAuthoringStep( @MvcAuthoringStepDef(
bundle = DefaultAuthoringStepConstants.BUNDLE, bundle = DefaultAuthoringStepConstants.BUNDLE,
descriptionKey = "authoringsteps.publish.description", descriptionKey = "authoringsteps.publish.description",
labelKey = "authoringsteps.publish.label", labelKey = "authoringsteps.publish.label",
supportedDocumentType = ContentItem.class supportedDocumentType = ContentItem.class
) )
public class PublishStep { public class PublishStep extends AbstractMvcAuthoringStep {
private static final String TEMPLATE private static final String TEMPLATE
= "org/librecms/ui/documenttypes/publish.xhtml"; = "org/librecms/ui/documenttypes/publish.xhtml";
@ -96,9 +96,11 @@ public class PublishStep {
@Inject @Inject
private Models models; private Models models;
@Inject @Override
private MvcAuthoringStepService stepService; public Class<PublishStep> getStepClass() {
return PublishStep.class;
}
@GET @GET
@Path("/") @Path("/")
@ -110,15 +112,15 @@ public class PublishStep {
final String documentPath final String documentPath
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
final ContentItem document = stepService.getDocument(); final ContentItem document = getDocument();
if (itemPermissionChecker.canPublishItems(stepService.getDocument())) { if (itemPermissionChecker.canPublishItems(getDocument())) {
final String lifecycleDefUuid; final String lifecycleDefUuid;
if (itemManager.isLive(document)) { if (itemManager.isLive(document)) {
lifecycleDefUuid = document lifecycleDefUuid = document
@ -135,11 +137,11 @@ public class PublishStep {
return TEMPLATE; return TEMPLATE;
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
defaultStepsMessageBundle.getMessage( defaultStepsMessageBundle.getMessage(
"access_to_authoringstep_denied", "access_to_authoringstep_denied",
new String[]{stepService.getLabel(getClass())} new String[]{getLabel()}
) )
); );
} }
@ -157,7 +159,7 @@ public class PublishStep {
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String getAssignedLifecycleLabel() { public String getAssignedLifecycleLabel() {
return Optional return Optional
.ofNullable(stepService.getDocument().getLifecycle()) .ofNullable(getDocument().getLifecycle())
.map(Lifecycle::getDefinition) .map(Lifecycle::getDefinition)
.map(LifecycleDefinition::getLabel) .map(LifecycleDefinition::getLabel)
.map(globalizationHelper::getValueFromLocalizedString) .map(globalizationHelper::getValueFromLocalizedString)
@ -177,7 +179,7 @@ public class PublishStep {
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String getAssignedLifecycleDecription() { public String getAssignedLifecycleDecription() {
return Optional return Optional
.ofNullable(stepService.getDocument().getLifecycle()) .ofNullable(getDocument().getLifecycle())
.map(Lifecycle::getDefinition) .map(Lifecycle::getDefinition)
.map(LifecycleDefinition::getDescription) .map(LifecycleDefinition::getDescription)
.map(globalizationHelper::getValueFromLocalizedString) .map(globalizationHelper::getValueFromLocalizedString)
@ -222,14 +224,14 @@ public class PublishStep {
final String endTimeParam final String endTimeParam
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
final ContentItem document = stepService.getDocument(); final ContentItem document = getDocument();
if (selectedLifecycleDefUuid.isEmpty()) { if (selectedLifecycleDefUuid.isEmpty()) {
models.put("missingLifecycleDefinitionUuid", true); models.put("missingLifecycleDefinitionUuid", true);
@ -332,7 +334,7 @@ public class PublishStep {
if (!itemPermissionChecker.canPublishItems(document)) { if (!itemPermissionChecker.canPublishItems(document)) {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
document, document,
"item.publish" "item.publish"
); );
@ -355,7 +357,7 @@ public class PublishStep {
if (!definitionResult.isPresent()) { if (!definitionResult.isPresent()) {
models.put( models.put(
"contentSection", "contentSection",
stepService.getContentSection().getLabel() getContentSection().getLabel()
); );
models.put("lifecycleDefinitionUuid", selectedLifecycleDefUuid); models.put("lifecycleDefinitionUuid", selectedLifecycleDefUuid);
return "org/librecms/ui/documents/lifecycle-definition-not-found.xhtml"; return "org/librecms/ui/documents/lifecycle-definition-not-found.xhtml";
@ -366,7 +368,7 @@ public class PublishStep {
); );
} }
return stepService.buildRedirectPathForStep(getClass()); return buildRedirectPathForStep();
} }
/** /**
@ -380,10 +382,10 @@ public class PublishStep {
) )
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String unpublish() { public String unpublish() {
final ContentItem document = stepService.getDocument(); final ContentItem document = getDocument();
if (!itemPermissionChecker.canPublishItems(document)) { if (!itemPermissionChecker.canPublishItems(document)) {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
document, document,
"item.unpublish" "item.unpublish"
); );
@ -391,7 +393,7 @@ public class PublishStep {
itemManager.unpublish(document); itemManager.unpublish(document);
return stepService.buildRedirectPathForStep(getClass()); return buildRedirectPathForStep();
} }
} }

View File

@ -35,14 +35,20 @@ import org.librecms.ui.contentsections.FolderBreadcrumbsModel;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.core.UriBuilder;
import static javax.transaction.Transactional.TxType.values;
/** /**
* Model/named bean providing data about the currently selected document for * Model/named bean providing data about the currently selected document for
@ -84,6 +90,9 @@ public class SelectedDocumentModel {
@Inject @Inject
private GlobalizationHelper globalizationHelper; private GlobalizationHelper globalizationHelper;
@Inject
private HttpServletRequest request;
/** /**
* Used to check permissions * Used to check permissions
*/ */
@ -209,7 +218,7 @@ public class SelectedDocumentModel {
itemTitle = globalizationHelper.getValueFromLocalizedString( itemTitle = globalizationHelper.getValueFromLocalizedString(
item.getTitle() item.getTitle()
); );
itemPath = itemManager.getItemPath(item); itemPath = itemManager.getItemPath(item).substring(1); //Without leading slash
parentFolderBreadcrumbs = itemManager parentFolderBreadcrumbs = itemManager
.getItemFolders(item) .getItemFolders(item)
.stream() .stream()
@ -322,7 +331,7 @@ public class SelectedDocumentModel {
/** /**
* Helper method for building a {@link AuthoringStepListEntry} from the * Helper method for building a {@link AuthoringStepListEntry} from the
* {@link MvcAuthoringStep}. * {@link MvcAuthoringStepDef}.
* *
* @param step Th step. * @param step Th step.
* *
@ -331,8 +340,8 @@ public class SelectedDocumentModel {
private AuthoringStepListEntry buildAuthoringStepListEntry( private AuthoringStepListEntry buildAuthoringStepListEntry(
final Class<?> authoringStepClass final Class<?> authoringStepClass
) { ) {
final MvcAuthoringStep stepAnnotation = authoringStepClass final MvcAuthoringStepDef stepAnnotation = authoringStepClass
.getAnnotation(MvcAuthoringStep.class); .getAnnotation(MvcAuthoringStepDef.class);
final Path pathAnnotation = authoringStepClass.getAnnotation( final Path pathAnnotation = authoringStepClass.getAnnotation(
Path.class Path.class
); );
@ -341,7 +350,7 @@ public class SelectedDocumentModel {
final AuthoringStepListEntry entry = new AuthoringStepListEntry(); final AuthoringStepListEntry entry = new AuthoringStepListEntry();
entry.setDescription(textsUtil.getText(stepAnnotation.descriptionKey())); entry.setDescription(textsUtil.getText(stepAnnotation.descriptionKey()));
entry.setLabel(textsUtil.getText(stepAnnotation.labelKey())); entry.setLabel(textsUtil.getText(stepAnnotation.labelKey()));
entry.setPath(createStepPath(pathAnnotation.value())); entry.setPath(createStepPath(authoringStepClass));
return entry; return entry;
} }
@ -363,4 +372,30 @@ public class SelectedDocumentModel {
); );
} }
private String createStepPath(final Class<?> stepClass) {
final Map<String, String> values = new HashMap<>();
values.put(
MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM,
item.getContentType().getContentSection().getLabel()
);
values.put(
MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME,
itemPath
);
final UriBuilder uriBuilder;
if (request.getContextPath() == null) {
uriBuilder = UriBuilder.fromPath("/@contentsections");
} else {
uriBuilder = UriBuilder
.fromPath(request.getContextPath())
.path("/@contentsections");
}
return uriBuilder
.path(stepClass)
.buildFromMap(values, false)
.toString();
}
} }

View File

@ -25,11 +25,11 @@ import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.FolderManager; import org.librecms.contentsection.FolderManager;
import org.librecms.contenttypes.Article; import org.librecms.contenttypes.Article;
import org.librecms.ui.contentsections.ItemPermissionChecker; import org.librecms.ui.contentsections.ItemPermissionChecker;
import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep;
import org.librecms.ui.contentsections.documents.ContentSectionNotFoundException; import org.librecms.ui.contentsections.documents.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentNotFoundException; import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentUi; import org.librecms.ui.contentsections.documents.DocumentUi;
import org.librecms.ui.contentsections.documents.MvcAuthoringStep; import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepService;
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps; import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
import java.util.Collections; import java.util.Collections;
@ -63,13 +63,13 @@ import javax.ws.rs.PathParam;
@Path(MvcAuthoringSteps.PATH_PREFIX + "article-basicproperties") @Path(MvcAuthoringSteps.PATH_PREFIX + "article-basicproperties")
@Controller @Controller
@Named("CmsArticlePropertiesStep") @Named("CmsArticlePropertiesStep")
@MvcAuthoringStep( @MvcAuthoringStepDef(
bundle = ArticleStepsConstants.BUNDLE, bundle = ArticleStepsConstants.BUNDLE,
descriptionKey = "authoringsteps.basicproperties.description", descriptionKey = "authoringsteps.basicproperties.description",
labelKey = "authoringsteps.basicproperties.label", labelKey = "authoringsteps.basicproperties.label",
supportedDocumentType = Article.class supportedDocumentType = Article.class
) )
public class MvcArticlePropertiesStep { public class MvcArticlePropertiesStep extends AbstractMvcAuthoringStep {
@Inject @Inject
private ArticleMessageBundle articleMessageBundle; private ArticleMessageBundle articleMessageBundle;
@ -107,9 +107,6 @@ public class MvcArticlePropertiesStep {
@Inject @Inject
private Models models; private Models models;
@Inject
private MvcAuthoringStepService stepService;
private Map<String, String> titleValues; private Map<String, String> titleValues;
private List<String> unusedTitleLocales; private List<String> unusedTitleLocales;
@ -118,6 +115,11 @@ public class MvcArticlePropertiesStep {
private List<String> unusedDescriptionLocales; private List<String> unusedDescriptionLocales;
@Override
public Class<MvcArticlePropertiesStep> getStepClass() {
return MvcArticlePropertiesStep.class;
}
@GET @GET
@Path("/") @Path("/")
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@ -128,16 +130,15 @@ public class MvcArticlePropertiesStep {
final String documentPath final String documentPath
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
titleValues = stepService titleValues = getDocument()
.getDocument()
.getTitle() .getTitle()
.getValues() .getValues()
.entrySet() .entrySet()
@ -149,8 +150,7 @@ public class MvcArticlePropertiesStep {
) )
); );
final Set<Locale> titleLocales = stepService final Set<Locale> titleLocales = getDocument()
.getDocument()
.getTitle() .getTitle()
.getAvailableLocales(); .getAvailableLocales();
@ -161,8 +161,7 @@ public class MvcArticlePropertiesStep {
.map(Locale::toString) .map(Locale::toString)
.collect(Collectors.toList()); .collect(Collectors.toList());
descriptionValues = stepService descriptionValues = getDocument()
.getDocument()
.getDescription() .getDescription()
.getValues() .getValues()
.entrySet() .entrySet()
@ -174,8 +173,7 @@ public class MvcArticlePropertiesStep {
) )
); );
final Set<Locale> descriptionLocales = stepService final Set<Locale> descriptionLocales = getDocument()
.getDocument()
.getDescription() .getDescription()
.getAvailableLocales(); .getAvailableLocales();
@ -189,8 +187,8 @@ public class MvcArticlePropertiesStep {
return "org/librecms/ui/contenttypes/article/article-basic-properties.xhtml"; return "org/librecms/ui/contenttypes/article/article-basic-properties.xhtml";
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
articleMessageBundle.getMessage("article.edit.denied") articleMessageBundle.getMessage("article.edit.denied")
); );
} }
@ -203,7 +201,7 @@ public class MvcArticlePropertiesStep {
* @return The display name of the current article. * @return The display name of the current article.
*/ */
public String getName() { public String getName() {
return stepService.getDocument().getDisplayName(); return getDocument().getDisplayName();
} }
/** /**
@ -226,33 +224,31 @@ public class MvcArticlePropertiesStep {
@FormParam("name") @DefaultValue("") final String name @FormParam("name") @DefaultValue("") final String name
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
if (name.isEmpty() || name.matches("\\s*")) { if (name.isEmpty() || name.matches("\\s*")) {
models.put("nameMissing", true); models.put("nameMissing", true);
return showStep(sectionIdentifier, documentPath); return showStep(sectionIdentifier, documentPath);
} }
stepService.getDocument().setDisplayName(name); getDocument().setDisplayName(name);
itemRepo.save(stepService.getDocument()); itemRepo.save(getDocument());
stepService.updateDocumentPath();
return stepService.buildRedirectPathForStep( updateDocumentPath();
MvcArticlePropertiesStep.class
); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(MvcArticlePropertiesStep.class) getLabel()
); );
} }
} }
@ -297,24 +293,24 @@ public class MvcArticlePropertiesStep {
@FormParam("value") final String value @FormParam("value") final String value
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
stepService.getDocument().getTitle().addValue(locale, value); getDocument().getTitle().addValue(locale, value);
itemRepo.save(stepService.getDocument()); itemRepo.save(getDocument());
return stepService.buildRedirectPathForStep(MvcArticlePropertiesStep.class); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(MvcArticlePropertiesStep.class) getLabel()
); );
} }
} }
@ -333,7 +329,7 @@ public class MvcArticlePropertiesStep {
@Path("/title/@edit/{locale}") @Path("/title/@edit/{locale}")
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String editTitle( public String editTitle(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM) @PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier, final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME) @PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath, final String documentPath,
@ -341,24 +337,24 @@ public class MvcArticlePropertiesStep {
@FormParam("value") final String value @FormParam("value") final String value
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
stepService.getDocument().getTitle().addValue(locale, value); getDocument().getTitle().addValue(locale, value);
itemRepo.save(stepService.getDocument()); itemRepo.save(getDocument());
return stepService.buildRedirectPathForStep(MvcArticlePropertiesStep.class); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(MvcArticlePropertiesStep.class) getLabel()
); );
} }
} }
@ -383,24 +379,24 @@ public class MvcArticlePropertiesStep {
@PathParam("locale") final String localeParam @PathParam("locale") final String localeParam
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
stepService.getDocument().getTitle().removeValue(locale); getDocument().getTitle().removeValue(locale);
itemRepo.save(stepService.getDocument()); itemRepo.save(getDocument());
return stepService.buildRedirectPathForStep(MvcArticlePropertiesStep.class); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(MvcArticlePropertiesStep.class) getLabel()
); );
} }
} }
@ -446,24 +442,24 @@ public class MvcArticlePropertiesStep {
@FormParam("value") final String value @FormParam("value") final String value
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
stepService.getDocument().getDescription().addValue(locale, value); getDocument().getDescription().addValue(locale, value);
itemRepo.save(stepService.getDocument()); itemRepo.save(getDocument());
return stepService.buildRedirectPathForStep(MvcArticlePropertiesStep.class); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(MvcArticlePropertiesStep.class) getLabel()
); );
} }
} }
@ -490,24 +486,24 @@ public class MvcArticlePropertiesStep {
@FormParam("value") final String value @FormParam("value") final String value
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
stepService.getDocument().getDescription().addValue(locale, value); getDocument().getDescription().addValue(locale, value);
itemRepo.save(stepService.getDocument()); itemRepo.save(getDocument());
return stepService.buildRedirectPathForStep(MvcArticlePropertiesStep.class); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(MvcArticlePropertiesStep.class) getLabel()
); );
} }
} }
@ -532,24 +528,24 @@ public class MvcArticlePropertiesStep {
@PathParam("locale") final String localeParam @PathParam("locale") final String localeParam
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getDocument())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
stepService.getDocument().getDescription().removeValue(locale); getDocument().getDescription().removeValue(locale);
itemRepo.save(stepService.getDocument()); itemRepo.save(getDocument());
return stepService.buildRedirectPathForStep(MvcArticlePropertiesStep.class); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getDocument(),
stepService.getLabel(MvcArticlePropertiesStep.class) getLabel()
); );
} }
} }

View File

@ -23,6 +23,7 @@ import org.libreccm.l10n.LocalizedString;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contenttypes.Article; import org.librecms.contenttypes.Article;
import org.librecms.ui.contentsections.ItemPermissionChecker; import org.librecms.ui.contentsections.ItemPermissionChecker;
import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep;
import org.librecms.ui.contentsections.documents.ContentSectionNotFoundException; import org.librecms.ui.contentsections.documents.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentNotFoundException; import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentUi; import org.librecms.ui.contentsections.documents.DocumentUi;
@ -30,8 +31,6 @@ import org.librecms.ui.contentsections.documents.DocumentUi;
import javax.mvc.Controller; import javax.mvc.Controller;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import org.librecms.ui.contentsections.documents.MvcAuthoringStep;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepService;
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps; import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
import java.util.List; import java.util.List;
@ -49,6 +48,8 @@ import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
/** /**
* Authoring step for editing the main text of an {@link Article}. * Authoring step for editing the main text of an {@link Article}.
* *
@ -58,13 +59,13 @@ import javax.ws.rs.PathParam;
@Path(MvcAuthoringSteps.PATH_PREFIX + "text") @Path(MvcAuthoringSteps.PATH_PREFIX + "text")
@Controller @Controller
@Named("CmsArticleTextBodyStep") @Named("CmsArticleTextBodyStep")
@MvcAuthoringStep( @MvcAuthoringStepDef(
bundle = ArticleStepsConstants.BUNDLE, bundle = ArticleStepsConstants.BUNDLE,
descriptionKey = "authoringsteps.text.description", descriptionKey = "authoringsteps.text.description",
labelKey = "authoringsteps.text.label", labelKey = "authoringsteps.text.label",
supportedDocumentType = Article.class supportedDocumentType = Article.class
) )
public class MvcArticleTextBodyStep { public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
@Inject @Inject
private ArticleMessageBundle articleMessageBundle; private ArticleMessageBundle articleMessageBundle;
@ -87,9 +88,11 @@ public class MvcArticleTextBodyStep {
@Inject @Inject
private ItemPermissionChecker itemPermissionChecker; private ItemPermissionChecker itemPermissionChecker;
@Inject @Override
private MvcAuthoringStepService stepService; public Class<MvcArticleTextBodyStep> getStepClass() {
return MvcArticleTextBodyStep.class;
}
@GET @GET
@Path("/") @Path("/")
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@ -100,19 +103,19 @@ public class MvcArticleTextBodyStep {
final String documentPath final String documentPath
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getArticle())) {
return "org/librecms/ui/contenttypes/article/article-text.xhtml"; return "org/librecms/ui/contenttypes/article/article-text.xhtml";
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getArticle(),
articleMessageBundle.getMessage("article.edit.denied") articleMessageBundle.getMessage("article.edit.denied")
); );
} }
@ -124,7 +127,7 @@ public class MvcArticleTextBodyStep {
* @return The localized values of the main text. * @return The localized values of the main text.
*/ */
public Map<String, String> getTextValues() { public Map<String, String> getTextValues() {
return getDocument() return getArticle()
.getText() .getText()
.getValues() .getValues()
.entrySet() .entrySet()
@ -143,7 +146,7 @@ public class MvcArticleTextBodyStep {
* @return The locales for which the main text has not been defined yet. * @return The locales for which the main text has not been defined yet.
*/ */
public List<String> getUnusedLocales() { public List<String> getUnusedLocales() {
final Set<Locale> locales = getDocument() final Set<Locale> locales = getArticle()
.getText() .getText()
.getAvailableLocales(); .getAvailableLocales();
return globalizationHelper return globalizationHelper
@ -176,24 +179,24 @@ public class MvcArticleTextBodyStep {
@FormParam("value") final String value @FormParam("value") final String value
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getArticle())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
getDocument().getText().addValue(locale, value); getArticle().getText().addValue(locale, value);
itemRepo.save(stepService.getDocument()); itemRepo.save(getArticle());
return stepService.buildRedirectPathForStep(getClass()); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getArticle(),
stepService.getLabel(getClass()) getLabel()
); );
} }
} }
@ -220,24 +223,24 @@ public class MvcArticleTextBodyStep {
@FormParam("value") final String value @FormParam("value") final String value
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getArticle())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
getDocument().getText().addValue(locale, value); getArticle().getText().addValue(locale, value);
itemRepo.save(stepService.getDocument()); itemRepo.save(getArticle());
return stepService.buildRedirectPathForStep(getClass()); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getArticle(),
stepService.getLabel(getClass()) getLabel()
); );
} }
} }
@ -262,30 +265,30 @@ public class MvcArticleTextBodyStep {
@PathParam("locale") final String localeParam @PathParam("locale") final String localeParam
) { ) {
try { try {
stepService.setSectionAndDocument(sectionIdentifier, documentPath); init();
} catch (ContentSectionNotFoundException ex) { } catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) { } catch (DocumentNotFoundException ex) {
return ex.showErrorMessage(); return ex.showErrorMessage();
} }
if (itemPermissionChecker.canEditItem(stepService.getDocument())) { if (itemPermissionChecker.canEditItem(getArticle())) {
final Locale locale = new Locale(localeParam); final Locale locale = new Locale(localeParam);
getDocument().getText().removeValue(locale); getArticle().getText().removeValue(locale);
itemRepo.save(stepService.getDocument()); itemRepo.save(getArticle());
return stepService.buildRedirectPathForStep(getClass()); return buildRedirectPathForStep();
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
stepService.getContentSection(), getContentSection(),
stepService.getDocument(), getArticle(),
stepService.getLabel(getClass()) getLabel()
); );
} }
} }
private Article getDocument() { private Article getArticle() {
return (Article) stepService.getDocument(); return (Article) getDocument();
} }
} }

View File

@ -103,7 +103,7 @@
<li aria-current="#{step.path == authoringStep ? 'true' : ''}" <li aria-current="#{step.path == authoringStep ? 'true' : ''}"
class="list-group-item #{step.path == authoringStep ? 'active' : ''}"> class="list-group-item #{step.path == authoringStep ? 'active' : ''}">
<a class="list-group-item-action" <a class="list-group-item-action"
href="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{step.path}"> href="#{step.path}">
#{step.label} #{step.label}
</a> </a>
</li> </li>

View File

@ -28,7 +28,7 @@
id="name-edit-dialog" id="name-edit-dialog"
tabindex="-1"> tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/name" <form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/name"
class="modal-content" class="modal-content"
method="post"> method="post">
<div class="modal-header"> <div class="modal-header">
@ -78,14 +78,14 @@
addDialogTitle="#{CmsArticleMessageBundle['basicproperties.title.add.header']}" addDialogTitle="#{CmsArticleMessageBundle['basicproperties.title.add.header']}"
addDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.title.add.value.help']}" addDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.title.add.value.help']}"
addDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.title.add.value.label']}" addDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.title.add.value.label']}"
addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/title/@add" addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/title/@add"
editButtonLabel="#{CmsArticleMessageBundle['basicproperties.title.edit']}" editButtonLabel="#{CmsArticleMessageBundle['basicproperties.title.edit']}"
editDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.title.edit.cancel']}" editDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.title.edit.cancel']}"
editDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.title.edit.submit']}" editDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.title.edit.submit']}"
editDialogTitle="#{CmsArticleMessageBundle['basicproperties.title.edit.header']}" editDialogTitle="#{CmsArticleMessageBundle['basicproperties.title.edit.header']}"
editDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.title.edit.value.help']}" editDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.title.edit.value.help']}"
editDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.title.edit.value.label']}" editDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.title.edit.value.label']}"
editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/title/@edit" editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/title/@edit"
editorId="title-editor" editorId="title-editor"
hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedTitleLocales.isEmpty()}" hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedTitleLocales.isEmpty()}"
headingLevel="3" headingLevel="3"
@ -95,7 +95,7 @@
removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.title.remove.submit']}" removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.title.remove.submit']}"
removeDialogText="#{CmsArticleMessageBundle['basicproperties.title.remove.text']}" removeDialogText="#{CmsArticleMessageBundle['basicproperties.title.remove.text']}"
removeDialogTitle="#{CmsArticleMessageBundle['basicproperties.title.remove.header']}" removeDialogTitle="#{CmsArticleMessageBundle['basicproperties.title.remove.header']}"
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/title/@remove" removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/title/@remove"
title="#{CmsArticleMessageBundle['basicproperties.title.header']}" title="#{CmsArticleMessageBundle['basicproperties.title.header']}"
unusedLocales="#{CmsArticlePropertiesStep.unusedTitleLocales}" unusedLocales="#{CmsArticlePropertiesStep.unusedTitleLocales}"
values="#{CmsArticlePropertiesStep.titleValues}" values="#{CmsArticlePropertiesStep.titleValues}"
@ -111,14 +111,14 @@
addDialogTitle="#{CmsArticleMessageBundle['basicproperties.description.add.header']}" addDialogTitle="#{CmsArticleMessageBundle['basicproperties.description.add.header']}"
addDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.description.add.value.help']}" addDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.description.add.value.help']}"
addDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.description.add.value.label']}" addDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.description.add.value.label']}"
addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/description/@add" addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/description/@add"
editButtonLabel="#{CmsArticleMessageBundle['basicproperties.description.edit']}" editButtonLabel="#{CmsArticleMessageBundle['basicproperties.description.edit']}"
editDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.description.edit.cancel']}" editDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.description.edit.cancel']}"
editDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.description.edit.submit']}" editDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.description.edit.submit']}"
editDialogTitle="#{CmsArticleMessageBundle['basicproperties.description.edit.header']}" editDialogTitle="#{CmsArticleMessageBundle['basicproperties.description.edit.header']}"
editDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.description.edit.value.help']}" editDialogValueHelp="#{CmsArticleMessageBundle['basicproperties.description.edit.value.help']}"
editDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.description.edit.value.label']}" editDialogValueLabel="#{CmsArticleMessageBundle['basicproperties.description.edit.value.label']}"
editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/description/@edit" editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/description/@edit"
editorId="description-editor" editorId="description-editor"
hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedDescriptionLocales.isEmpty()}" hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedDescriptionLocales.isEmpty()}"
headingLevel="3" headingLevel="3"
@ -128,7 +128,7 @@
removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.description.remove.submit']}" removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.description.remove.submit']}"
removeDialogText="#{CmsArticleMessageBundle['basicproperties.description.remove.text']}" removeDialogText="#{CmsArticleMessageBundle['basicproperties.description.remove.text']}"
removeDialogTitle="#{CmsArticleMessageBundle['basicproperties.description.remove.header']}" removeDialogTitle="#{CmsArticleMessageBundle['basicproperties.description.remove.header']}"
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/description/@remove" removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-basicproperties/description/@remove"
title="#{CmsArticleMessageBundle['basicproperties.description.header']}" title="#{CmsArticleMessageBundle['basicproperties.description.header']}"
unusedLocales="#{CmsArticlePropertiesStep.unusedDescriptionLocales}" unusedLocales="#{CmsArticlePropertiesStep.unusedDescriptionLocales}"
values="#{CmsArticlePropertiesStep.descriptionValues}" values="#{CmsArticlePropertiesStep.descriptionValues}"