Some bugfixes

pull/10/head
Jens Pelzetter 2021-12-21 20:55:12 +01:00
parent 4ef2b9ac8a
commit 6f026f99a7
13 changed files with 251 additions and 72 deletions

View File

@ -55,8 +55,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -736,6 +734,74 @@ public class DocumentFolderController {
); );
} }
/**
* Deletes an empty folder.
*
* @param sectionIdentifier The identifier of the content section
* @param folderPath The path of the folder.
*
* @return A redirect to the parent folder.
*/
@POST
@Path("/@delete/{folderPath:(.+)?}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String deleteFolder(
@PathParam("sectionIdentifier") final String sectionIdentifier,
@PathParam("folderPath") final String folderPath
) {
final Optional<ContentSection> sectionResult = sectionsUi
.findContentSection(sectionIdentifier);
if (!sectionResult.isPresent()) {
return sectionsUi.showContentSectionNotFound(sectionIdentifier);
}
final ContentSection section = sectionResult.get();
if (!itemPermissionChecker.canEditItems(section)) {
return sectionsUi.showAccessDenied(
"sectionidentifier", sectionIdentifier
);
}
final Folder folder;
final Optional<Folder> folderResult = folderRepo
.findByPath(
section,
folderPath,
FolderType.DOCUMENTS_FOLDER
);
if (folderResult.isPresent()) {
folder = folderResult.get();
documentFolderModel.setBreadcrumbs(buildBreadcrumbs(folderPath));
} else {
return showDocumentFolderNotFound(section, folderPath);
}
if (!itemPermissionChecker.canDeleteItems(folder)) {
return sectionsUi.showAccessDenied(
"sectionidentifier", sectionIdentifier,
"folderPath", folderPath
);
}
final String parentFolderPath = Optional
.ofNullable(folder.getParentFolder())
.map(folderManager::getFolderPath)
.orElse("");
if (folderManager.folderIsDeletable(folder)
== FolderManager.FolderIsDeletable.YES) {
folderManager.deleteFolder(folder);
}
return String.format(
"redirect:/%s/documentfolders/%s",
sectionIdentifier,
parentFolderPath
);
}
/** /**
* A helper method for building the breadcrumb trail of a folder. * A helper method for building the breadcrumb trail of a folder.
* *

View File

@ -25,6 +25,8 @@ import org.librecms.ui.contentsections.documents.relatedinfo.RelatedInfoStepServ
import org.librecms.ui.contenttypes.article.MvcArticlePropertiesStep; import org.librecms.ui.contenttypes.article.MvcArticlePropertiesStep;
import org.librecms.ui.contenttypes.article.MvcArticleTextBodyStep; import org.librecms.ui.contenttypes.article.MvcArticleTextBodyStep;
import org.librecms.ui.contenttypes.article.MvcArticleTextBodyStepResources; import org.librecms.ui.contenttypes.article.MvcArticleTextBodyStepResources;
import org.librecms.ui.contenttypes.mpa.MvcMpaPropertiesStep;
import org.librecms.ui.contenttypes.mpa.MvcMpaSectionsStep;
import java.util.Set; import java.util.Set;
@ -46,7 +48,9 @@ public class CmsMvcAuthoringSteps implements MvcAuthoringSteps {
PublishStep.class, PublishStep.class,
RelatedInfoStep.class, RelatedInfoStep.class,
MvcArticlePropertiesStep.class, MvcArticlePropertiesStep.class,
MvcArticleTextBodyStep.class MvcArticleTextBodyStep.class,
MvcMpaPropertiesStep.class,
MvcMpaSectionsStep.class
); );
} }

View File

@ -26,6 +26,7 @@ import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder; import org.librecms.contentsection.Folder;
import org.librecms.contentsection.FolderManager;
import org.librecms.contentsection.FolderRepository; import org.librecms.contentsection.FolderRepository;
import org.librecms.contentsection.FolderType; import org.librecms.contentsection.FolderType;
import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges;
@ -99,6 +100,9 @@ public class DocumentController {
@Inject @Inject
private DocumentUi documentUi; private DocumentUi documentUi;
@Inject
private FolderManager folderManager;
/** /**
* {@link FolderRepository} instance for retrieving folders. * {@link FolderRepository} instance for retrieving folders.
*/ */
@ -766,6 +770,57 @@ public class DocumentController {
); );
} }
/**
* Deletes a document.
*
* @param sectionIdentifier
* @param documentPath
*
* @return A redirect to the folder of the document.
*/
@POST
@Path("/{documentPath:(.+)?}/@delete")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String deleteDocument(
@PathParam("sectionIdentifier") final String sectionIdentifier,
@PathParam("documentPath") final String documentPath
) {
final Optional<ContentSection> sectionResult = sectionsUi
.findContentSection(sectionIdentifier);
if (!sectionResult.isPresent()) {
return sectionsUi.showContentSectionNotFound(sectionIdentifier);
}
final ContentSection section = sectionResult.get();
final Optional<ContentItem> itemResult = itemRepo
.findByPath(section, documentPath);
if (!itemResult.isPresent()) {
return documentUi.showDocumentNotFound(section, documentPath);
}
final ContentItem item = itemResult.get();
if (!permissionChecker.isPermitted(ItemPrivileges.DELETE, item)) {
return sectionsUi.showAccessDenied(
"sectionIdentifier", sectionIdentifier,
"documentPath", documentPath
);
}
final String folderPath = itemManager
.getItemFolder(item)
.map(folderManager::getFolderPath)
.orElse("");
if (!itemManager.isLive(item)) {
itemRepo.delete(item);
}
return String.format(
"redirect:/%s/documentfolders/%s",
sectionIdentifier,
folderPath
);
}
/** /**
* Helper method for reading the authoring steps for the current content * Helper method for reading the authoring steps for the current content
* item. * item.

View File

@ -63,4 +63,7 @@ public class MpaSectionsStepModel {
this.sections = new ArrayList<>(sections); this.sections = new ArrayList<>(sections);
} }
public boolean getSectionsEmpty() {
return sections.isEmpty();
}
} }

View File

@ -382,11 +382,33 @@
</td> </td>
<td> <td>
<c:if test="#{row.deletable}"> <c:if test="#{row.deletable}">
<button class="btn btn-danger" <c:choose>
title="#{CmsAdminMessages['contentsection.documentfolder.actions.delete.button.label']}"> <c:when test="#{row.folder}">
<bootstrap:svgIcon icon="x-circle" /> <libreccm:deleteDialog
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.actions.delete.button.label']}</span> actionTarget="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/@delete/#{row.folderPath}"
</button> buttonLabelClass="sr-only"
buttonText="#{CmsAdminMessages['contentsection.documentfolder.actions.delete.button.label']}"
cancelLabel="#{CmsAdminMessages['contentsection.documentfolder.actions.delete.cancel']}"
confirmLabel="#{CmsAdminMessages['contentsection.documentfolder.actions.delete.confirm']}"
dialogId="delete-folder-#{row.name}"
dialogTitle="#{CmsAdminMessages['contentsection.documentfolder.actions.delete.dialog.title']}"
message="#{CmsAdminMessages.getMessage('contentsection.documentfolder.actions.delete.dialog.message', [row.folderPath])}"
/>
</c:when>
<c:otherwise>
<libreccm:deleteDialog
actionTarget="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{DocumentFolderModel.pathWithTrailingSlash}#{row.name}/@delete"
buttonLabelClass="sr-only"
buttonText="#{CmsAdminMessages['contentsection.documentfolder.actions.delete_item.button.label']}"
cancelLabel="#{CmsAdminMessages['contentsection.documentfolder.actions.delete_item.cancel']}"
confirmLabel="#{CmsAdminMessages['contentsection.documentfolder.actions.delete_item.confirm']}"
dialogId="delete-folder-#{row.name}"
dialogTitle="#{CmsAdminMessages['contentsection.documentfolder.actions.delete_item.dialog.title']}"
message="#{CmsAdminMessages.getMessage('contentsection.documentfolder.actions.delete_item.dialog.message', [row.folderPath, row.name])}"
/>
</c:otherwise>
</c:choose>
</c:if> </c:if>
</td> </td>
</tr> </tr>

View File

@ -11,7 +11,7 @@
value="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@mpa-sections" /> value="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@mpa-sections" />
<ui:define name="authoringStep"> <ui:define name="authoringStep">
<h2>#{CmsMpaMessageBundle.getMessage('sectionsstep.header', CmsMpaSectionsStep.articleTitle)}</h2> <h2>#{CmsMpaMessageBundle.getMessage('sectionsstep.header', [CmsMpaSectionsStep.articleTitle])}</h2>
<c:if test="#{CmsMpaSectionsStep.canEdit}"> <c:if test="#{CmsMpaSectionsStep.canEdit}">
<div class="text-right"> <div class="text-right">
@ -95,6 +95,13 @@
</div> </div>
</div> </div>
</c:if> </c:if>
<c:choose>
<c:when test="#{CmsMpaSectionsStep.sectionsEmpty}">
<p>
#{CmsMpaMessageBundle['sectionsstep.sections.empty']}
</p>
</c:when>
<c:otherwise>
<table> <table>
<thead> <thead>
<tr> <tr>
@ -149,6 +156,8 @@
</c:forEach> </c:forEach>
</tbody> </tbody>
</table> </table>
</c:otherwise>
</c:choose>
</ui:define> </ui:define>

View File

@ -1014,3 +1014,12 @@ contentsection.document.authoring.workflow.none=No workflow assigned
contentsection.document.authoring.workflow.change_workflow.title=Assign workflow contentsection.document.authoring.workflow.change_workflow.title=Assign workflow
contentsection.document.authoring.workflow.change_workflow.submit=Assign workflow contentsection.document.authoring.workflow.change_workflow.submit=Assign workflow
contentsection.document.authoring.workflow.change_workflow.close=Cancel contentsection.document.authoring.workflow.change_workflow.close=Cancel
contentsection.documentfolder.actions.delete.cancel=Cancel
contentsection.documentfolder.actions.delete.confirm=Delete folder
contentsection.documentfolder.actions.delete.dialog.title=Confirm deletion of folder
contentsection.documentfolder.actions.delete.dialog.message=Are you sure to delete the folder {0}?
contentsection.documentfolder.actions.delete_item.button.label=Delete document
contentsection.documentfolder.actions.delete_item.cancel=Cancel
contentsection.documentfolder.actions.delete_item.confirm=Delete document
contentsection.documentfolder.actions.delete_item.dialog.title=Confirm deletation of document
contentsection.documentfolder.actions.delete_item.dialog.message=Are you sure to delete the document {0}/{1}?

View File

@ -1015,3 +1015,12 @@ contentsection.document.authoring.workflow.none=Kein Arbeitsablauf zugewiesen
contentsection.document.authoring.workflow.change_workflow.title=Arbeitsablauf zuweisen contentsection.document.authoring.workflow.change_workflow.title=Arbeitsablauf zuweisen
contentsection.document.authoring.workflow.change_workflow.submit=Arbeitsablauf zuweisen contentsection.document.authoring.workflow.change_workflow.submit=Arbeitsablauf zuweisen
contentsection.document.authoring.workflow.change_workflow.close=Abbrechen contentsection.document.authoring.workflow.change_workflow.close=Abbrechen
contentsection.documentfolder.actions.delete.cancel=Abbrechen
contentsection.documentfolder.actions.delete.confirm=Ordner l\u00f6schen
contentsection.documentfolder.actions.delete.dialog.title=L\u00f6schen des Ordners best\u00e4tigen
contentsection.documentfolder.actions.delete.dialog.message=Are you sure to delete the folder {0}?
contentsection.documentfolder.actions.delete_item.button.label=Dokument l\u00f6schen
contentsection.documentfolder.actions.delete_item.cancel=Abbrechen
contentsection.documentfolder.actions.delete_item.confirm=Dokument l\u00f6schen
contentsection.documentfolder.actions.delete_item.dialog.title=L\u00f6schen des Dokumentes best\u00e4tigen
contentsection.documentfolder.actions.delete_item.dialog.message=Sind Sie sicher, dass Sie das Dokument {0}/{1} l\u00f6schen wollen?

View File

@ -90,7 +90,7 @@ textstep.languages.th.language=Language
textstep.languages.th.actions=Actions textstep.languages.th.actions=Actions
textstep.languages.none=No texts available textstep.languages.none=No texts available
textstep.header.edit=Edit text for locale {0} textstep.header.edit=Edit text for locale {0}
textstep.header.view=Text for locale {0} textstep.header.view=Text of Article {0} for locale {1}
textstep.back=Back to available languages textstep.back=Back to available languages
text.editor.add_variant=Add language text.editor.add_variant=Add language
text.editor.add.locale.help=The language of the new variant. text.editor.add.locale.help=The language of the new variant.

View File

@ -90,7 +90,7 @@ textstep.languages.th.language=Sprache
textstep.languages.th.actions=Aktionen textstep.languages.th.actions=Aktionen
textstep.languages.none=Keine Texte vorhandenen textstep.languages.none=Keine Texte vorhandenen
textstep.header.edit=Text f\u00fcr Sprache {0} bearbeiten textstep.header.edit=Text f\u00fcr Sprache {0} bearbeiten
textstep.header.view=Text f\u00fcr Sprache {0} textstep.header.view=Text des Artikels {0} f\u00fcr Sprache {1}
textstep.back=Zur\u00fcck zur Liste der verf\u00fcgbaren Sprachen textstep.back=Zur\u00fcck zur Liste der verf\u00fcgbaren Sprachen
text.editor.add_variant=Sprache hinzuf\u00fcgen text.editor.add_variant=Sprache hinzuf\u00fcgen
text.editor.add.locale.help=Die Sprache der neuen Variante. text.editor.add.locale.help=Die Sprache der neuen Variante.

View File

@ -113,3 +113,4 @@ sectionstep.textstep.back=Back
sectionstep.textstep.header.edit=Edit text for locale {2} of section {1} of multipart article {0} sectionstep.textstep.header.edit=Edit text for locale {2} of section {1} of multipart article {0}
sectionstep.textstep.text.editor.header=Text sectionstep.textstep.text.editor.header=Text
authoringsteps.sections.label=Sections authoringsteps.sections.label=Sections
sectionsstep.sections.empty=This multipart article has no sections yet.

View File

@ -113,3 +113,4 @@ sectionstep.textstep.back=Zur\u00fcck
sectionstep.textstep.header.edit=Text f\u00fcr Sprache {2} des Abschnitts {1} des mehrteiligen Artikels {0} bearbeiten sectionstep.textstep.header.edit=Text f\u00fcr Sprache {2} des Abschnitts {1} des mehrteiligen Artikels {0} bearbeiten
sectionstep.textstep.text.editor.header=Text sectionstep.textstep.text.editor.header=Text
authoringsteps.sections.label=Abschnitte authoringsteps.sections.label=Abschnitte
sectionsstep.sections.empty=Diese mehrteilige Artikel hat noch keine Abschnitte.