Current status text step

pull/10/head
Jens Pelzetter 2021-05-10 21:24:48 +02:00
parent 5dc98cfe8a
commit b526f9eac2
9 changed files with 765 additions and 34 deletions

View File

@ -114,6 +114,11 @@
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>

View File

@ -0,0 +1,49 @@
/*
* 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;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CmsEditorLocaleVariantRow {
private String locale;
private long wordCount;
public String getLocale() {
return locale;
}
public void setLocale(final String locale) {
this.locale = locale;
}
public long getWordCount() {
return wordCount;
}
public void setWordCount(final long wordCount) {
this.wordCount = wordCount;
}
}

View File

@ -20,6 +20,8 @@ package org.librecms.ui.contenttypes;
import com.arsdigita.kernel.KernelConfig;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.l10n.LocalizedString;
@ -27,6 +29,7 @@ import org.librecms.contentsection.ContentItemRepository;
import org.librecms.contenttypes.Article;
import org.librecms.ui.contentsections.ItemPermissionChecker;
import org.librecms.ui.contentsections.documents.AbstractMvcAuthoringStep;
import org.librecms.ui.contentsections.documents.CmsEditorLocaleVariantRow;
import org.librecms.ui.contentsections.documents.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentUi;
@ -54,6 +57,7 @@ import javax.ws.rs.PathParam;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
import java.util.Collections;
import java.util.StringTokenizer;
/**
* Authoring step for editing the main text of an {@link Article}.
@ -97,6 +101,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
private ItemPermissionChecker itemPermissionChecker;
private Map<String, String> textValues;
private List<CmsEditorLocaleVariantRow> variants;
private List<String> unusedLocales;
@ -125,8 +131,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
}
if (itemPermissionChecker.canEditItem(getArticle())) {
// return "org/librecms/ui/contenttypes/article/article-text.xhtml";
return "org/librecms/ui/contenttypes/article/article-text/available-languages.xhtml";
return "org/librecms/ui/contenttypes/article/article-text.xhtml";
// return "org/librecms/ui/contenttypes/article/article-text/available-languages.xhtml";
} else {
return documentUi.showAccessDenied(
getContentSection(),
@ -144,6 +150,10 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
public Map<String, String> getTextValues() {
return Collections.unmodifiableMap(textValues);
}
public List<CmsEditorLocaleVariantRow> getVariants() {
return variants;
}
/**
* Gets the locales for which the main text has not been defined yet.
@ -168,7 +178,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
* @return A redirect to this authoring step.
*/
@POST
@Path("/@add")
// @Path("/@add")
@Path("/add")
@Transactional(Transactional.TxType.REQUIRED)
public String addTextValue(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
@ -216,7 +227,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
}
@GET
@Path("/{locale}/@view")
// @Path("/{locale}/@view")
@Path("/variants/{locale}")
@Transactional(Transactional.TxType.REQUIRED)
public String viewTextValue(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
@ -236,7 +248,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
if (itemPermissionChecker.canEditItem(getArticle())) {
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);
} else {
return documentUi.showAccessDenied(
getContentSection(),
@ -248,7 +261,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
@GET
@Path("/{locale}/@edit")
// @Path("/{locale}/@edit")
@Path("/edit/{locale}")
@Transactional(Transactional.TxType.REQUIRED)
public String editTextValue(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
@ -289,7 +303,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
* @return A redirect to this authoring step.
*/
@POST
@Path("/{locale}/@edit")
// @Path("/{locale}/@edit")
@Path("/edit/{locale}")
@Transactional(Transactional.TxType.REQUIRED)
public String editTextValue(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
@ -332,7 +347,8 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
* @return A redirect to this authoring step.
*/
@POST
@Path("/{locale}/@remove")
// @Path("/{locale}/@remove")
@Path("/remove/{locale}")
@Transactional(Transactional.TxType.REQUIRED)
public String removeTextValue(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
@ -381,6 +397,14 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
entry -> entry.getValue()
)
);
variants = getArticle()
.getText()
.getValues()
.entrySet()
.stream()
.map(this::buildVariantRow)
.collect(Collectors.toList());
final Set<Locale> locales = getArticle()
.getText()
@ -397,5 +421,19 @@ public class MvcArticleTextBodyStep extends AbstractMvcAuthoringStep {
private Article getArticle() {
return (Article) getDocument();
}
private CmsEditorLocaleVariantRow buildVariantRow(
final Map.Entry<Locale, String> entry
) {
final CmsEditorLocaleVariantRow variant = new CmsEditorLocaleVariantRow();
variant.setLocale(entry.getKey().toString());
final Document document = Jsoup.parseBodyFragment(entry.getValue());
document.body().text();
variant.setWordCount(
new StringTokenizer(document.body().text()).countTokens()
);
return variant;
}
}

View File

@ -0,0 +1,560 @@
<!DOCTYPE html [<!ENTITY times '&#215;'>]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<cc:interface shortDescription="A editor component for HTML texts using the TipTap editor. To use this component you have also to include the cms-editor.js file into the page.">
<cc:attribute name="addMethod"
required="true"
shortDescription="URL of teh endpoint for adding localized values."
type="String" />
<cc:attribute name="addButtonLabel"
default="Add"
required="false"
shortDescription="Label for the add button"
type="String" />
<cc:attribute name="addDialogCancelLabel"
default="Cancel"
required="false"
shortDescription="Label for the cancel and close buttons."
type="String" />
<cc:attribute name="addDialogLocaleSelectHelp"
default="The locale of the value of add"
required="false"
shortDescription="Help text for the locale select field"
type="String" />
<cc:attribute name="addDialogLocaleSelectLabel"
default="Locale"
required="false"
shortDescription="Label for the locale select field"
type="String" />
<cc:attribute name="addDialogSubmitLabel"
default="Add"
required="false"
shortDescription="Label for the submit button"
type="String" />
<cc:attribute name="addDialogTitle"
default="Add localization"
required="false"
shortDescription="Title for the dialog."
type="String" />
<cc:attribute name="canEdit"
default="true"
required="false"
shortDescription="Can the current user edit the text?"
type="boolean" />
<cc:attribute name="editButtonLabel"
default="Edit"
required="false"
shortDescription="Label for the edit button"
type="String" />
<cc:attribute name="editDialogCancelLabel"
default="Cancel"
required="false"
shortDescription="Label for the cancel and close button of the edit dialog"
type="String" />
<cc:attribute name="editDialogSubmitLabel"
default="save"
required="false"
shortDescription="Label for the submit button of the edit dialog"
type="String" />
<cc:attribute name="editDialogValueHelp"
default="Value to update"
required="false"
shortDescription="Help text for the value field"
type="String" />
<cc:attribute name="editDialogValueLabel"
default="Value"
required="false"
shortDescription="Label for the value field"
type="String" />
<cc:attribute name="editDialogTitle"
default="Edit localized value"
required="false"
shortDescription="Title for the edit dialog"
type="String" />
<cc:attribute name="editMethod"
required="true"
shortDescription="URL of the endpoint for editing/updating a value. The value of the locale to update is added after the provided URL, eg. /de for updating the german value."
type="String" />
<cc:attribute name="hasUnusedLocales"
required="true"
shortDescription="Are there unused locales? This will usually be an expression pointing to some method. The result must resolve to boolean."
type="boolean" />
<cc:attribute name="headingLevel"
default="2"
required="false"
shortDescription="Level of the heading used for the component. Also determines the heading levels used for other parts of the component."
type="int" />
<cc:attribute name="editorId"
required="true"
shortDescription="ID for the editor. Also used as prefix to generate IDs for some subcomponents"
type="String" />
<cc:attribute name="emptyText"
default="No localized values"
required="false"
shortDescription="Text shown if the localized has no values yet."
type="String" />
<cc:attribute name="messageSaveFailed"
default="Failed to save."
required="false"
type="String" />
<cc:attribute name="messageSaveSuccessful"
default="Saved sucessfully."
required="false"
type="String" />
<cc:attribute name="messageVariantLoadFailed"
default="Failed to load variant."
required="false"
type="String" />
<cc:attribute name="objectIdentifier"
required="true"
shortDescription="Identifier of the object to which the localized string belongs"
type="String" />
<cc:attribute name="removeButtonLabel"
default="Remove"
required="false"
shortDescription="Label for the remove button"
type="String" />
<cc:attribute name="removeDialogCancelLabel"
default="Cancel"
required="false"
shortDescription="Label for the cancel and close buttons of the remove dialog"
type="String" />
<cc:attribute name="removeDialogSubmitLabel"
default="Remove localized value"
required="false"
shortDescription="Label for the submit button of the remove dialog (removes the localized value)"
type="String" />
<cc:attribute name="removeDialogText"
default="Are you sure to remove the following localized value?"
required="false"
shortDescription="Text for the remove dialog"
type="String" />
<cc:attribute name="removeDialogTitle"
default="Remove localized value"
required="false"
shortDescription="The title of the remove dialog"
type="String" />
<cc:attribute name="removeMethod"
required="true"
shortDescription="URL of the endpoint for remvoving a value. The locale of the value to remove is added to the end of the URL. Eg. /de for removing the value for the locale de."
type="String" />
<cc:attribute name="tableActionsHeading"
default="Actions"
required="false"
shortDescription="Heading for the action columns"
type="String" />
<cc:attribute name="tableLocaleHeading"
default="Locale"
required="false"
shortDescription="Heading for the locale column"
type="String" />
<cc:attribute name="tableWordCountHeading"
default="Words"
required="false"
shortDescription="Heading for the word count column"
type="String" />
<cc:attribute name="title"
required="true"
shortDescription="Title/Heading of the editor widget"
type="String" />
<cc:attribute name="unusedLocales"
required="true"
shortDescription="A collection of the unused locales of the edited localized string"
type="java.util.Collection" />
<cc:attribute name="variants"
required="true"
shortDescription="Info about the available variants. Must be a List of CmsEditorLocaleVariantRow objects."
type="java.util.List" />
<cc:attribute name="variantUrl"
required="true"
shortDescription="URL of the endpoint for retrieving a variant. The locale of the variant to retrieve is appended as last token."
type="String" />
<cc:attribute name="viewButtonLabel"
default="View"
type="String" />
<cc:attribute name="viewDialogTitle"
default="View"
type="String" />
<cc:attribute name="viewDialogEditButtonLabel"
default="Edit"
type="String" />
<cc:attribute name="viewDialogCloseButtonLabel"
default="Close"
type="String" />
</cc:interface>
<cc:implementation>
<div class="cms-editor"
id="#{cc.attrs.editorId}">
<c:choose>
<c:when test="#{cc.attrs.headingLevel == 1}">
<h1>#{cc.attrs.title}</h1>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 2}">
<h2>#{cc.attrs.title}</h2>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 3}">
<h3>#{cc.attrs.title}</h3>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 4}">
<h4>#{cc.attrs.title}</h4>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 5}">
<h5>#{cc.attrs.title}</h5>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 6}">
<h6>#{cc.attrs.title}</h6>
</c:when>
<c:otherwise>
<div>#{cc.attrs.title}</div>
</c:otherwise>
</c:choose>
<div class="cms-editor-messages">
<template id="cms-editor-msg-save-failed">
<div class="alert alert alert-danger" role="alert">
#{cc.attrs.messageSaveFailed}
</div>
</template>
<template id="cms-editor-msg-save-successful">
<div class="alert alert-danger" role="alert">
#{cc.attrs.messageSaveSuccessful}
</div>
</template>
<template id="cms-editor-msg-variant-load-failed">
<div class="alert alert-warning" role="alert">
#{cc.attrs.messageVariantLoadFailed}
</div>
</template>
</div>
<c:if test="#{cc.attrs.hasUnusedLocales}">
<div class="mb-2">
<div class="text-right">
<button class="btn btn-secondary"
data-target="##{cc.attrs.editorId}-dialog"
data-toggle="modal"
type="button">
<bootstrap:svgIcon icon="plus-circle" />
<span>
#{cc.attrs.addButtonLabel}
</span>
</button>
</div>
<div aria-labelledby="#{cc.attrs.editorId}-dialog-title"
aria-hidden="true"
class="modal fade"
id="#{cc.attrs.editorId}-dialog"
tabindex="-1">
<div class="modal-dialog">
<form action="#{cc.attrs.addMethod}"
class="modal-content"
method="post">
<div class="modal-header">
<c:choose>
<c:when test="#{cc.attrs.headingLevel == 1}">
<h2 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h2>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 2}">
<h3 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h3>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 3}">
<h4 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h4>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 4}">
<h5 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h5>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 5}">
<h6 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h6>
</c:when>
<c:otherwise>
<div>#{cc.attrs.addDialogTitle}</div>
</c:otherwise>
</c:choose>
<button aria-label="#{cc.attrs.addDialogCancelLabel}"
class="close"
data-dismiss="modal"
type="button" >
<span aria-hidden="true">
<bootstrap:svgIcon icon="x" />
</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="#{cc.attrs.editorId}-form-locale-select">
#{cc.attrs.addDialogLocaleSelectLabel}
</label>
<select aria-describedby="#{cc.attrs.editorId}-form-locale-select-help"
id="#{cc.attrs.editorId}-form-locale-select"
name="locale"
required="true">
<c:forEach items="#{cc.attrs.unusedLocales}"
var="locale">
<option value="#{locale}">#{locale}</option>
</c:forEach>
</select>
<small class="form-text text-muted"
id="#{cc.attrs.editorId}-form-locale-select-help">
#{cc.attrs.addDialogLocaleSelectHelp}
</small>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{cc.attrs.addDialogCancelLabel}
</button>
<button type="submit" class="btn btn-primary">
#{cc.attrs.addDialogSubmitLabel}
</button>
</div>
</form>
</div>
</div>
</div>
</c:if>
<c:choose>
<c:when test="#{cc.attrs.values.isEmpty()}">
<p>
#{cc.attrs.emptyText}
</p>
</c:when>
<c:otherwise>
<table class="cms-editor-variants table table-hover">
<thead class="thead-light">
<tr>
<th scope="col">#{cc.attrs.tableLocaleHeading}</th>
<th scope="col">#{cc.attrs.tableWordCountHeading}</th>
<th scope="col">#{cc.attrs.tableActionsHeading}</th>
</tr>
</thead>
<tbody>
<c:forEach items="#{cc.attrs.variants}"
var="variant">
<tr>
<td>#{variant.locale}</td>
<td>#{CmsAdminMessages.getMessage('cms_editor.variants.wordcount', [variant.wordCount])}</td>
<td>
<button class="btn btn-primary cms-editor-view-button"
data-view-dialog="#{cc.attrs.editorId}-view-dialog"
data-variant-url="#{cc.attrs.variantUrl}/#{variant.locale}"
type="button">
<bootstrap:svgIcon icon="eye" />
<span class="sr-only">
#{cc.attrs.viewButtonLabel}
</span>
</button>
<c:if test="#{cc.attrs.canEdit}">
<button class="btn btn-primary cms-editor-edit-button"
data-edit-dialog="#{cc.attrs.editorId}-edit-dialog"
data-variant-url="#{cc.attrs.variantUrl}/#{variant.locale}"
type="button">
<bootstrap:svgIcon icon="pen" />
<span class="sr-only">
#{cc.attrs.editButtonLabel}
</span>
</button>
<button class="btn btn-danger"
data-target="##{cc.attrs.editorId}-#{entry.key}-remove-dialog"
data-toggle="modal"
type="button">
<bootstrap:svgIcon icon="x-circle" />
<span class="sr-only">
#{cc.attrs.removeButtonLabel}
</span>
</button>
<div aria-describedby="#{cc.attrs.editorId}-#{entry.key}-remove-dialog-title"
aria-hidden="true"
class="modal fade"
data-backdrop="static"
id="#{cc.attrs.editorId}-#{entry.key}-remove-dialog"
tabindex="-1">
<div class="modal-dialog">
<form action="#{cc.attrs.removeMethod}/#{entry.key}"
class="modal-content"
method="post">
<div class="modal-header">
<c:choose>
<c:when test="#{cc.attrs.headingLevel == 1}">
<h2>#{cc.attrs.removeDialogTitle}</h2>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 2}">
<h3>#{cc.attrs.removeDialogTitle}</h3>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 3}">
<h4>#{cc.attrs.removeDialogTitle}</h4>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 4}">
<h5>#{cc.attrs.removeDialogTitle}</h5>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 5}">
<h6>#{cc.attrs.removeDialogTitle}</h6>
</c:when>
<c:otherwise>
<div>#{cc.attrs.removeDialogTitle}</div>
</c:otherwise>
</c:choose>
<button aria-label="#{cc.attrs.removeDialogCancelLabel}"
class="close"
data-dismiss="modal"
type="button" >
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>
#{cc.attrs.removeDialogText}
</p>
<pre>#{entry.key}: #{entry.value}</pre>
<input name="confirmed"
type="hidden"
value="true" />
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{cc.attrs.removeDialogCancelLabel}
</button>
<button type="submit" class="btn btn-danger">
#{cc.attrs.removeDialogSubmitLabel}
</button>
</div>
</form>
</div>
</div>
</c:if>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</c:otherwise>
</c:choose>
</div>
<div aria-describedby="#{cc.attrs.editorId}-view-dialog-title"
aria-hidden="true"
class="modal modal-xl fade"
data-backdrop="static"
id="#{cc.attrs.editorId}-view-dialog"
tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<c:choose>
<c:when test="#{cc.attrs.headingLevel == 1}">
<h2 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h2>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 2}">
<h3 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h3>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 3}">
<h4 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h4>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 4}">
<h5 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h5>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 5}">
<h6 id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</h6>
</c:when>
<c:otherwise>
<div id="#{cc.attrs.editorId}-view-dialog-title">#{cc.attrs.removeDialogTitle}</div>
</c:otherwise>
</c:choose>
<button aria-label="#{cc.attrs.removeDialogCancelLabel}"
class="close"
data-dismiss="modal"
type="button" >
<bootstrap:svgIcon icon="x" />
</button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{cc.attrs.viewDialogCloseButtonLabel}
</button>
</div>
</div>
</div>
</div>
<div aria-describedby="#{cc.attrs.editorId}-edit-dialog-title"
aria-hidden="true"
class="modal modal-xl fade"
data-backdrop="static"
id="#{cc.attrs.editorId}-edit-dialog"
tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<c:choose>
<c:when test="#{cc.attrs.headingLevel == 1}">
<h2 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h2>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 2}">
<h3 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h3>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 3}">
<h4 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h4>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 4}">
<h5 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h5>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 5}">
<h6 id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</h6>
</c:when>
<c:otherwise>
<div id="#{cc.attrs.editorId}-edit-dialog-title">#{cc.attrs.removeDialogTitle}</div>
</c:otherwise>
</c:choose>
<button aria-label="#{cc.attrs.removeDialogCancelLabel}"
class="close"
data-dismiss="modal"
type="button" >
<bootstrap:svgIcon icon="x" />
</button>
</div>
<div class="modal-body">
<div class="cms-tiptap-editor-buttons">
<button class="btn btn-outline-dark tiptap-emph"
type="button">
<bootstrap:svgIcon icon="type-italic" />
<span class="sr-only">
#{CmsAdminMessages['cms_editor.buttons.emph']}
</span>
</button>
<button class="btn btn-outline-dark tiptap-strong-emph"
type="button">
<bootstrap:svgIcon icon="type-bold" />
<span class="sr-only">
#{CmsAdminMessages['cms_editor.buttons.strong_emph']}
</span>
</button>
</div>
<div class="cms-tiptap-editor">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-warning"
data-dismiss="modal"
type="button" >
#{cc.attrs.editDialogCancelLabel}
</button>
<button type="submit" class="btn btn-success">
#{cc.attrs.editDialogSubmitLabel}
</button>
</div>
</div>
</div>
</div>
</cc:implementation>
</html>

View File

@ -3,30 +3,44 @@
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
xmlns:librecms="http://xmlns.jcp.org/jsf/composite/components/librecms"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/librecms/ui/contentsection/documents/authoringstep.xhtml">
<ui:define name="authoringStep">
<h2>#{CmsArticleMessageBundle['textstep.header']}</h2>
<libreccm:localizedStringEditor
addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/add"
editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/edit"
editorId="article-text-editor"
hasUnusedLocales="#{!CmsArticleTextBodyStep.unusedLocales.isEmpty()}"
headingLevel="3"
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/remove"
title="#{CmsArticleMessageBundle['text.editor.header']}"
unusedLocales="#{CmsArticleTextBodyStep.unusedLocales}"
useTextarea="true"
values="#{CmsArticleTextBodyStep.textValues}"
/>
<div id="cms-editor"></div>
<!-- <libreccm:localizedStringEditor
addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/add"
editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/edit"
editorId="article-text-editor"
hasUnusedLocales="#{!CmsArticleTextBodyStep.unusedLocales.isEmpty()}"
headingLevel="3"
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/remove"
title="#{CmsArticleMessageBundle['text.editor.header']}"
unusedLocales="#{CmsArticleTextBodyStep.unusedLocales}"
useTextarea="true"
values="#{CmsArticleTextBodyStep.textValues}"
/>
<div id="cms-editor"></div>-->
<librecms:cmsEditor addMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/add"
editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/edit"
editorId="article-text-editor"
hasUnusedLocales="#{!CmsArticleTextBodyStep.unusedLocales.isEmpty()}"
headingLevel="3"
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
removeMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/remove"
title="#{CmsArticleMessageBundle['text.editor.header']}"
unusedLocales="#{CmsArticleTextBodyStep.unusedLocales}"
variantUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/variants"
variants="#{CmsArticleTextBodyStep.variants}"
/>
</ui:define>
<ui:define name="scripts">
<script src="#{request.contextPath}/assets/@content-sections/cms-editor.js"></script>
</ui:define>

View File

@ -766,3 +766,6 @@ contentsection.configuration.workflows.task_details.assigned_to.title=Assigned r
contentsection.configuration.workflow.task_details.assignments.dialog.roles.label=Roles
contentsection.configuration.workflow.task_details.assignments.dialog.roles.help=Select the roles to which task is assigned.
contentsection.configuration.workflows.task_details.assigned_to.dialog.title=Edit assigned roles
cms_editor.buttons.emph=Emphasized
cms_editor.buttons.strong_emph=Strong emphasized
cms_editor.variants.wordcount={0} words

View File

@ -767,3 +767,6 @@ contentsection.configuration.workflows.task_details.assigned_to.title=Zugewiesen
contentsection.configuration.workflow.task_details.assignments.dialog.roles.label=Rollen
contentsection.configuration.workflow.task_details.assignments.dialog.roles.help=W\u00e4hlen Sie die Rollen, denen die Aufgabe zugewiesen ist.
contentsection.configuration.workflows.task_details.assigned_to.dialog.title=Zugewiesene Rollen bearbeiten
cms_editor.buttons.emph=Betont
cms_editor.buttons.strong_emph=Stark betont
cms_editor.variants.wordcount={0} W\u00f6rter

View File

@ -1,15 +1,66 @@
import "bootstrap";
import * as $ from "jquery";
import { Editor } from "@tiptap/core";
import StarterKit from "@tiptap/starter-kit";
document.addEventListener("DOMContentLoaded", function (event) {
console.log("Starting editor");
new Editor({
element: document.querySelector('#cms-editor'),
extensions: [
StarterKit
],
content: '<h1>Hello World</h1>'
})
document
.querySelector(
".cms-editor .cms-editor-variants .cms-editor-view-button"
)
.addEventListener("click", function (event) {
event.preventDefault();
const target = event.currentTarget as Element;
const variantUrl = target.getAttribute("data-variant-url");
const viewDialogId = target.getAttribute("data-view-dialog");
})
fetch(variantUrl, {
method: "GET",
credentials: "include"
})
.then(response => {
if (response.ok) {
response
.text()
.then(text => {
const viewDialog = document.querySelector(
`#${viewDialogId}`
);
const viewDialogBody = viewDialog.querySelector(
".modal-body"
);
viewDialogBody.textContent = text;
$(`#${viewDialogId}`).modal('toggle');
})
.catch(err => {
const template = document.querySelector(
"#cms-editor-msg-variant-load-failed"
) as HTMLTemplateElement;
const msg = template.content.cloneNode(true);
document
.querySelector(".cms-editor-messages")
.append(msg);
});
}
})
.catch(err => {
const template = document.querySelector(
"#cms-editor-msg-variant-load-failed"
) as HTMLTemplateElement;
const msg = template.content.cloneNode(true);
document.querySelector(".cms-editor-messages").append(msg);
});
});
// console.log("Starting editor");
// new Editor({
// element: document.querySelector('#cms-editor'),
// extensions: [
// StarterKit
// ],
// content: '<h1>Hello World</h1>'
// })
});

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"lib": [
"DOM",
"ES2016"
]
}
}