ContentItemPicker component and bugfixes for asset picker
parent
80cf9143ee
commit
c8f36b9099
|
|
@ -244,7 +244,7 @@ import javax.xml.bind.annotation.XmlElementWrapper;
|
||||||
+ ")")
|
+ ")")
|
||||||
,
|
,
|
||||||
@NamedQuery(
|
@NamedQuery(
|
||||||
name = "ContentItem.findNameAndContentSectionAndVersion",
|
name = "ContentItem.findByNameAndContentSectionAndVersion",
|
||||||
query = "SELECT DISTINCT i "
|
query = "SELECT DISTINCT i "
|
||||||
+ "FROM ContentItem i "
|
+ "FROM ContentItem i "
|
||||||
+ "JOIN i.contentType t "
|
+ "JOIN i.contentType t "
|
||||||
|
|
@ -310,7 +310,9 @@ import javax.xml.bind.annotation.XmlElementWrapper;
|
||||||
+ " )"
|
+ " )"
|
||||||
+ " )"
|
+ " )"
|
||||||
+ " OR true = :isSystemUser OR true = :isAdmin"
|
+ " OR true = :isSystemUser OR true = :isAdmin"
|
||||||
+ ")")
|
+ ")"
|
||||||
|
)
|
||||||
|
|
||||||
,
|
,
|
||||||
@NamedQuery(
|
@NamedQuery(
|
||||||
name = "ContentItem.findByNameAndTypeAndContentSection",
|
name = "ContentItem.findByNameAndTypeAndContentSection",
|
||||||
|
|
|
||||||
|
|
@ -339,7 +339,7 @@ public class ContentItemRepository
|
||||||
|
|
||||||
final TypedQuery<ContentItem> query = getEntityManager()
|
final TypedQuery<ContentItem> query = getEntityManager()
|
||||||
.createNamedQuery(
|
.createNamedQuery(
|
||||||
"ContentItem.findByNameAndContentSectionAndVersion",
|
"ContentItem.findByTypeAndContentSectionAndVersion",
|
||||||
ContentItem.class);
|
ContentItem.class);
|
||||||
query.setParameter("section", section);
|
query.setParameter("section", section);
|
||||||
query.setParameter("type", type);
|
query.setParameter("type", type);
|
||||||
|
|
@ -357,7 +357,7 @@ public class ContentItemRepository
|
||||||
final ContentSection section) {
|
final ContentSection section) {
|
||||||
|
|
||||||
final TypedQuery<ContentItem> query = getEntityManager()
|
final TypedQuery<ContentItem> query = getEntityManager()
|
||||||
.createNamedQuery("ContentItem.findByNameAndContentSection",
|
.createNamedQuery("ContentItem.findByNameAndTypeAndContentSection",
|
||||||
ContentItem.class);
|
ContentItem.class);
|
||||||
query.setParameter("section", section);
|
query.setParameter("section", section);
|
||||||
query.setParameter("name", name);
|
query.setParameter("name", name);
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ public class ContentItems {
|
||||||
if (ContentItem.class.isAssignableFrom(clazz)) {
|
if (ContentItem.class.isAssignableFrom(clazz)) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Class<? extends ContentItem> typeClass
|
final Class<? extends ContentItem> typeClass
|
||||||
= (Class<? extends ContentItem>) clazz;
|
= (Class<? extends ContentItem>) clazz;
|
||||||
return typeClass;
|
return typeClass;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
|
|
@ -177,7 +177,7 @@ public class ContentItems {
|
||||||
} else {
|
} else {
|
||||||
itemVersion = ContentItemVersion.LIVE;
|
itemVersion = ContentItemVersion.LIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ContentItem> items;
|
final List<ContentItem> items;
|
||||||
if ((query == null || query.trim().isEmpty())
|
if ((query == null || query.trim().isEmpty())
|
||||||
&& (type == null || type.trim().isEmpty())) {
|
&& (type == null || type.trim().isEmpty())) {
|
||||||
|
|
@ -187,25 +187,30 @@ public class ContentItems {
|
||||||
} else if ((query != null && !query.trim().isEmpty())
|
} else if ((query != null && !query.trim().isEmpty())
|
||||||
&& (type == null || type.trim().isEmpty())) {
|
&& (type == null || type.trim().isEmpty())) {
|
||||||
|
|
||||||
items = itemRepo.findByNameAndContentSection(query,
|
items = itemRepo.findByNameAndContentSection(
|
||||||
contentSection,
|
query,
|
||||||
itemVersion);
|
contentSection,
|
||||||
|
itemVersion
|
||||||
|
);
|
||||||
} else if ((query == null || query.trim().isEmpty())
|
} else if ((query == null || query.trim().isEmpty())
|
||||||
&& (type != null && !type.trim().isEmpty())) {
|
&& (type != null && !type.trim().isEmpty())) {
|
||||||
|
|
||||||
final Class<? extends ContentItem> itemType
|
final Class<? extends ContentItem> itemType
|
||||||
= toContentItemTypeClass(type);
|
= toContentItemTypeClass(type);
|
||||||
items = itemRepo.findByTypeAndContentSection(itemType,
|
items = itemRepo.findByTypeAndContentSection(
|
||||||
contentSection,
|
itemType,
|
||||||
itemVersion);
|
contentSection,
|
||||||
|
itemVersion
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
final Class<? extends ContentItem> itemType
|
final Class<? extends ContentItem> itemType
|
||||||
= toContentItemTypeClass(type);
|
= toContentItemTypeClass(type);
|
||||||
items = itemRepo.findByNameAndTypeAndContentSection(
|
items = itemRepo.findByNameAndTypeAndContentSection(
|
||||||
query,
|
query,
|
||||||
itemType,
|
itemType,
|
||||||
contentSection,
|
contentSection,
|
||||||
itemVersion);
|
itemVersion
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
|
@ -279,11 +284,11 @@ public class ContentItems {
|
||||||
} else if ((query == null || query.trim().isEmpty())
|
} else if ((query == null || query.trim().isEmpty())
|
||||||
&& (type != null && type.trim().isEmpty())) {
|
&& (type != null && type.trim().isEmpty())) {
|
||||||
final Class<? extends ContentItem> itemType
|
final Class<? extends ContentItem> itemType
|
||||||
= toContentItemTypeClass(type);
|
= toContentItemTypeClass(type);
|
||||||
items = itemRepo.filterByFolderAndType(folder, itemType);
|
items = itemRepo.filterByFolderAndType(folder, itemType);
|
||||||
} else {
|
} else {
|
||||||
final Class<? extends ContentItem> itemType
|
final Class<? extends ContentItem> itemType
|
||||||
= toContentItemTypeClass(type);
|
= toContentItemTypeClass(type);
|
||||||
items = itemRepo.filterByFolderAndTypeAndName(folder,
|
items = itemRepo.filterByFolderAndTypeAndName(folder,
|
||||||
itemType,
|
itemType,
|
||||||
query);
|
query);
|
||||||
|
|
|
||||||
|
|
@ -187,43 +187,10 @@ public class LinkDetailsModel {
|
||||||
return Bookmark.class.getName();
|
return Bookmark.class.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
public boolean isTargetSet() {
|
||||||
// * Sets the properties of this model based on the properties on the provided
|
return bookmarkUuid != null || targetItemUuid != null;
|
||||||
// * link.
|
}
|
||||||
// *
|
|
||||||
// * @param link The link to use.
|
|
||||||
// */
|
|
||||||
// protected void setInternalLink(final RelatedLink link) {
|
|
||||||
// Objects.requireNonNull(link);
|
|
||||||
//
|
|
||||||
// uuid = link.getUuid();
|
|
||||||
// label = globalizationHelper.getValueFromLocalizedString(
|
|
||||||
// link.getTitle()
|
|
||||||
// );
|
|
||||||
// title = link
|
|
||||||
// .getTitle()
|
|
||||||
// .getValues()
|
|
||||||
// .entrySet()
|
|
||||||
// .stream()
|
|
||||||
// .collect(
|
|
||||||
// Collectors.toMap(
|
|
||||||
// entry -> entry.getKey().toString(),
|
|
||||||
// entry -> entry.getValue()
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// final Set<Locale> titleLocales = link.getTitle().getAvailableLocales();
|
|
||||||
// unusedTitleLocales = globalizationHelper
|
|
||||||
// .getAvailableLocales()
|
|
||||||
// .stream()
|
|
||||||
// .filter(locale -> !titleLocales.contains(locale))
|
|
||||||
// .map(Locale::toString)
|
|
||||||
// .collect(Collectors.toList());
|
|
||||||
// targetItemUuid = link.getTargetItem().getItemUuid();
|
|
||||||
// targetItemName = link.getTargetItem().getDisplayName();
|
|
||||||
// targetItemTitle = globalizationHelper.getValueFromLocalizedString(
|
|
||||||
// link.getTargetItem().getTitle()
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
public void setTargetItemTitle(String targetItemTitle) {
|
public void setTargetItemTitle(String targetItemTitle) {
|
||||||
this.targetItemTitle = targetItemTitle;
|
this.targetItemTitle = targetItemTitle;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
class="modal fade"
|
class="modal fade"
|
||||||
id="#{cc.attrs.assetPickerId}-dialog"
|
id="#{cc.attrs.assetPickerId}-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>
|
||||||
|
|
@ -82,7 +82,10 @@
|
||||||
id="#{cc.attrs.assetPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h6>
|
id="#{cc.attrs.assetPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h6>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
<div><strong>#{cc.attrs.dialogTitle}</strong></div>
|
<div class="modal-title"
|
||||||
|
id="#{cc.attrs.assetPickerId}-dialog-title">
|
||||||
|
<strong>#{cc.attrs.dialogTitle}</strong>
|
||||||
|
</div>
|
||||||
</c:otherwise>
|
</c:otherwise>
|
||||||
</c:choose>
|
</c:choose>
|
||||||
<button
|
<button
|
||||||
|
|
@ -127,9 +130,7 @@
|
||||||
<th>#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.column.action']}</th>
|
<th>#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.column.action']}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody></tbody>
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
data-target="##{cc.attrs.assetPickerId}-dialog"
|
data-target="##{cc.attrs.assetPickerId}-dialog"
|
||||||
type="button">
|
type="button">
|
||||||
<bootstrap:svgIcon icon="#{cc.attrs.buttonIcon}" />
|
<bootstrap:svgIcon icon="#{cc.attrs.buttonIcon}" />
|
||||||
<span class="sr-only">#{buttonText}</span>
|
<span class="sr-only">#{cc.attrs.buttonText}</span>
|
||||||
</button>
|
</button>
|
||||||
</cc:implementation>
|
</cc:implementation>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
<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="An component for selecting content items">
|
||||||
|
<cc:attribute name="actionUrl"
|
||||||
|
required="true"
|
||||||
|
shortDescription="Base URL for the actions of the asset picker."
|
||||||
|
type="String" />
|
||||||
|
<cc:attribute name="contentItemType"
|
||||||
|
required="false"
|
||||||
|
shortDescription="Type of the content items to show."
|
||||||
|
type="String"
|
||||||
|
default="org.librecms.contentsection.ContentItem" />
|
||||||
|
<cc:attribute name="contentItemPickerId"
|
||||||
|
required="true"
|
||||||
|
shortDescription="ID of the content item picker."
|
||||||
|
type="String" />
|
||||||
|
<cc:attribute name="contentSection"
|
||||||
|
required="true"
|
||||||
|
shortDescription="The current content section"
|
||||||
|
type="String" />
|
||||||
|
<cc:attribute name="dialogTitle"
|
||||||
|
required="false"
|
||||||
|
shortDescription="Title of the content item picker dialog"
|
||||||
|
default="#{CmsDefaultStepsMessageBundle['contentitempicker.title']}"
|
||||||
|
type="String" />
|
||||||
|
<cc:attribute name="formParamName"
|
||||||
|
required="true"
|
||||||
|
shortDescription="The name of the form parameter that will contain the UUID of the selected asset."
|
||||||
|
type="String" />
|
||||||
|
<cc:attribute name="headingLevel"
|
||||||
|
required="false"
|
||||||
|
shortDescription="The level of the heading used as title of the content item picker dialog."
|
||||||
|
default="3"
|
||||||
|
type="int" />
|
||||||
|
<cc:attribute name="baseUrl"
|
||||||
|
required="true"
|
||||||
|
shortDescription="Base URL for requests. Must include the scheme, the server name, the port (if no standard port is used) and the context path of the application."
|
||||||
|
type="String" />
|
||||||
|
</cc:interface>
|
||||||
|
<cc:implementation>
|
||||||
|
<div class="ccm-cms-contentitem-picker"
|
||||||
|
data-contentitem-type="#{cc.attrs.contentItemType}"
|
||||||
|
data-baseUrl="#{cc.attrs.baseUrl}"
|
||||||
|
data-contentsection="#{cc.attrs.contentSection}"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}">
|
||||||
|
<div aria-hidden="true"
|
||||||
|
aria-labelledby="#{cc.attrs.contentItemPickerId}-dialog-title"
|
||||||
|
class="modal fade"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-dialog"
|
||||||
|
tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-xl">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{cc.attrs.headingLevel == 1}">
|
||||||
|
<h1 class="modal-title"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h1>
|
||||||
|
</c:when>
|
||||||
|
<c:when test="#{cc.attrs.headingLevel == 2}">
|
||||||
|
<h2 class="modal-title"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h2>
|
||||||
|
</c:when>
|
||||||
|
<c:when test="#{cc.attrs.headingLevel == 3}">
|
||||||
|
<h3 class="modal-title"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h3>
|
||||||
|
</c:when>
|
||||||
|
<c:when test="#{cc.attrs.headingLevel == 4}">
|
||||||
|
<h4 class="modal-title"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h4>
|
||||||
|
</c:when>
|
||||||
|
<c:when test="#{cc.attrs.headingLevel == 5}">
|
||||||
|
<h5 class="modal-title"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h5>
|
||||||
|
</c:when>
|
||||||
|
<c:when test="#{cc.attrs.headingLevel == 6}">
|
||||||
|
<h6 class="modal-title"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-dialog-title">#{cc.attrs.dialogTitle}</h6>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<div id="#{cc.attrs.contentItemPickerId}-dialog-title">
|
||||||
|
<strong>#{cc.attrs.dialogTitle}</strong>
|
||||||
|
</div>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
<button
|
||||||
|
aria-label="#{CmsDefaultStepsMessageBundle['contentitempicker.close']}"
|
||||||
|
class="close"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
<bootstrap:svgIcon icon="x" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form action="#{cc.attrs.actionUrl}"
|
||||||
|
class="modal-body"
|
||||||
|
method="post">
|
||||||
|
<input class="contentitempicker-param"
|
||||||
|
id="#{cc.attrs.contentItemPickerId}-param-input"
|
||||||
|
name="#{cc.attrs.formParamName}"
|
||||||
|
type="hidden" />
|
||||||
|
<bootstrap:formGroupText
|
||||||
|
class="contentitempicker-filter"
|
||||||
|
help="#{CmsDefaultStepsMessageBundle['contenitempicker.filter.help']}"
|
||||||
|
inputId="#{cc.attrs.contentItemPickerId}-filter"
|
||||||
|
label="#{CmsDefaultStepsMessageBundle['contenitempicker.filter.label']}"
|
||||||
|
name="" />
|
||||||
|
<template id="#{cc.attrs.contentItemPickerId}-row">
|
||||||
|
<tr>
|
||||||
|
<td class="col-name"></td>
|
||||||
|
<td class="col-type"></td>
|
||||||
|
<td class="col-action">
|
||||||
|
<button class="btn btn-primary"
|
||||||
|
data-itemuuid=""
|
||||||
|
type="button">
|
||||||
|
#{CmsDefaultStepsMessageBundle['contentitempicker.select']}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#{CmsDefaultStepsMessageBundle['contentitempicker.column.name']}</th>
|
||||||
|
<th>#{CmsDefaultStepsMessageBundle['contentitempicker.column.type']}</th>
|
||||||
|
<th>#{CmsDefaultStepsMessageBundle['contentitempicker.column.action']}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
#{CmsDefaultStepsMessageBundle['contentitempicker.close']}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</cc:implementation>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html [<!ENTITY times '×'>]>
|
||||||
|
<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="An component for selecting content items">
|
||||||
|
<cc:attribute name="contentItemPickerId"
|
||||||
|
required="true"
|
||||||
|
shortDescription="ID of the content item picker"
|
||||||
|
type="String" />
|
||||||
|
<cc:attribute name="buttonText"
|
||||||
|
required="true"
|
||||||
|
shortDescription="Label of the button"
|
||||||
|
type="String" />
|
||||||
|
<cc:attribute name="buttonIcon"
|
||||||
|
default="pen"
|
||||||
|
required="false"
|
||||||
|
shortDescription="Icon of the content item picker button"
|
||||||
|
type="String" />
|
||||||
|
</cc:interface>
|
||||||
|
<cc:implementation>
|
||||||
|
<button class="btn btn-primary"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="##{cc.attrs.contentItemPickerId}-dialog"
|
||||||
|
type="button">
|
||||||
|
<bootstrap:svgIcon icon="#{cc.attrs.buttonIcon}" />
|
||||||
|
<span class="sr-only">#{cc.attrs.buttonText}</span>
|
||||||
|
</button>
|
||||||
|
</cc:implementation>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -57,16 +57,64 @@
|
||||||
selectedOptions="#{[CmsLinkDetailsModel.linkType]}"
|
selectedOptions="#{[CmsLinkDetailsModel.linkType]}"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h3>#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.title.target']}</h3>
|
<h3>#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.title.target']}</h3>
|
||||||
|
|
||||||
<div class="d-none relatedlink-target"
|
<div class="d-none relatedlink-target"
|
||||||
id="relatedlink-target-internal">
|
id="relatedlink-target-internal">
|
||||||
<p>ToDo: Content Item Picker</p>
|
<c:choose>
|
||||||
|
<c:when test="#{CmsLinkDetailsModel.targetSet}">
|
||||||
|
<dl>
|
||||||
|
<div>
|
||||||
|
<dt>#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.target.type']}</dt>
|
||||||
|
<dd>#{CmsDefaultStepsMessageBundle['relatedinfo.links.type.internal']}</dd>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<dt>#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.target.item_name']}</dt>
|
||||||
|
<dd>#{CmsLinkDetailsModel.targetItemName}</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<p>
|
||||||
|
#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.target.not_set']}
|
||||||
|
</p>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
<librecms:contentItemPickerButton
|
||||||
|
contentItemPickerId="item-picker"
|
||||||
|
buttonText="#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.title.target.select_targetitem']}"
|
||||||
|
/>
|
||||||
|
<librecms:contentItemPicker
|
||||||
|
actionUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@relatedinfo/attachmentlists/#{CmsLinkDetailsModel.listIdentifier}/links/#{CmsLinkDetailsModel.uuid}/details/@set-target-item"
|
||||||
|
contentItemPickerId="item-picker"
|
||||||
|
baseUrl="#{CmsLinkDetailsModel.baseUrl}"
|
||||||
|
contentSection="#{CmsLinkDetailsModel.sectionName}"
|
||||||
|
formParamName="itemIdentifier"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-none relatedlink-target"
|
<div class="d-none relatedlink-target"
|
||||||
id="relatedlink-target-external">
|
id="relatedlink-target-external">
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{CmsLinkDetailsModel.targetSet}">
|
||||||
|
<dl>
|
||||||
|
<div>
|
||||||
|
<dt>#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.target.type']}</dt>
|
||||||
|
<dd>#{CmsDefaultStepsMessageBundle['relatedinfo.links.type.external']}</dd>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<dt>#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.target.bookmark_name']}</dt>
|
||||||
|
<dd>#{CmsLinkDetailsModel.bookmarkName}</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<p>
|
||||||
|
#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.target.not_set']}
|
||||||
|
</p>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
<librecms:assetPickerButton
|
<librecms:assetPickerButton
|
||||||
assetPickerId="bookmark-picker"
|
assetPickerId="bookmark-picker"
|
||||||
buttonText="#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.title.target.select_bookmark']}"
|
buttonText="#{CmsDefaultStepsMessageBundle['relatedinfo.link.details.title.target.select_bookmark']}"
|
||||||
|
|
|
||||||
|
|
@ -205,3 +205,16 @@ relatedinfo.links.type.help=The type of the link. Internal links are linked with
|
||||||
relatedinfo.link.details.title.target=Target of the related link
|
relatedinfo.link.details.title.target=Target of the related link
|
||||||
relatedinfo.link.details.title.target.select_bookmark=Select bookmark
|
relatedinfo.link.details.title.target.select_bookmark=Select bookmark
|
||||||
relatedinfo.links.type.none_selected=Please select a link type.
|
relatedinfo.links.type.none_selected=Please select a link type.
|
||||||
|
contentitempicker.title=Select content item to use
|
||||||
|
contentitempicker.close=Cancel
|
||||||
|
contenitempicker.filter.help=Filters the content item shown below by name.
|
||||||
|
contenitempicker.filter.label=Filter content items
|
||||||
|
contentitempicker.select=Select
|
||||||
|
contentitempicker.column.name=Name
|
||||||
|
contentitempicker.column.type=Type
|
||||||
|
contentitempicker.column.action=Actions
|
||||||
|
relatedinfo.link.details.title.target.select_targetitem=Select the target of the link
|
||||||
|
relatedinfo.link.details.target.not_set=Target for link has not been set yet.
|
||||||
|
relatedinfo.link.details.target.type=Type
|
||||||
|
relatedinfo.link.details.target.item_name=Target
|
||||||
|
relatedinfo.link.details.target.bookmark_name=Bookmark
|
||||||
|
|
|
||||||
|
|
@ -205,3 +205,16 @@ relatedinfo.links.type.help=Der Typ des Links. Interne Links verweisen auf ein a
|
||||||
relatedinfo.link.details.title.target=Ziel des weiterf\u00fchrenden Links
|
relatedinfo.link.details.title.target=Ziel des weiterf\u00fchrenden Links
|
||||||
relatedinfo.link.details.title.target.select_bookmark=Lesezeichen ausw\u00e4hlen
|
relatedinfo.link.details.title.target.select_bookmark=Lesezeichen ausw\u00e4hlen
|
||||||
relatedinfo.links.type.none_selected=Bitte w\u00e4hlen Sie einen Link-Typ aus.
|
relatedinfo.links.type.none_selected=Bitte w\u00e4hlen Sie einen Link-Typ aus.
|
||||||
|
contentitempicker.title=W\u00e4hlen Sie das Content Item, das verwendet werden soll
|
||||||
|
contentitempicker.close=Abbrechen
|
||||||
|
contenitempicker.filter.help=Filtert die unten angezeigten Content Item nach Name.
|
||||||
|
contenitempicker.filter.label=Content Item filtern
|
||||||
|
contentitempicker.select=Ausw\u00e4hlen
|
||||||
|
contentitempicker.column.name=Name
|
||||||
|
contentitempicker.column.type=Typ
|
||||||
|
contentitempicker.column.action=Aktionen
|
||||||
|
relatedinfo.link.details.title.target.select_targetitem=Ziel des Links ausw\u00e4hlen
|
||||||
|
relatedinfo.link.details.target.not_set=Es wurde noch kein Ziel f\u00fcr den Link gesetzt.
|
||||||
|
relatedinfo.link.details.target.type=Typ
|
||||||
|
relatedinfo.link.details.target.item_name=Ziel
|
||||||
|
relatedinfo.link.details.target.bookmark_name=Lesezeichen
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,6 @@ import "./cms-assetpicker";
|
||||||
|
|
||||||
import "./cms-attachment-lists";
|
import "./cms-attachment-lists";
|
||||||
|
|
||||||
|
import "./cms-contentitempicker";
|
||||||
|
|
||||||
import "./cms-related-link";
|
import "./cms-related-link";
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
import * as $ from "jquery";
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function (event) {
|
||||||
|
const itemPickers = document.querySelectorAll(
|
||||||
|
".ccm-cms-contentitem-picker"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let i = 0; i < itemPickers.length; i++) {
|
||||||
|
initContentItemPicker(itemPickers[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function initContentItemPicker(itemPickerElem: Element) {
|
||||||
|
const itemPickerId = itemPickerElem.getAttribute("id");
|
||||||
|
const itemType = getContentType(itemPickerElem);
|
||||||
|
const baseUrl = itemPickerElem.getAttribute("data-baseUrl");
|
||||||
|
const contentSection = itemPickerElem.getAttribute("data-contentsection");
|
||||||
|
|
||||||
|
console.log(`itemPickerId = ${itemPickerId}`);
|
||||||
|
|
||||||
|
if (!baseUrl) {
|
||||||
|
console.error("No baseUrl provided.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!contentSection) {
|
||||||
|
console.error("No content section provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchUrl = buildFetchUrl(baseUrl, contentSection, itemType);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(fetchUrl);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const items = (await response.json()) as [];
|
||||||
|
|
||||||
|
const rowTemplate = itemPickerElem.querySelector(
|
||||||
|
`#${itemPickerId}-row`
|
||||||
|
) as HTMLTemplateElement;
|
||||||
|
|
||||||
|
const tbody = itemPickerElem.querySelector("tbody");
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
const row = rowTemplate?.content.cloneNode(true) as Element;
|
||||||
|
const colName = row.querySelector(".col-name");
|
||||||
|
const colType = row.querySelector(".col-type");
|
||||||
|
const selectButton = row.querySelector(".col-action button");
|
||||||
|
|
||||||
|
if (colName) {
|
||||||
|
colName.textContent = item["name"];
|
||||||
|
}
|
||||||
|
if (colType) {
|
||||||
|
colType.textContent = item["type"];
|
||||||
|
}
|
||||||
|
selectButton?.setAttribute("data-itemuuid", item["uuid"]);
|
||||||
|
|
||||||
|
selectButton?.addEventListener("click", event =>
|
||||||
|
selectItem(event, itemPickerElem)
|
||||||
|
);
|
||||||
|
|
||||||
|
tbody?.appendChild(row);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`Error. Status: ${response.status}. Status Text: ${response.statusText}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildFetchUrl(
|
||||||
|
baseUrl: string,
|
||||||
|
contentSection: string,
|
||||||
|
itemType: string
|
||||||
|
) {
|
||||||
|
if (itemType && itemType !== "org.librecms.contentsection.ContentItem") {
|
||||||
|
return `${baseUrl}/content-sections/${contentSection}/items?type=${itemType}&version=draft`;
|
||||||
|
} else {
|
||||||
|
return `${baseUrl}/content-sections/${contentSection}/items?version=draft`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContentType(itemPickerElem: Element):string {
|
||||||
|
if (itemPickerElem.hasAttribute("data-contentitem-type")) {
|
||||||
|
const result = itemPickerElem.getAttribute("data-contentitem-type");
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return "org.librecms.contentsection.ContentItem";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "org.librecms.contentsection.ContentItem";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectItem(event: Event, itemPickerElem: Element) {
|
||||||
|
const selectButton = event.currentTarget as Element;
|
||||||
|
const itemUuid = selectButton.getAttribute("data-itemuuid");
|
||||||
|
if (!itemUuid) {
|
||||||
|
console.error("itemUuid is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemPickerParam = itemPickerElem.querySelector(
|
||||||
|
".contentitempicker-param"
|
||||||
|
) as HTMLInputElement;
|
||||||
|
if (!itemPickerParam) {
|
||||||
|
console.error("contentItemPickerParam is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
itemPickerParam.value = `UUID-${itemUuid}`;
|
||||||
|
|
||||||
|
const form = itemPickerElem.querySelector("form") as HTMLFormElement;
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue