New annotations for authoring steps

pull/10/head
Jens Pelzetter 2021-04-20 20:05:48 +02:00
parent 5239c601a8
commit a31e242c48
9 changed files with 367 additions and 84 deletions

View File

@ -43,6 +43,7 @@ import org.librecms.ui.contenttypes.MvcArticleCreateStep;
import org.librecms.ui.contenttypes.MvcArticlePropertiesStep; import org.librecms.ui.contenttypes.MvcArticlePropertiesStep;
import org.librecms.ui.contenttypes.MvcArticleTextBodyStep; import org.librecms.ui.contenttypes.MvcArticleTextBodyStep;
import org.librecms.ui.contentsections.documents.MvcAuthoringKit; import org.librecms.ui.contentsections.documents.MvcAuthoringKit;
import org.librecms.ui.contentsections.documents.MvcAuthoringKitStep;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
@ -78,8 +79,14 @@ import javax.xml.bind.annotation.XmlRootElement;
@MvcAuthoringKit( @MvcAuthoringKit(
createStep = MvcArticleCreateStep.class, createStep = MvcArticleCreateStep.class,
authoringSteps = { authoringSteps = {
MvcArticlePropertiesStep.class, @MvcAuthoringKitStep(
MvcArticleTextBodyStep.class path = "basic-properties",
authoringStep = MvcArticlePropertiesStep.class
),
@MvcAuthoringKitStep(
path = "basic-properties",
authoringStep = MvcArticleTextBodyStep.class
)
} }
) )
@XmlRootElement(name = "article", namespace = CMS_XML_NS) @XmlRootElement(name = "article", namespace = CMS_XML_NS)

View File

@ -0,0 +1,133 @@
/*
* 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;
import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentSection;
import org.librecms.ui.contentsections.documents.MvcAuthoringStep;
import java.util.Map;
import java.util.Objects;
import javax.inject.Inject;
import javax.mvc.Models;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
@Inject
private ContentItemManager itemManager;
@Inject
private GlobalizationHelper globalizationHelper;
@Inject
private Models models;
private ContentSection section;
private ContentItem document;
@Override
public ContentSection getContentSection() {
return section;
}
@Override
public void setContentSection(final ContentSection section) {
this.section = section;
}
@Override
public String getContentSectionLabel() {
return section.getLabel();
}
@Override
public String getContentSectionTitle() {
return globalizationHelper
.getValueFromLocalizedString(section.getTitle());
}
@Override
public ContentItem getContentItem() {
return document;
}
@Override
public void setContentItem(final ContentItem document) {
this.document = document;
}
@Override
public String getContentItemPath() {
return itemManager.getItemPath(document);
}
@Override
public String getContentItemTitle() {
return globalizationHelper
.getValueFromLocalizedString(document.getTitle());
}
protected boolean hasParameter(
final Map<String, String[]> parameters,
final String parameterName
) {
Objects.requireNonNull(
parameters,
"parameters can't be null."
);
Objects.requireNonNull(
parameterName,
"parameterName can't be null."
);
return parameters.containsKey(parameterName)
&& parameters.get(parameterName) != null
&& parameters.get(parameterName).length != 0;
}
/**
* Helper method to add a form parameter value to {@link #models}.
*
* @param parameters The form parameters.
* @param parameterName The parameter name
*/
protected void addParameterValueToModels(
final Map<String, String[]> parameters,
final String parameterName
) {
models.put(
Objects.requireNonNull(
parameterName,
"parameterName can't be null"
),
Objects.requireNonNull(
parameters,
"parameters can't be null."
).getOrDefault(parameterName, new String[]{""})[0]
);
}
}

View File

