ArticleTextBodyStep UI mostly works
parent
b526f9eac2
commit
62d98af857
|
|
@ -74,6 +74,7 @@ public class ContentSectionApplication extends Application {
|
||||||
classes.add(DocumentWorkflowController.class);
|
classes.add(DocumentWorkflowController.class);
|
||||||
|
|
||||||
classes.addAll(getAuthoringSteps());
|
classes.addAll(getAuthoringSteps());
|
||||||
|
classes.addAll(getAuthoringStepResources());
|
||||||
|
|
||||||
classes.add(IsAuthenticatedFilter.class);
|
classes.add(IsAuthenticatedFilter.class);
|
||||||
|
|
||||||
|
|
@ -89,4 +90,12 @@ public class ContentSectionApplication extends Application {
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<Class<?>> getAuthoringStepResources() {
|
||||||
|
return authoringSteps
|
||||||
|
.stream()
|
||||||
|
.map(MvcAuthoringSteps::getResourceClasses)
|
||||||
|
.flatMap(Set::stream)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ package org.librecms.ui.contentsections.documents;
|
||||||
|
|
||||||
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.contenttypes.MvcArticleTextBodyStepResources;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -46,4 +47,12 @@ public class CmsMvcAuthoringSteps implements MvcAuthoringSteps {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Class<?>> getResourceClasses() {
|
||||||
|
final Set<Class<?>> classes = new HashSet<>();
|
||||||
|
classes.add(MvcArticleTextBodyStepResources.class);
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,12 @@ import javax.ws.rs.Path;
|
||||||
*/
|
*/
|
||||||
public interface MvcAuthoringStep {
|
public interface MvcAuthoringStep {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the class implementing the step. This method is used by CCM is to
|
||||||
|
* get the correct class instead of a CDI proxy.
|
||||||
|
*
|
||||||
|
* @return The class implementing the step.
|
||||||
|
*/
|
||||||
Class<? extends MvcAuthoringStep> getStepClass();
|
Class<? extends MvcAuthoringStep> getStepClass();
|
||||||
|
|
||||||
ContentSection getContentSection() throws ContentSectionNotFoundException;
|
ContentSection getContentSection() throws ContentSectionNotFoundException;
|
||||||
|
|
@ -52,7 +58,9 @@ public interface MvcAuthoringStep {
|
||||||
* admin priviliges for the content section of the item.</li>
|
* admin priviliges for the content section of the item.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @return {@code true} if the current user can edit the document/item, {@false} otherwise.
|
* @return {@code true} if the current user can edit the document/item, {
|
||||||
|
*
|
||||||
|
* @false} otherwise.
|
||||||
*/
|
*/
|
||||||
boolean getCanEdit();
|
boolean getCanEdit();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.librecms.ui.contentsections.documents;
|
package org.librecms.ui.contentsections.documents;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -34,8 +35,13 @@ public interface MvcAuthoringSteps {
|
||||||
|
|
||||||
public static final String DOCUMENT_PATH_PATH_PARAM_NAME = "documentPath";
|
public static final String DOCUMENT_PATH_PATH_PARAM_NAME = "documentPath";
|
||||||
|
|
||||||
public static final String DOCUMENT_PATH_PATH_PARAM = DOCUMENT_PATH_PATH_PARAM_NAME + ":(.+)?";
|
public static final String DOCUMENT_PATH_PATH_PARAM
|
||||||
|
= DOCUMENT_PATH_PATH_PARAM_NAME + ":(.+)?";
|
||||||
|
|
||||||
Set<Class<?>> getClasses();
|
Set<Class<?>> getClasses();
|
||||||
|
|
||||||
|
default Set<Class<?>> getResourceClasses() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -226,38 +226,38 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
// @GET
|
||||||
// @Path("/{locale}/@view")
|
//// @Path("/{locale}/@view")
|
||||||
@Path("/variants/{locale}")
|
// @Path("/variants/{locale}")
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
// @Transactional(Transactional.TxType.REQUIRED)
|
||||||
public String viewTextValue(
|
// public String viewTextValue(
|
||||||
@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,
|
||||||
@PathParam("locale") final String localeParam
|
// @PathParam("locale") final String localeParam
|
||||||
) {
|
// ) {
|
||||||
try {
|
// try {
|
||||||
init();
|
// 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(getArticle())) {
|
// if (itemPermissionChecker.canEditItem(getArticle())) {
|
||||||
selectedLocale = new Locale(localeParam).toString();
|
// selectedLocale = new Locale(localeParam).toString();
|
||||||
|
//
|
||||||
// return "org/librecms/ui/contenttypes/article/article-text/view.xhtml";
|
//// return "org/librecms/ui/contenttypes/article/article-text/view.xhtml";
|
||||||
return getTextValues().get(localeParam);
|
// return getTextValues().get(localeParam);
|
||||||
} else {
|
// } else {
|
||||||
return documentUi.showAccessDenied(
|
// return documentUi.showAccessDenied(
|
||||||
getContentSection(),
|
// getContentSection(),
|
||||||
getArticle(),
|
// getArticle(),
|
||||||
articleMessageBundle.getMessage("article.edit.denied")
|
// articleMessageBundle.getMessage("article.edit.denied")
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contenttypes;
|
||||||
|
|
||||||
|
import org.librecms.contentsection.ContentItem;
|
||||||
|
import org.librecms.contentsection.ContentItemRepository;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
import org.librecms.contenttypes.Article;
|
||||||
|
import org.librecms.ui.contentsections.ContentSectionsUi;
|
||||||
|
import org.librecms.ui.contentsections.ItemPermissionChecker;
|
||||||
|
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import javax.ws.rs.ForbiddenException;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.NotFoundException;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
@Path(MvcAuthoringSteps.PATH_PREFIX + "article-text-resources")
|
||||||
|
public class MvcArticleTextBodyStepResources {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for retrieving and saving the article.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ContentItemRepository itemRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ContentSectionsUi sectionsUi;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ItemPermissionChecker itemPermissionChecker;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
// @Path("/{locale}/@view")
|
||||||
|
@Path("/variants/{locale}")
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String viewTextValue(
|
||||||
|
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
|
||||||
|
final String sectionIdentifier,
|
||||||
|
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
|
||||||
|
final String documentPathParam,
|
||||||
|
@PathParam("locale") final String localeParam
|
||||||
|
) {
|
||||||
|
// try {
|
||||||
|
// init();
|
||||||
|
// } catch (ContentSectionNotFoundException ex) {
|
||||||
|
// return ex.showErrorMessage();
|
||||||
|
// } catch (DocumentNotFoundException ex) {
|
||||||
|
// return ex.showErrorMessage();
|
||||||
|
// }
|
||||||
|
|
||||||
|
final ContentSection contentSection = sectionsUi
|
||||||
|
.findContentSection(sectionIdentifier)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new NotFoundException()
|
||||||
|
);
|
||||||
|
|
||||||
|
final ContentItem document = itemRepo
|
||||||
|
.findByPath(contentSection, documentPathParam)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new NotFoundException()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!(document instanceof Article)) {
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Article article = (Article) document;
|
||||||
|
if (itemPermissionChecker.canEditItem(article)) {
|
||||||
|
return article.getText().getValue(new Locale(localeParam));
|
||||||
|
} else {
|
||||||
|
throw new ForbiddenException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -217,7 +217,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template id="cms-editor-msg-save-successful">
|
<template id="cms-editor-msg-save-successful">
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-success" role="alert">
|
||||||
#{cc.attrs.messageSaveSuccessful}
|
#{cc.attrs.messageSaveSuccessful}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -354,6 +354,7 @@
|
||||||
<button class="btn btn-primary cms-editor-edit-button"
|
<button class="btn btn-primary cms-editor-edit-button"
|
||||||
data-edit-dialog="#{cc.attrs.editorId}-edit-dialog"
|
data-edit-dialog="#{cc.attrs.editorId}-edit-dialog"
|
||||||
data-variant-url="#{cc.attrs.variantUrl}/#{variant.locale}"
|
data-variant-url="#{cc.attrs.variantUrl}/#{variant.locale}"
|
||||||
|
data-save-url="#{cc.attrs.editMethod}/#{variant.locale}"
|
||||||
type="button">
|
type="button">
|
||||||
<bootstrap:svgIcon icon="pen" />
|
<bootstrap:svgIcon icon="pen" />
|
||||||
<span class="sr-only">
|
<span class="sr-only">
|
||||||
|
|
@ -440,34 +441,34 @@
|
||||||
</div>
|
</div>
|
||||||
<div aria-describedby="#{cc.attrs.editorId}-view-dialog-title"
|
<div aria-describedby="#{cc.attrs.editorId}-view-dialog-title"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
class="modal modal-xl fade"
|
class="modal fade"
|
||||||
data-backdrop="static"
|
data-backdrop="static"
|
||||||
id="#{cc.attrs.editorId}-view-dialog"
|
id="#{cc.attrs.editorId}-view-dialog"
|
||||||
tabindex="-1">
|
tabindex="-1">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog modal-xl">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<c:choose>
|
<c:choose>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 1}">
|
<c:when test="#{cc.attrs.headingLevel == 1}">
|
||||||
<h2 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h2>
|
<h2 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.viewDialogTitle}</h2>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 2}">
|
<c:when test="#{cc.attrs.headingLevel == 2}">
|
||||||
<h3 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h3>
|
<h3 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.viewDialogTitle}</h3>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 3}">
|
<c:when test="#{cc.attrs.headingLevel == 3}">
|
||||||
<h4 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h4>
|
<h4 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.viewDialogTitle}</h4>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 4}">
|
<c:when test="#{cc.attrs.headingLevel == 4}">
|
||||||
<h5 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h5>
|
<h5 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.viewDialogTitle}</h5>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 5}">
|
<c:when test="#{cc.attrs.headingLevel == 5}">
|
||||||
<h6 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h6>
|
<h6 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.viewDialogTitle}</h6>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
<div id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</div>
|
<div id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.viewDialogTitle}</div>
|
||||||
</c:otherwise>
|
</c:otherwise>
|
||||||
</c:choose>
|
</c:choose>
|
||||||
<button aria-label="#{cc.attrs.removeDialogCancelLabel}"
|
<button aria-label="#{cc.attrs.viewDialogCancelLabel}"
|
||||||
class="close"
|
class="close"
|
||||||
data-dismiss="modal"
|
data-dismiss="modal"
|
||||||
type="button" >
|
type="button" >
|
||||||
|
|
@ -488,42 +489,41 @@
|
||||||
</div>
|
</div>
|
||||||
<div aria-describedby="#{cc.attrs.editorId}-edit-dialog-title"
|
<div aria-describedby="#{cc.attrs.editorId}-edit-dialog-title"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
class="modal modal-xl fade"
|
class="modal fade"
|
||||||
data-backdrop="static"
|
data-backdrop="static"
|
||||||
id="#{cc.attrs.editorId}-edit-dialog"
|
id="#{cc.attrs.editorId}-edit-dialog"
|
||||||
tabindex="-1">
|
tabindex="-1">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog modal-xl">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<c:choose>
|
<c:choose>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 1}">
|
<c:when test="#{cc.attrs.headingLevel == 1}">
|
||||||
<h2 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h2>
|
<h2 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.editDialogTitle}</h2>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 2}">
|
<c:when test="#{cc.attrs.headingLevel == 2}">
|
||||||
<h3 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h3>
|
<h3 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.editDialogTitle}</h3>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 3}">
|
<c:when test="#{cc.attrs.headingLevel == 3}">
|
||||||
<h4 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h4>
|
<h4 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.editDialogTitle}</h4>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 4}">
|
<c:when test="#{cc.attrs.headingLevel == 4}">
|
||||||
<h5 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h5>
|
<h5 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.editDialogTitle}</h5>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{cc.attrs.headingLevel == 5}">
|
<c:when test="#{cc.attrs.headingLevel == 5}">
|
||||||
<h6 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h6>
|
<h6 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.editDialogTitle}</h6>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
<div id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</div>
|
<div id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.editDialogTitle}</div>
|
||||||
</c:otherwise>
|
</c:otherwise>
|
||||||
</c:choose>
|
</c:choose>
|
||||||
<button aria-label="#{cc.attrs.removeDialogCancelLabel}"
|
<button aria-label="#{cc.attrs.editDialogCancelLabel}"
|
||||||
class="close"
|
class="close"
|
||||||
data-dismiss="modal"
|
|
||||||
type="button" >
|
type="button" >
|
||||||
<bootstrap:svgIcon icon="x" />
|
<bootstrap:svgIcon icon="x" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="cms-tiptap-editor-buttons">
|
<div class="cms-tiptap-editor-buttons mb-1">
|
||||||
<button class="btn btn-outline-dark tiptap-emph"
|
<button class="btn btn-outline-dark tiptap-emph"
|
||||||
type="button">
|
type="button">
|
||||||
<bootstrap:svgIcon icon="type-italic" />
|
<bootstrap:svgIcon icon="type-italic" />
|
||||||
|
|
@ -539,17 +539,17 @@
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="cms-tiptap-editor">
|
<div class="cms-tiptap-editor border">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn btn-warning"
|
<button class="btn btn-warning cms-editor-cancel-button"
|
||||||
data-dismiss="modal"
|
|
||||||
type="button" >
|
type="button" >
|
||||||
#{cc.attrs.editDialogCancelLabel}
|
#{cc.attrs.editDialogCancelLabel}
|
||||||
</button>
|
</button>
|
||||||
<button type="submit" class="btn btn-success">
|
<button class="btn btn-success cms-editor-save-button"
|
||||||
|
type="button" >
|
||||||
#{cc.attrs.editDialogSubmitLabel}
|
#{cc.attrs.editDialogSubmitLabel}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/remove"
|
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/remove"
|
||||||
title="#{CmsArticleMessageBundle['text.editor.header']}"
|
title="#{CmsArticleMessageBundle['text.editor.header']}"
|
||||||
unusedLocales="#{CmsArticleTextBodyStep.unusedLocales}"
|
unusedLocales="#{CmsArticleTextBodyStep.unusedLocales}"
|
||||||
variantUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/variants"
|
variantUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text-resources/variants"
|
||||||
variants="#{CmsArticleTextBodyStep.variants}"
|
variants="#{CmsArticleTextBodyStep.variants}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,12 @@ import * as $ from "jquery";
|
||||||
import { Editor } from "@tiptap/core";
|
import { Editor } from "@tiptap/core";
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
|
|
||||||
|
function showMessage(messageId: string) {
|
||||||
|
const template = document.querySelector(messageId) as HTMLTemplateElement;
|
||||||
|
const msg = template.content.cloneNode(true);
|
||||||
|
document.querySelector(".cms-editor-messages").append(msg);
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function (event) {
|
document.addEventListener("DOMContentLoaded", function (event) {
|
||||||
document
|
document
|
||||||
.querySelector(
|
.querySelector(
|
||||||
|
|
@ -33,25 +39,171 @@ document.addEventListener("DOMContentLoaded", function (event) {
|
||||||
|
|
||||||
viewDialogBody.textContent = text;
|
viewDialogBody.textContent = text;
|
||||||
|
|
||||||
$(`#${viewDialogId}`).modal('toggle');
|
$(`#${viewDialogId}`).modal("toggle");
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
const template = document.querySelector(
|
showMessage(
|
||||||
"#cms-editor-msg-variant-load-failed"
|
"#cms-editor-msg-variant-load-failed"
|
||||||
) as HTMLTemplateElement;
|
);
|
||||||
const msg = template.content.cloneNode(true);
|
|
||||||
document
|
|
||||||
.querySelector(".cms-editor-messages")
|
|
||||||
.append(msg);
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
showMessage("#cms-editor-msg-variant-load-failed");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
const template = document.querySelector(
|
showMessage("#cms-editor-msg-variant-load-failed");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector(
|
||||||
|
".cms-editor .cms-editor-variants .cms-editor-edit-button"
|
||||||
|
)
|
||||||
|
.addEventListener("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const target = event.currentTarget as Element;
|
||||||
|
const variantUrl = target.getAttribute("data-variant-url");
|
||||||
|
const editDialogId = target.getAttribute("data-edit-dialog");
|
||||||
|
const saveUrl = target.getAttribute("data-save-url");
|
||||||
|
|
||||||
|
fetch(variantUrl, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include"
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
response
|
||||||
|
.text()
|
||||||
|
.then(text => {
|
||||||
|
const editDialog = document.querySelector(
|
||||||
|
`#${editDialogId}`
|
||||||
|
);
|
||||||
|
const tiptapDiv = editDialog.querySelector(
|
||||||
|
".modal-body .cms-tiptap-editor"
|
||||||
|
);
|
||||||
|
if (!tiptapDiv) {
|
||||||
|
console.warn("tiptapDiv is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
const editor = new Editor({
|
||||||
|
element: tiptapDiv,
|
||||||
|
extensions: [StarterKit],
|
||||||
|
content: text
|
||||||
|
});
|
||||||
|
|
||||||
|
const buttonsDiv = editDialog.querySelector(
|
||||||
|
".cms-tiptap-editor-buttons"
|
||||||
|
);
|
||||||
|
if (!buttonsDiv) {
|
||||||
|
console.warn("buttonsDiv is null.");
|
||||||
|
}
|
||||||
|
const emphButton = buttonsDiv.querySelector(
|
||||||
|
".tiptap-emph"
|
||||||
|
);
|
||||||
|
if (!emphButton) {
|
||||||
|
console.warn("emphButton not found.");
|
||||||
|
}
|
||||||
|
emphButton.addEventListener("click", event => {
|
||||||
|
event.preventDefault();
|
||||||
|
editor.chain().focus().toggleItalic().run();
|
||||||
|
});
|
||||||
|
|
||||||
|
const strongEmphButton = buttonsDiv.querySelector(
|
||||||
|
".tiptap-strong-emph"
|
||||||
|
);
|
||||||
|
if (!strongEmphButton) {
|
||||||
|
console.warn("strongEmphButton not found.");
|
||||||
|
}
|
||||||
|
strongEmphButton.addEventListener(
|
||||||
|
"click",
|
||||||
|
event => {
|
||||||
|
event.preventDefault();
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.toggleBold()
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const closeButton = editDialog.querySelector(
|
||||||
|
".modal-header .close"
|
||||||
|
);
|
||||||
|
const cancelButton = editDialog.querySelector(
|
||||||
|
".modal-footer .cms-editor-cancel-button"
|
||||||
|
);
|
||||||
|
const saveButton = editDialog.querySelector(
|
||||||
|
".modal-footer .cms-editor-save-button"
|
||||||
|
);
|
||||||
|
|
||||||
|
closeButton.addEventListener("click", event => {
|
||||||
|
editor.chain().clearContent();
|
||||||
|
editor.destroy();
|
||||||
|
$(`#${editDialogId}`).modal("toggle");
|
||||||
|
});
|
||||||
|
|
||||||
|
cancelButton.addEventListener(
|
||||||
|
"click",
|
||||||
|
event => {
|
||||||
|
editor.chain().clearContent();
|
||||||
|
editor.destroy();
|
||||||
|
$(`#${editDialogId}`).modal("toggle");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
saveButton.addEventListener("click", event => {
|
||||||
|
const html = editor.getHTML();
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("value", html);
|
||||||
|
fetch(saveUrl, {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(saveResponse => {
|
||||||
|
if (saveResponse.ok) {
|
||||||
|
showMessage(
|
||||||
|
"#cms-editor-msg-save-successful"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
showMessage(
|
||||||
|
"#cms-editor-msg-save-failed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$(`#${editDialogId}`).modal(
|
||||||
|
"toggle"
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
showMessage(
|
||||||
|
"#cms-editor-msg-save-failed"
|
||||||
|
);
|
||||||
|
console.error(err);
|
||||||
|
$(`#${editDialogId}`).modal(
|
||||||
|
"toggle"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(`#${editDialogId}`).modal("toggle");
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
showMessage(
|
||||||
"#cms-editor-msg-variant-load-failed"
|
"#cms-editor-msg-variant-load-failed"
|
||||||
) as HTMLTemplateElement;
|
);
|
||||||
const msg = template.content.cloneNode(true);
|
console.error(err);
|
||||||
document.querySelector(".cms-editor-messages").append(msg);
|
});
|
||||||
|
} else {
|
||||||
|
showMessage("#cms-editor-msg-variant-load-failed");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
showMessage("#cms-editor-msg-variant-load-failed");
|
||||||
|
console.error(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue