PublishStep: Publishing works, unpublishing not, republishing not tested yet. Some finetuning is also required. Also not all error messages set by the controller are displayed yet.

pull/10/head
Jens Pelzetter 2021-08-07 19:49:23 +02:00
parent eb1f0b1cba
commit 9bded5ad64
6 changed files with 190 additions and 80 deletions

View File

@ -43,6 +43,7 @@ public class CmsMvcAuthoringSteps implements MvcAuthoringSteps {
ExampleAuthoringStep.class, ExampleAuthoringStep.class,
CategorizationStep.class, CategorizationStep.class,
MediaStep.class, MediaStep.class,
PublishStep.class,
RelatedInfoStep.class, RelatedInfoStep.class,
MvcArticlePropertiesStep.class, MvcArticlePropertiesStep.class,
MvcArticleTextBodyStep.class MvcArticleTextBodyStep.class

View File

@ -18,6 +18,7 @@
*/ */
package org.librecms.ui.contentsections.documents; package org.librecms.ui.contentsections.documents;
import org.libreccm.core.UnexpectedErrorException;
import org.librecms.ui.contentsections.ContentSectionNotFoundException; import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;
@ -36,6 +37,7 @@ 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.Optional; import java.util.Optional;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
@ -69,7 +71,7 @@ import javax.ws.rs.PathParam;
public class PublishStep extends AbstractMvcAuthoringStep { public class PublishStep extends AbstractMvcAuthoringStep {
private static final String TEMPLATE private static final String TEMPLATE
= "org/librecms/ui/documenttypes/publish.xhtml"; = "org/librecms/ui/contentsection/documents/publish.xhtml";
/** /**
* The path fragment of the publish step. * The path fragment of the publish step.
@ -110,23 +112,50 @@ public class PublishStep extends AbstractMvcAuthoringStep {
DocumentNotFoundException { DocumentNotFoundException {
super.init(); super.init();
publishStepModel.setAssignedLifecycleLabel( publishStepModel.setAvailableLifecycles(
Optional getContentSection()
.ofNullable(getDocument().getLifecycle()) .getLifecycleDefinitions()
.map(Lifecycle::getDefinition) .stream()
.map(LifecycleDefinition::getLabel) .map(this::buildLifecycleListEntry)
.map(globalizationHelper::getValueFromLocalizedString) .collect(Collectors.toList())
.orElse("")
); );
publishStepModel.setAssignedLifecycleDescription( final ContentItem document = getDocument();
Optional
.ofNullable(getDocument().getLifecycle()) if (itemManager.isLive(document)) {
.map(Lifecycle::getDefinition) final ContentItem live = itemManager
.map(LifecycleDefinition::getDescription) .getLiveVersion(document, document.getClass())
.map(globalizationHelper::getValueFromLocalizedString) .orElseThrow(
.orElse("") () -> new UnexpectedErrorException(
); String.format(
"ContentItem %s is reported as live by "
+ "ContentItemManager#isLive"
+ "but has no live version.",
document.getUuid()
)
)
);
publishStepModel.setAssignedLifecycleLabel(
Optional
.ofNullable(live.getLifecycle())
.map(Lifecycle::getDefinition)
.map(LifecycleDefinition::getLabel)
.map(globalizationHelper::getValueFromLocalizedString)
.orElse("")
);
publishStepModel.setAssignedLifecycleDescription(
Optional
.ofNullable(live.getLifecycle())
.map(Lifecycle::getDefinition)
.map(LifecycleDefinition::getDescription)
.map(globalizationHelper::getValueFromLocalizedString)
.orElse("")
);
} else {
publishStepModel.setAssignedLifecycleDescription("");
publishStepModel.setAssignedLifecycleLabel("");
}
publishStepModel.setLive(itemManager.isLive(getDocument())); publishStepModel.setLive(itemManager.isLive(getDocument()));
} }
@ -152,7 +181,18 @@ public class PublishStep extends AbstractMvcAuthoringStep {
if (itemPermissionChecker.canPublishItems(getDocument())) { if (itemPermissionChecker.canPublishItems(getDocument())) {
final String lifecycleDefUuid; final String lifecycleDefUuid;
if (itemManager.isLive(document)) { if (itemManager.isLive(document)) {
lifecycleDefUuid = document lifecycleDefUuid = itemManager
.getLiveVersion(document, document.getClass())
.orElseThrow(
() -> new UnexpectedErrorException(
String.format(
"ContentItem %s is reported as live by "
+ "ContentItemManager#isLive"
+ "but has no live version.",
document.getUuid()
)
)
)
.getLifecycle() .getLifecycle()
.getDefinition() .getDefinition()
.getUuid(); .getUuid();
@ -279,49 +319,54 @@ public class PublishStep extends AbstractMvcAuthoringStep {
final LocalDateTime startLocalDateTime = LocalDateTime.of( final LocalDateTime startLocalDateTime = LocalDateTime.of(
localStartDate, localStartTime localStartDate, localStartTime
); );
final Date startDateTime = Date.from( final Date startDateTime = Date.from(
startLocalDateTime.toInstant( startLocalDateTime.atZone(ZoneId.systemDefault())
ZoneOffset.from(startLocalDateTime) .toInstant()
)
); );
final LocalDate localEndDate; final Date endDateTime;
try { if (endDateParam == null || endDateParam.isBlank()) {
localEndDate = LocalDate.parse(endDateParam, isoDateFormatter); endDateTime = null;
} catch (DateTimeParseException ex) { } else {
models.put("invalidEndDate", true); final LocalDate localEndDate;
models.put("lifecycleDefinitionUuid", selectedLifecycleDefUuid); try {
models.put("startDate", startDateParam); localEndDate = LocalDate.parse(endDateParam, isoDateFormatter);
models.put("startTime", startTimeParam); } catch (DateTimeParseException ex) {
models.put("endDate", endDateParam); models.put("invalidEndDate", true);
models.put("endTime", endTimeParam); models.put("lifecycleDefinitionUuid", selectedLifecycleDefUuid);
models.put("startDate", startDateParam);
models.put("startTime", startTimeParam);
models.put("endDate", endDateParam);
models.put("endTime", endTimeParam);
return TEMPLATE; return TEMPLATE;
}
final LocalTime localEndTime;
try {
localEndTime = LocalTime.parse(endTimeParam, isoTimeFormatter);
} catch (DateTimeParseException ex) {
models.put("invalidEndTime", true);
models.put("lifecycleDefinitionUuid", selectedLifecycleDefUuid);
models.put("startDate", startDateParam);
models.put("startTime", startTimeParam);
models.put("endDate", endDateParam);
models.put("endTime", endTimeParam);
return TEMPLATE;
}
final LocalDateTime endLocalDateTime = LocalDateTime.of(
localEndDate, localEndTime
);
endDateTime = Date.from(
endLocalDateTime
.atZone(ZoneId.systemDefault())
.toInstant()
);
} }
final LocalTime localEndTime;
try {
localEndTime = LocalTime.parse(endTimeParam, isoTimeFormatter);
} catch (DateTimeParseException ex) {
models.put("invalidEndTime", true);
models.put("lifecycleDefinitionUuid", selectedLifecycleDefUuid);
models.put("startDate", startDateParam);
models.put("startTime", startTimeParam);
models.put("endDate", endDateParam);
models.put("endTime", endTimeParam);
return TEMPLATE;
}
final LocalDateTime endLocalDateTime = LocalDateTime.of(
localEndDate, localEndTime
);
final Date endDateTime = Date.from(
endLocalDateTime.toInstant(
ZoneOffset.from(endLocalDateTime)
)
);
if (!itemPermissionChecker.canPublishItems(document)) { if (!itemPermissionChecker.canPublishItems(document)) {
return documentUi.showAccessDenied( return documentUi.showAccessDenied(
getContentSection(), getContentSection(),
@ -333,7 +378,20 @@ public class PublishStep extends AbstractMvcAuthoringStep {
if (selectedLifecycleDefUuid.isEmpty()) { if (selectedLifecycleDefUuid.isEmpty()) {
if (itemManager.isLive(document)) { if (itemManager.isLive(document)) {
final LifecycleDefinition definition; final LifecycleDefinition definition;
definition = document.getLifecycle().getDefinition(); definition = itemManager
.getLiveVersion(document, document.getClass())
.orElseThrow(
() -> new UnexpectedErrorException(
String.format(
"ContentItem %s is reported as live by "
+ "ContentItemManager#isLive"
+ "but has no live version.",
document.getUuid()
)
)
)
.getLifecycle()
.getDefinition();
itemManager.publish( itemManager.publish(
document, definition, startDateTime, endDateTime document, definition, startDateTime, endDateTime
); );
@ -366,10 +424,8 @@ public class PublishStep extends AbstractMvcAuthoringStep {
* *
* @return A redirect to the publish step. * @return A redirect to the publish step.
*/ */
@MvcAuthoringAction( @POST
method = MvcAuthoringActionMethod.POST, @Path("/unpublish")
path = "/@unpublish"
)
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public String unpublish() { public String unpublish() {
final ContentItem document = getDocument(); final ContentItem document = getDocument();
@ -386,4 +442,23 @@ public class PublishStep extends AbstractMvcAuthoringStep {
return buildRedirectPathForStep(); return buildRedirectPathForStep();
} }
private LifecycleListEntry buildLifecycleListEntry(
final LifecycleDefinition definition
) {
final LifecycleListEntry entry = new LifecycleListEntry();
entry.setDescription(
globalizationHelper.getValueFromLocalizedString(
definition.getDescription()
)
);
entry.setLabel(
globalizationHelper.getValueFromLocalizedString(
definition.getLabel()
)
);
entry.setUuid(definition.getUuid());
return entry;
}
} }

View File

@ -20,6 +20,10 @@ package org.librecms.ui.contentsections.documents;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -50,7 +54,7 @@ public class PublishStepModel {
/** /**
* A list of the available lifecycles. * A list of the available lifecycles.
*/ */
private List<LifecycleListEntry> availableListcycles; private List<LifecycleListEntry> availableLivecycles;
/** /**
* 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
@ -99,18 +103,18 @@ public class PublishStepModel {
} }
public PublishStepModel() { public PublishStepModel() {
availableListcycles = new ArrayList<>(); availableLivecycles = new ArrayList<>();
phases = new ArrayList<>(); phases = new ArrayList<>();
} }
public List<LifecycleListEntry> getAvailableLifecycles() { public List<LifecycleListEntry> getAvailableLifecycles() {
return Collections.unmodifiableList(availableListcycles); return Collections.unmodifiableList(availableLivecycles);
} }
public void setAvailableLifecycles( public void setAvailableLifecycles(
final List<LifecycleListEntry> availableListcycles final List<LifecycleListEntry> availableListcycles
) { ) {
this.availableListcycles = new ArrayList<>(availableListcycles); this.availableLivecycles = new ArrayList<>(availableListcycles);
} }
public List<PhaseListEntry> getPhases() { public List<PhaseListEntry> getPhases() {
@ -121,4 +125,20 @@ public class PublishStepModel {
this.phases = new ArrayList<>(phases); this.phases = new ArrayList<>(phases);
} }
public String getToday() {
return LocalDateTime
.now()
.format(DateTimeFormatter.ISO_DATE.withZone(ZoneId.systemDefault()));
}
public String getNow() {
return LocalTime
.now()
.format(
DateTimeFormatter
.ofPattern("HH:mm")
.withZone(ZoneId.systemDefault())
);
}
} }

View File

@ -4,20 +4,29 @@
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm" xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"> xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/librecms/ui/contentsection/documents/document.xhtml"> <ui:composition template="/WEB-INF/views/org/librecms/ui/contentsection/documents/authoringstep.xhtml">
<ui:param name="activePage" value="document" /> <!--<ui:param name="activePage" value="document" />-->
<ui:param name="authoringStep" value="publish" /> <ui:param name="authoringStep" value="publish" />
<ui:param name="title" value="#{CmsAdminMessages['contentsection.documents.publishstep.title']}" /> <!--<ui:param name="title" value="#{CmsAdminMessages['contentsection.documents.publishstep.title']}" />-->
<ui:define name="breadcrumb"> <!-- <ui:define name="breadcrumb">
<ui:include src="document-breadcrumbs.xhtml" /> <ui:include src="document-breadcrumbs.xhtml" />
<li aria-current="page" class="breadcrumb-item"> <li aria-current="page" class="breadcrumb-item">
#{CmsAdminMessages['contentsection.document.publishstep.title']} #{CmsAdminMessages['contentsection.document.publishstep.title']}
</li> </li>
</ui:define> </ui:define>-->
<!--<ui:define name="main">-->
<ui:define name="authoringStep">
<h1>#{CmsDefaultStepsMessageBundle.getMessage('publish.title', [CmsSelectedDocumentModel.itemTitle])}</h1>
<c:if test="#{missingLifecycleDefinitionUuid}">
<div class="alert alert-danger">
#{CmsDefaultStepsMessageBundle['publish.no_lifecycle_selected']}
</div>
</c:if>
<ui:define name="main">
<c:choose> <c:choose>
<c:when test="#{CmsDocumentPublishStepModel.live}"> <c:when test="#{CmsDocumentPublishStepModel.live}">
<h2> <h2>
@ -29,7 +38,8 @@
</p> </p>
<div class="d-flex"> <div class="d-flex">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringSteps/publish/@publish" <form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@publish"
class="mr-3"
method="post"> method="post">
<button class="btn btn-primary" <button class="btn btn-primary"
type="submit"> type="submit">
@ -37,7 +47,7 @@
</button> </button>
</form> </form>
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringSteps/publish/@unpublish" <form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@publish/unpublish"
method="post"> method="post">
<button class="btn btn-warning" <button class="btn btn-warning"
type="submit"> type="submit">
@ -47,7 +57,7 @@
</div> </div>
</c:when> </c:when>
<c:otherwise> <c:otherwise>
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringSteps/publish/@publish" <form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@publish"
method="post"> method="post">
<div class="form-group"> <div class="form-group">
@ -83,7 +93,8 @@
id="lifecycle-startdate" id="lifecycle-startdate"
name="startDate" name="startDate"
required="true" required="true"
type="date" /> type="date"
value="#{CmsDocumentPublishStepModel.today}" />
<label for="starttime"> <label for="starttime">
${CmsDefaultStepsMessageBundle['publishstep.lifecycle_starttime.label']} ${CmsDefaultStepsMessageBundle['publishstep.lifecycle_starttime.label']}
@ -92,7 +103,8 @@
id="lifecycle-starttime" id="lifecycle-starttime"
name="startTime" name="startTime"
required="true" required="true"
type="date" /> type="time"
value="#{CmsDocumentPublishStepModel.now}" />
</div> </div>
<small class="form-text text-muted" <small class="form-text text-muted"
@ -110,7 +122,6 @@
<input class="form-control" <input class="form-control"
id="lifecycle-enddate" id="lifecycle-enddate"
name="endDate" name="endDate"
required="true"
type="date" /> type="date" />
<label for="endtime"> <label for="endtime">
@ -119,8 +130,7 @@
<input class="form-control" <input class="form-control"
id="lifecycle-endtime" id="lifecycle-endtime"
name="endTime" name="endTime"
required="true" type="time" />
type="date" />
</div> </div>
<small class="form-text text-muted" <small class="form-text text-muted"

View File

@ -20,7 +20,7 @@ publishstep.lifecycle_starttime.label=Start Time
publishstep.lifecycle_startdatetime.help=Date and time of the begin of the lifecycle. publishstep.lifecycle_startdatetime.help=Date and time of the begin of the lifecycle.
publishstep.lifecycle_enddate.label=End Date publishstep.lifecycle_enddate.label=End Date
publishstep.lifecycle_endtime.label=End Time publishstep.lifecycle_endtime.label=End Time
publishstep.lifecycle.publish=Date and time of the end of the lifecycle (optional). publishstep.lifecycle.publish=Publish
relatedinfo.asset.not_found.title=Asset not found relatedinfo.asset.not_found.title=Asset not found
contentsection.document.relatedinfo.breadcrumb=Related Information contentsection.document.relatedinfo.breadcrumb=Related Information
relatedinfo.asset.not_found.message=No asset {1} found in Content Section {0}. relatedinfo.asset.not_found.message=No asset {1} found in Content Section {0}.
@ -337,3 +337,5 @@ media.medialist.not_found.title=Media List not found
media.medialist.not_found.message=Content Item {0} has not media list {1}. media.medialist.not_found.message=Content Item {0} has not media list {1}.
media.title=Media for Content Item {0} media.title=Media for Content Item {0}
relatedinfo.title=Related Info for Content Item {0} relatedinfo.title=Related Info for Content Item {0}
publish.title=Publish Content Item {0}
publishstep.lifecycle_enddatetime.help=Date and time of the end of the lifecycle (optional).

View File

@ -20,7 +20,7 @@ publishstep.lifecycle_starttime.label=Beginn (Uhrzeit)
publishstep.lifecycle_startdatetime.help=Datum und Uhrzeit des Beginns des Lebenszylus publishstep.lifecycle_startdatetime.help=Datum und Uhrzeit des Beginns des Lebenszylus
publishstep.lifecycle_enddate.label=Ende (Datum) publishstep.lifecycle_enddate.label=Ende (Datum)
publishstep.lifecycle_endtime.label=Ende (Uhrzeit) publishstep.lifecycle_endtime.label=Ende (Uhrzeit)
publishstep.lifecycle.publish=Datum und Uhrzeit des Endes des Lebenszyklus (optional). publishstep.lifecycle.publish=Publizieren
relatedinfo.asset.not_found.title=Asset nicht gefunden relatedinfo.asset.not_found.title=Asset nicht gefunden
contentsection.document.relatedinfo.breadcrumb=Weiterf\u00fchrende Informationen contentsection.document.relatedinfo.breadcrumb=Weiterf\u00fchrende Informationen
relatedinfo.asset.not_found.message=Es wurde kein Asset {1} in der Content Section {0} gefunden. relatedinfo.asset.not_found.message=Es wurde kein Asset {1} in der Content Section {0} gefunden.
@ -337,3 +337,5 @@ media.medialist.not_found.title=Medienliste nicht gefunden
media.medialist.not_found.message=Keine Medienliste {1} f\u00fcr Dokument {0} gefunden. media.medialist.not_found.message=Keine Medienliste {1} f\u00fcr Dokument {0} gefunden.
media.title=Medien f\u00fcr Dokument {0} media.title=Medien f\u00fcr Dokument {0}
relatedinfo.title=Weiterf\u00fchrende Informationen f\u00fcr Dokument {0} relatedinfo.title=Weiterf\u00fchrende Informationen f\u00fcr Dokument {0}
publish.title=Dokument {0} publizieren
publishstep.lifecycle_enddatetime.help=Datum und Uhrzeit des Endes des Lebenszyklus (optional).