@ -308,7 +308,6 @@ public class DocumentController {
sectionIdentifier, sectionIdentifier,
"", "",
documentType, documentType,
//formParameters
request request
); );
} }
@ -327,7 +326,8 @@ public class DocumentController {
) { ) {
final CreateStepResult result = findCreateStep( final CreateStepResult result = findCreateStep(
sectionIdentifier, sectionIdentifier,
folderPath, documentType folderPath,
documentType
); );
if (result.isCreateStepAvailable()) { if (result.isCreateStepAvailable()) {

View File

@ -0,0 +1,74 @@
/*
* 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 java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MediaType;
/**
* Used to annotate methods of an authoring step processing requests for a
* specific sub path. The annoated MUST have the following signature:
*
* <pre>
* actionMethod(String parameterPath, Map<String, String[]> parameters)
* </pre>
*
* The {@link DocumentController} will put the rest of the path behind the path
* fragments for the action in the {@code parameterPath} parameter. The
* parameter {@code parameters} will contain the list of parameters for the
* request as returned by {@link HttpServletRequest#getParameterMap() }.
*
* The return type of the annotated method MUST be {@code String} if the action
* is showing a template ({@link #produces()} is set to
* {@link MediaType#TEXT_HTML}), or any object type is {@link #produces() } is
* set the {@link MediaType#APPLICATION_JSON}.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface MvcAuthoringAction {
/**
* The HTTP method used to invoke the action.
*
* @return The HTTP method used to invoke the action.
*/
MvcAuthoringActionMethod method() default MvcAuthoringActionMethod.GET;
/**
* The path fragment for invoking the action. The value of this parameter is
* added to the path of the authoring step.
*
* @return The path fragment for invoking the action.
*/
String path();
/**
* The type of data the the action produces. If the action shows a view the
* value should be {@link MediaType#TEXT_HTML} (the default). If the action
* produces JSON data the value MUST BE {@link MediaType#APPLICATION_JSON}.
*
* @return The type of data the the action produces.
*/
String produces() default MediaType.TEXT_HTML;
}

View File

@ -0,0 +1,31 @@
/*
* 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;
/**
* Request methods for {@link MvcAuthoringAction}s.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public enum MvcAuthoringActionMethod {
GET,
POST
}

View File

@ -47,10 +47,9 @@ public @interface MvcAuthoringKit {
* The authoring steps for editing the properties of the document. They are * The authoring steps for editing the properties of the document. They are
* used in the same order as they are provided here. * used in the same order as they are provided here.
* *
* @return The descriptor classes ofr the authoring steps for the annotated * @return The authoring steps for the annotated document type.
* document type.
*/ */
Class<? extends MvcAuthoringStep>[] authoringSteps(); MvcAuthoringKitStep[] authoringSteps();
/** /**
* If set to {@code true} some authoring steps like categorization or * If set to {@code true} some authoring steps like categorization or

View File

@ -0,0 +1,47 @@
/*
* 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 java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Metadata about an authoring step.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface MvcAuthoringKitStep {
/**
* The path of authoring step. This value is added the the path for
* authoring steps.
*
* @return The path fragment for th authoring step.
*/
String path();
/**
* The class implementing the authoring step.
*
* @return The class implementing the authoring step.
*/
Class<? extends MvcAuthoringStep> authoringStep();
}

View File

@ -22,10 +22,9 @@ import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import java.util.Map;
import javax.inject.Named; import javax.inject.Named;
import javax.transaction.Transactional;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
/** /**
* An authoring step for a document (content item). Implementing classes are * An authoring step for a document (content item). Implementing classes are
@ -139,9 +138,17 @@ public interface MvcAuthoringStep {
* *
* @return The template of the edit step. * @return The template of the edit step.
*/ */
@GET
@Path("/")
@Transactional(Transactional.TxType.REQUIRED)
String showStep(); String showStep();
/**
* Apply changes from the from of the script.Authoring steps that have
* multiple forms may choose to implement this method as any no-op method
* that simply redirects to the template view (same as {@link #showStep()}.
*
* @param formParameters The form parameters submitted.
*
* @return The template of the view to show.
*/
String applyEdits(Map<String, String[]> formParameters);
} }

View File

@ -19,12 +19,14 @@
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.AuthorizationRequired;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.lifecycle.Lifecycle; import org.librecms.lifecycle.Lifecycle;
import org.librecms.lifecycle.LifecycleDefinition; import org.librecms.lifecycle.LifecycleDefinition;
import org.librecms.lifecycle.LifecycleDefinitionRepository; import org.librecms.lifecycle.LifecycleDefinitionRepository;
import org.librecms.ui.contentsections.AbstractMvcAuthoringStep;
import org.librecms.ui.contentsections.ItemPermissionChecker; import org.librecms.ui.contentsections.ItemPermissionChecker;
import java.time.LocalDate; import java.time.LocalDate;
@ -35,6 +37,7 @@ import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.util.Date; import java.util.Date;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
@ -57,7 +60,19 @@ import javax.ws.rs.Path;
@Path("/") @Path("/")
@AuthoringStepPathFragment(PublishStep.PATH_FRAGMENT) @AuthoringStepPathFragment(PublishStep.PATH_FRAGMENT)
@Named("CmsPublishStep") @Named("CmsPublishStep")
public class PublishStep implements MvcAuthoringStep { public class PublishStep extends AbstractMvcAuthoringStep {
private static final String SELECTED_LIFECYCLE_DEF_UUID
= "selectedLifecycleDefUuid";
private static final String START_DATE = "startDate";
private static final String START_TIME = "startTime";
private static final String END_DATE = "endDate";
private static final String END_TIME = "endTime";
/** /**
* The path fragment of the publish step. * The path fragment of the publish step.
@ -85,9 +100,6 @@ public class PublishStep implements MvcAuthoringStep {
@Inject @Inject
private Models models; private Models models;
private ContentItem document;
private ContentSection section;
@Override @Override
public Class<? extends ContentItem> supportedDocumentType() { public Class<? extends ContentItem> supportedDocumentType() {
@ -113,59 +125,19 @@ public class PublishStep implements MvcAuthoringStep {
return DefaultAuthoringStepConstants.BUNDLE; return DefaultAuthoringStepConstants.BUNDLE;
} }
@Override
public ContentSection getContentSection() {
return section;
}
@Override
public void setContentSection(final ContentSection section) {
this.section = section;
}
@Override
public String getContentSectionLabel() {
return section.getLabel();
}
@Override
public String getContentSectionTitle() {
return globalizationHelper
.getValueFromLocalizedString(section.getTitle());
}
@Override
public ContentItem getContentItem() {
return document;
}
@Override
public void setContentItem(final ContentItem document) {
this.document = document;
}
@Override
public String getContentItemPath() {
return itemManager.getItemPath(document);
}
@Override
public String getContentItemTitle() {
return globalizationHelper
.getValueFromLocalizedString(document.getTitle());
}
@Override @Override
public String showStep() { public String showStep() {
if (itemPermissionChecker.canPublishItems(document)) { if (itemPermissionChecker.canPublishItems(getContentItem())) {
final String lifecycleDefUuid; final String lifecycleDefUuid;
if (itemManager.isLive(document)) { if (itemManager.isLive(getContentItem())) {
lifecycleDefUuid = document lifecycleDefUuid = getContentItem()
.getLifecycle() .getLifecycle()
.getDefinition() .getDefinition()
.getUuid(); .getUuid();
} else { } else {
lifecycleDefUuid = document lifecycleDefUuid = getContentItem()
.getContentType() .getContentType()
.getDefaultLifecycle() .getDefaultLifecycle()
.getUuid(); .getUuid();
@ -174,8 +146,8 @@ public class PublishStep implements MvcAuthoringStep {
return "org/librecms/ui/documents/publish.xhtml"; return "org/librecms/ui/documents/publish.xhtml";
} else { } else {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
section, getContentSection(),
document, getContentItem(),
defaultStepsMessageBundle.getMessage( defaultStepsMessageBundle.getMessage(
"access_to_authoringstep_denied", new String[]{getLabel()} "access_to_authoringstep_denied", new String[]{getLabel()}
) )
@ -183,14 +155,28 @@ public class PublishStep implements MvcAuthoringStep {
} }
} }
/** @AuthorizationRequired
* Is the current document live? @Transactional(Transactional.TxType.REQUIRED)
* @Override
* @return public String applyEdits(final Map<String, String[]> formParameters) {
*/ if (!formParameters.containsKey(SELECTED_LIFECYCLE_DEF_UUID)
public boolean isLive() { || formParameters.get(SELECTED_LIFECYCLE_DEF_UUID) == null
return itemManager.isLive(document); || formParameters.get(SELECTED_LIFECYCLE_DEF_UUID).length == 0) {
if (!formParameters.containsKey(SELECTED_LIFECYCLE_DEF_UUID)
|| formParameters.get(SELECTED_LIFECYCLE_DEF_UUID) == null
|| formParameters.get(SELECTED_LIFECYCLE_DEF_UUID).length == 0) {
models.put("missingLifecycleDefinitionUuid", true);
addParameterValueToModels(formParameters, START_DATE);
addParameterValueToModels(formParameters, START_TIME);
addParameterValueToModels(formParameters, END_DATE);
addParameterValueToModels(formParameters, END_TIME);
return "org/librecms/ui/documenttypes/publish.xhtml";
} }
}
}
/** /**
* Get the label of the lifecycle assigned to the current content item. The * Get the label of the lifecycle assigned to the current content item. The
@ -204,7 +190,7 @@ public class PublishStep implements MvcAuthoringStep {
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String getAssignedLifecycleLabel() { public String getAssignedLifecycleLabel() {
return Optional return Optional
.ofNullable(document.getLifecycle()) .ofNullable(getContentItem().getLifecycle())
.map(Lifecycle::getDefinition) .map(Lifecycle::getDefinition)
.map(LifecycleDefinition::getLabel) .map(LifecycleDefinition::getLabel)
.map(globalizationHelper::getValueFromLocalizedString) .map(globalizationHelper::getValueFromLocalizedString)
@ -224,7 +210,7 @@ public class PublishStep implements MvcAuthoringStep {
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String getAssignedLifecycleDecription() { public String getAssignedLifecycleDecription() {
return Optional return Optional
.ofNullable(document.getLifecycle()) .ofNullable(getContentItem().getLifecycle())
.map(Lifecycle::getDefinition) .map(Lifecycle::getDefinition)
.map(LifecycleDefinition::getDescription) .map(LifecycleDefinition::getDescription)
.map(globalizationHelper::getValueFromLocalizedString) .map(globalizationHelper::getValueFromLocalizedString)
@ -247,16 +233,14 @@ public class PublishStep implements MvcAuthoringStep {
* *
* @return A redirect the the publish step. * @return A redirect the the publish step.
*/ */
@POST @MvcAuthoringAction(
@Path("/@publish") method = MvcAuthoringActionMethod.POST,
path = "/@publish"
)
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String publish( public String publish(
@FormParam("selectedLifecycleDefUuid") final String parameterPath,
final String selectedLifecycleDefUuid, final Map<String, String[]> parameters
@FormParam("startDate") final String startDateParam,
@FormParam("startTime") final String startTimeParam,
@FormParam("endDate") final String endDateParam,
@FormParam("endTime") final String endTimeParam
) { ) {
if (selectedLifecycleDefUuid == null) { if (selectedLifecycleDefUuid == null) {
models.put("missingLifecycleDefinitionUuid", true); models.put("missingLifecycleDefinitionUuid", true);
@ -421,4 +405,5 @@ public class PublishStep implements MvcAuthoringStep {
); );
} }
} }