An error occurred while processing the template.
The following has evaluated to null or missing:
==> ddmFormFieldValue.getValue().getString(locale) [in template "64612643129409#230641#233264" at line 15, column 32]
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: #assign value = ddmFormFieldValue.get... [in template "64612643129409#230641#233264" in function "getFieldValue" at line 15, column 17]
----
1<#setting url_escaping_charset='UTF-8'/>
2
3<#assign SiteGroup = themeDisplay.getSiteGroup() />
4<#assign displayUrl = SiteGroup.getDisplayURL(themeDisplay) />
5<#assign currentUrl = themeDisplay.getLayout().getFriendlyURL() />
6
7<#function decodeUrlString str>
8 <#return str?replace("%20", " ", "r")>
9</#function>
10
11<#function getFieldValue ddmFormFieldValues fieldReference>
12 <#list ddmFormFieldValues as ddmFormFieldValue>
13 <#if ddmFormFieldValue.getDDMFormField().getFieldReference()==fieldReference>
14 <#if (ddmFormFieldValue.getValue())??>
15 <#assign value=ddmFormFieldValue.getValue().getString(locale) />
16 <#return value />
17 <#else>
18 <#return null />
19 </#if>
20 </#if>
21 </#list>
22 <#return null />
23</#function>
24
25
26<#function getCategoryDetails categories>
27 <#assign categoryDetailsList = [] />
28 <#if categories?has_content>
29 <#list categories as category>
30 <#assign categoryName = decodeUrlString(category.getName()) />
31 <#assign categoryID = category.getCategoryId()?string />
32 <#assign categoryUrl = "#/?category=" + category.getName()?url />
33 <#assign categoryDetail = {"name": categoryName, "id": categoryID, "url": categoryUrl} />
34 <#assign categoryDetailsList = categoryDetailsList + [categoryDetail] />
35 </#list>
36 </#if>
37 <#return categoryDetailsList>
38</#function>
39
40<#if entries?has_content>
41 <section class="article-list-publisher clearfix">
42 <#assign row=1 />
43 <#list entries as curEntry>
44 <#assign assetRenderer = curEntry.getAssetRenderer() />
45 <#assign viewURL = assetRenderer.getURLViewInContext(renderRequest, renderResponse, viewURL) />
46 <#assign viewAssetPubURL = assetPublisherHelper.getAssetViewURL(renderRequest, renderResponse, entry) />
47 <#assign ddmFormValuesReader = assetRenderer.getDDMFormValuesReader() />
48 <#assign ddmFormFieldValues = ddmFormValuesReader.getDDMFormValues().getDDMFormFieldValues() />
49
50 <#-- Process categories -->
51 <#assign categories = curEntry.getCategories() />
52 <#assign categoryDetails = getCategoryDetails(categories) />
53 <#assign categoryNamesList = [] />
54 <#assign categoryUrlsList = [] />
55 <#assign categoryIDsList = [] />
56 <#list categoryDetails as detail>
57 <#assign categoryNamesList = categoryNamesList + [detail.name] />
58 <#assign categoryUrlsList = categoryUrlsList + [detail.url] />
59 <#assign categoryIDsList = categoryIDsList + [detail.id] />
60 </#list>
61 <#assign categoryNames = categoryNamesList?join(", ") />
62 <#assign categoryUrls = categoryUrlsList?join(",") />
63 <#assign categoryIDs = categoryIDsList?join(",") />
64
65 <#-- Get image from article -->
66 <#assign articleImage = getFieldValue(ddmFormFieldValues, 'featuredImage') />
67 <#assign articleImage_map = jsonFactoryUtil.createJSONObject(articleImage) />
68
69 <#-- Get article title -->
70 <#assign articleTitle = htmlUtil.escape(assetRenderer.getTitle(locale)) />
71
72 <#-- Get articleBody from news article structure, shorten to 200 signs -->
73 <#assign plainDescription = htmlUtil.escape(curEntry.getDescription(locale)) />
74 <#assign cleanedDescription = plainDescription?replace('<', '<')?replace('>', '>')?replace('&', '&')?replace(' ', ' ')?replace('<[^>]*>', '', 'r') />
75 <#assign articleDescription = stringUtil.shorten(cleanedDescription, 200) />
76
77 <#--Show all link, this is hardcoded, should be fetched from articles display page-->
78 <#assign allArticlesLink = "article-archive" />
79
80 <#--Fetch create date from article-->
81 <#assign publishDate = curEntry.createDate?datetime />
82
83 <#switch locale>
84 <#-- Add or modify date formats for additional locales as needed -->
85 <#case "de_DE"> <#assign dateTimeFormat = "dd.MM.yyyy"> <#break>
86 <#case "en_GB"> <#assign dateTimeFormat = "dd/MM/yyyy"> <#break>
87 <#case "en_NZ"> <#assign dateTimeFormat = "dd/MM/yyyy"> <#break>
88 <#case "en_US"> <#assign dateTimeFormat = "M/d/yyyy"> <#break>
89 <#case "fi_FI"> <#assign dateTimeFormat = "d.M.yyyy"> <#break>
90 <#case "fr_FR"> <#assign dateTimeFormat = "dd/MM/yyyy"> <#break>
91 <#case "nb_NO"> <#case "nn_NO"> <#assign dateTimeFormat = "dd.MM.yyyy"> <#break>
92 <#case "ru_FI"> <#assign dateTimeFormat = "dd.MM.yyyy"> <#break>
93 <#case "sv_SE"> <#assign dateTimeFormat = "yyyy-MM-dd"> <#break>
94 <#default><#assign dateTimeFormat = "yyyy-MM-dd"> <#break>
95 </#switch>
96
97 <#--Format date object-->
98 <#assign publishDate = publishDate?string(dateTimeFormat)>
99
100 <div class="asset-actions lfr-meta-actions clearfix"><@getEditIcon /></div>
101 <div class="news-list-container no-gutters row">
102 <a class="col-md-12" href="${viewURL}" tabindex="0" aria-label="<@liferay.language key='to.the.article'/> ${articleTitle}">
103 <div class="row no-gutters">
104 <#if (articleImage_map.url)?? >
105 <#assign articleImage = articleImage_map.url />
106 <#if (articleImage)?? >
107 <div class="article-news-header col-md-8">
108 <img src="${articleImage}" alt="${articleImage_map.alt}" loading="lazy"
109 class="img-fluid">
110 </div>
111 </#if>
112 </#if>
113
114 <#assign u_id = (.now?long)?c />
115 <article aria-labelledby="${u_id}" class="article-news-container col-md-4 <#if (row % 2) == 0>order-md-first</#if>">
116 <h2 id="${u_id}" class="article-news-title">${articleTitle}</h2>
117 <div class="article-news-summary">${articleDescription}</div>
118 <div class="article-publish">
119 <#if (categoryNamesList?size > 0)>
120 <span>
121 <@liferay.language key="category"/>:
122 <#list categoryDetails as detail>
123 <#assign categoryUrl = "${displayUrl}/article-archive/-/categories/" + detail.id />
124 <button
125 class="category-button position-relative z-2 btn btn-unstyled"
126 data-url="${categoryUrl}"
127 title="${detail.name}"
128 aria-label="<@liferay.language key="view.all.category.articles"/> ${detail.name}">
129 ${detail.name}
130 </button><#if detail_has_next>, </#if>
131 </#list>
132 </span>
133 <br>
134 </#if>
135 <span><@liferay.language key="published"/>: ${publishDate}</span>
136 </div>
137 </article>
138 </div>
139 </a>
140 </div>
141 <#assign row = row + 1 />
142 </#list>
143
144 <#-- Add Show all article link -->
145 <#if !currentUrl?contains("article-archive")>
146 <div class="all-articles">
147 <a class="all-articles-link" href="${displayUrl}/article-archive"
148 title="<@liferay.language key="view-all"/> ${categoryNames}"
149 aria-label="<@liferay.language key="view-all"/> ${categoryNames}">
150 <span><@liferay.language key="view-all" /></span>
151 </a>
152 </div>
153 </#if>
154 </section>
155</#if>
156
157
158<script>
159 document.addEventListener ('DOMContentLoaded', function () {
160 if ( window.location.href.includes ("categories") ) {
161 var baseUrl = '${displayUrl}${currentUrl}';
162 var categoriesSelect = document.querySelector (".categories");
163 var categoryName = categoriesSelect.getAttribute ('data-category-name');
164 var breadcrumbList = document.querySelector (".breadcrumb");
165 var newListItem = document.createElement ("li");
166 newListItem.className = "breadcrumb-item";
167 newListItem.innerHTML = '<span class="active breadcrumb-text-truncate breadcrumb-category">' + categoryName + '</span>';
168 breadcrumbList.appendChild (newListItem);
169 var breadcrumbItems = document.querySelectorAll ('.breadcrumb-item');
170 breadcrumbItems.forEach (function (item) {
171 if ( item.textContent.trim () === "Article archive" ) {
172 var archiveLink = document.createElement ('a');
173 archiveLink.href = baseUrl;
174 archiveLink.classList.add ("breadcrumb-link");
175 archiveLink.innerHTML = item.innerHTML;
176 item.innerHTML = '';
177 item.appendChild (archiveLink);
178 }
179 });
180 }
181 });
182 document.addEventListener ('DOMContentLoaded', function () {
183 const buttons = document.querySelectorAll ('.category-button');
184 buttons.forEach (button => {
185 button.addEventListener ('click', function (event) {
186 event.stopPropagation ();
187 event.preventDefault ();
188 const url = this.getAttribute ('data-url');
189 if ( url ) {
190 window.location.href = url;
191 }
192 });
193 });
194 });
195</script>
196
197
198<#macro getEditIcon>
199 <#if assetRenderer.hasEditPermission(themeDisplay.getPermissionChecker())>
200 <#assign redirectURL = renderResponse.createRenderURL() />
201
202 ${redirectURL.setParameter("struts_action", "/asset_publisher/add_asset_redirect")}
203 ${redirectURL.setWindowState("pop_up")}
204
205 <#assign editPortletURL = assetRenderer.getURLEdit(renderRequest, renderResponse, windowStateFactory.getWindowState("pop_up"), redirectURL) />
206
207 <#if validator.isNotNull(editPortletURL)>
208 <#assign title = languageUtil.format(locale, "edit-x", htmlUtil.escape(assetRenderer.getTitle(locale))) />
209
210 <@liferay_ui["icon"]
211 <#--image="edit"-->
212 iconCssClass="icon-edit"
213 message=title
214 url="javascript:Liferay.Util.openWindow({dialog: {destroyOnHide: true, width: 960}, id:'" + renderResponse.getNamespace() + "editAsset', title: '" + title + "', uri:'" + htmlUtil.escapeURL(editPortletURL.toString()) + "'});"
215 />
216 </#if>
217 </#if>
218</#macro>