/o//commerce-media/accounts/-1/images/18566750?download=true
Tweed
Collaboration & Knowledge Sharing
描述
The Tweed Twitter Timeline plugin portlet allows you to display a
fully-rendered user timeline for a specified public Twitter account. The
timeline is rendered dynamically, with new Tweets appearing periodically
at the top of the timeline. Simply add the portlet from the social
category of the Applications library, configure the portlet with the
Twitter username and optionally a height parameter, and that's it!
The Tweed Twitter Timeline plugin portlet allows you to display a
fully-rendered user timeline for a specified public Twitter account. The
timeline is rendered dynamically, with new Tweets appearing periodically
at the top of the timeline. Simply add the portlet from the social
category of the Applications library, configure the portlet with the
Twitter username and optionally a height parameter, and that's it!
DEVELOPER
处理模板时发生错误。
The string doesn't match the expected date/time/date-time format. The string to parse was: "0". The expected format was: "yyyy-MM-dd'T'HH:mm:ss'Z'".
The nested reason given follows:
Unparseable date: "0"
----
FTL stack trace ("~" means nesting-related):
- Failed at: #assign parsedDate = createDate?datet... [in template "3192443#3192485#null" at line 58, column 17]
~ Reached through: #nested [in template "3192443#3192485#null" in macro "section" at line 246, column 17]
~ Reached through: @section title=languageUtil.get(local... [in template "3192443#3192485#null" at line 56, column 1]
----
1<#assign
2 channel = restClient.get("/headless-commerce-delivery-catalog/v1.0/channels?accountId=-1&filter=name eq 'Marketplace Channel' and siteGroupId eq '${themeDisplay.getScopeGroupId()}'")
3
4 product = restClient.get(
5 "/headless-commerce-delivery-catalog/v1.0/channels/" + channel.items[0].id +
6 "/products/" + CPDefinition_cProductId.getData() +
7 "?accountId=-1&nestedFields=categories,productSpecifications,skus&skus.accountId=-1&skus.currencyCode=USD"
8 )
9
10 catalogName = product.catalogName!""
11 categories = product.categories![]
12 createDate = product.createDate!0
13 productSpecifications = product.productSpecifications![]
14
15 liferayVersions = productSpecifications?filter(item -> stringUtil.equals(item.specificationKey, "liferay-version"))
16 platformOffering = categories?filter(item -> stringUtil.equals(item.vocabulary?replace(" ", "-"), "marketplace-liferay-platform-offering"))
17>
18
19<#assign
20 publisherDetailsResponse = restClient.get("/c/publisherdetailses?filter=publisherName eq '${catalogName}'")
21 redirectPath = "https://marketplace.liferay.com/e/publisher-details/29282497"
22/>
23
24<#if publisherDetailsResponse.items?has_content>
25 <#assign
26 publisherDetails = publisherDetailsResponse.items[0]
27 profileImageURL = publisherDetails.publisherProfileImage?replace("https://", "http://")
28 />
29</#if>
30
31<#assign
32 appDocumentationURL = getSpecificationValue("appdocumentationurl")
33 appInstallationGuideURL = getSpecificationValue("appinstallationguideurl")
34 appUsageTerms = getSpecificationValue("appusagetermsurl")
35 cpuValue = getSpecificationValue("cpu")
36 developerName = getSpecificationValue("developer-name", catalogName)
37 publisherURL = (getSpecificationValue("publisherwebsiteurl")?trim?replace(" ", ""))!""
38 ramValue = getSpecificationValue("ram")
39 sourceCode = getSpecificationValue("source-code-url")
40 supportEmail = getSpecificationValue("supportemailaddress")
41 supportPhone = getSpecificationValue("supportphone")
42 type = getSpecificationValue("type")?lower_case
43>
44<@section title = languageUtil.get(locale, "developer")>
45 <#if publisherDetails?has_content>
46 <a class = "bg-neutral-8" href = "${redirectPath}/${publisherDetails.id}">
47 ${developerName}
48 </a>
49 <#else>
50 <a class = "bg-neutral-8" href = "/?developer-name=${developerName}">
51 ${developerName}
52 </a>
53 </#if>
54</@section>
55
56<@section title = languageUtil.get(locale, "publisher-date", "Publisher Date")>
57 <#if createDate?has_content>
58 <#assign parsedDate = createDate?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") />
59
60 <p>${parsedDate?string("MMMM d, yyyy")}</p>
61 </#if>
62</@section>
63
64<@section title = languageUtil.get(locale, "deployment-method", "Deployment Method")>
65 <#list platformOffering as offering>
66 <p>${offering.name}</p>
67 </#list>
68</@section>
69
70<@section title = languageUtil.get(locale, "app-type", "App Type")>
71 <#if type == 'client-extension'> Client Extension </#if>
72 <#if type == 'cloud'> Cloud </#if>
73 <#if type == 'composite-app'> Composite App </#if>
74 <#if type == 'dxp'> DXP </#if>
75 <#if type == 'low-code-configuration'> Low Code Configuration </#if>
76</@section>
77
78<@section title = languageUtil.get(locale, "version")>
79 ${getSpecificationValue("latest-version", "1.0.0")}
80</@section>
81
82<#if liferayVersions?has_content>
83 <@section title = languageUtil.get(locale, "supported-versions", "Supported Versions")>
84 <#list liferayVersions as version>
85 ${version.value}<#if version?has_next>, </#if>
86 </#list>
87 </@section>
88</#if>
89
90<#if cpuValue?has_content>
91 <@section title = languageUtil.get(locale, "resource-requirements", "Resource Requirements")>
92 <p>
93 <#if cpuValue?has_content>
94 ${cpuValue}
95 <#assign cpuNumber = cpuValue?number?default(0) />
96 <#if cpuValue?eval gt 1>
97 CPUS
98 </#if>
99 <#if cpuValue?eval lt 2>
100 CPU
101 </#if>
102 </#if>, <#if ramValue?has_content>${ramValue} GB RAM</#if>
103 </p>
104 </@section>
105</#if>
106
107<@section title = languageUtil.get(locale, "standard-price", "Standard Price")>
108 <div>
109 <#assign purchasableSkus = [] />
110
111 <#list product.skus as sku>
112 <#if sku.purchasable?? && sku.purchasable>
113 <#assign purchasableSkus = purchasableSkus + [sku] />
114 </#if>
115 </#list>
116
117 <#assign standardSku = {} />
118
119 <#list purchasableSkus as sku>
120 <#assign matched = false />
121
122 <#list sku.skuOptions as opt>
123 <#if stringUtil.equals(opt.skuOptionValueKey, "standard")>
124 <#assign
125 matched = true
126 standardSku = sku
127 />
128
129 <#break>
130 </#if>
131 </#list>
132 <#if matched><#break></#if>
133 </#list>
134
135 <#if standardSku.price?? && standardSku.price.price?eval gt 0>
136 <div class="bg-neutral-8">${standardSku.price.priceFormatted!""}</div>
137 <#else>
138 ${languageUtil.get(locale, "free", "Free")}
139 </#if>
140 </div>
141</@section>
142
143<@section title = languageUtil.get(locale, "help-and-support", "Help and Support")>
144 <div class="d-flex flex-column mt-4">
145 <#if (appDocumentationURL?has_content || appInstallationGuideURL?has_content)>
146 <div class="d-flex mb-4">
147 <span class="help-and-support-modal-icon" id="installation-documentation">
148 <@clay["icon"] symbol="document" />
149 </span>
150
151 <a class="d-flex w-100 justify-content-between help-and-support-modal" href="javascript:void(0)" onClick="openInstallationDocsModal()">
152 <span class="copy-text ml-1 help-and-support-modal">
153 ${languageUtil.get(locale, "installation-documentation", "Installation Documentation")}
154 </span>
155
156 <@clay["icon"]
157 className="help-and-support-modal-arrow link-arrow ml-auto"
158 height="12"
159 symbol="angle-right-small"
160 />
161 </a>
162 </div>
163 </#if>
164
165 <div class="d-flex mb-4">
166 <span class="help-and-support-modal-icon" id="publisher-support">
167 <@clay["icon"] symbol="envelope-closed" />
168 </span>
169
170 <a class="d-flex w-100 justify-content-between help-and-support-modal" href="javascript:void(0)" onClick="openPublisherSupportModal()">
171 <span class="copy-text ml-1 help-and-support-modal">
172 ${languageUtil.get(locale, "publisher-support", "Publisher Support")}
173 </span>
174
175 <@clay["icon"]
176 className="help-and-support-modal-arrow link-arrow ml-auto"
177 height="12"
178 symbol="angle-right-small"
179 />
180 </a>
181 </div>
182
183 <#if sourceCode?has_content>
184 <div class="d-flex mb-4">
185 <span class="help-and-support-link-icon">
186 <@clay["icon"] symbol="code" />
187 </span>
188
189 <a
190 class="d-flex font-weight-semi-bold help-and-support-link justify-content-between w-100"
191 href="${sourceCode}"
192 target="_blank">
193 <span class="copy-text ml-1 help-and-support-link">
194 ${languageUtil.get(locale, "source-code", "Source Code")}
195 </span>
196 </a>
197 </div>
198 </#if>
199
200 <div class="d-flex">
201 <span class="help-and-support-link-icon">
202 <@clay["icon"] symbol="check-square" />
203 </span>
204
205 <a
206 class="d-flex font-weight-semi-bold help-and-support-link justify-content-between w-100"
207 href="${(appUsageTerms?has_content)?then(appUsageTerms, 'https://marketplace.liferay.com/license-agreement')}"
208 target="_blank">
209
210 <span class="copy-text ml-1 help-and-support-link">
211 ${languageUtil.get(locale, "eula", "EULA")}
212 </span>
213 </a>
214 </div>
215 </div>
216</@section>
217
218<@section
219 showLine = false
220 title = languageUtil.get(locale, "share-link")
221>
222 <a class="align-items-center copy-text d-flex font-weight-bold ml-1 text-primary" href="#copy-share-link" onclick="copyToClipboard(Liferay.ThemeDisplay.getCanonicalURL())">
223 <span class="help-and-support-link-icon mr-1">
224 <@clay["icon"] symbol="link" />
225 </span>
226 Copy & Share
227 </a>
228</@section>
229
230<#function getSpecificationValue key default="">
231 <#local spec = productSpecifications?filter(productSpecification ->
232 stringUtil.equals(productSpecification.specificationKey, key)) />
233
234 <#return (spec?first.value)!default />
235</#function>
236
237<#macro section
238 title
239 showLine=true
240>
241 <p>
242 <strong>${title}</strong>
243 </p>
244
245 <div>
246 <#nested>
247 </div>
248
249 <#if showLine>
250 <hr />
251 </#if>
252</#macro>
253
254<script ${nonceAttribute}>
255 function installationDocsModalBody() {
256 return `
257 <#if appDocumentationURL?has_content>
258 <div class="d-flex flex-row align-items-center mb-3">
259 <span class="align-items-center d-flex justify-content-center modal-icon-background mr-3" style="background: #E2E2E4; border-radius:50%; height:40px; overflow:hidden; width:40px;">
260 <@clay["icon"]
261 style="fill:#6B6C7E;"
262 symbol="document-code"
263 />
264 </span>
265
266 <div class="d-flex flex-column">
267 <span class="text-black-50">${languageUtil.get(locale, "app-documentation-url", "App Documentation URL")}</span>
268
269 <a class="font-weight-bold" href="tel:${appDocumentationURL}" target="_blank">
270 ${appDocumentationURL}
271 </a>
272 </div>
273 </div>
274 </#if>
275
276 <#if appInstallationGuideURL?has_content>
277 <div class="d-flex flex-row align-items-center mb-4">
278 <span class="align-items-center d-flex justify-content-center modal-icon-background mr-3" style="background: #E2E2E4; border-radius:50%; height:40px; overflow:hidden; width:40px;">
279 <@clay["icon"]
280 style="fill:#6B6C7E;"
281 symbol="document"
282 />
283 </span>
284
285 <div class="d-flex flex-column">
286 <span class="text-black-50">${languageUtil.get(locale, "app-installation-guide-url", "App Installation Guide URL")}</span>
287
288 <a class="font-weight-bold" href="tel:${appInstallationGuideURL}" target="_blank">
289 ${appInstallationGuideURL}
290 </a>
291 </div>
292 </div>
293 </#if>
294 `;
295 }
296
297 function publisherSupportModalBody() {
298 return `
299 <div class="align-items-center d-flex flex-row mb-3">
300 <span class="align-items-center d-flex justify-content-center modal-icon-background mr-3" style="background: #E2E2E4; border-radius:50%; height:40px; overflow:hidden; width:40px;">
301 <#if profileImageURL?? && profileImageURL?length gt 0>
302 <img src="${profileImageURL}" alt="Publisher Image" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%;" />
303 <#else>
304 <@clay["icon"]
305 style="fill:#6B6C7E;"
306 symbol="picture"
307 />
308 </#if>
309 </span>
310
311 <div class="d-flex flex-column">
312 <h3 class="font-weight-bold mb-0">
313 ${catalogName}
314 </h3>
315 </div>
316 </div>
317
318 <#if publisherURL?has_content>
319 <div class="align-items-center d-flex flex-row mb-3">
320 <span class="align-items-center d-flex justify-content-center modal-icon-background mr-3" style="background: #E2E2E4; border-radius:50%; height:40px; overflow:hidden; width:40px;">
321 <@clay["icon"]
322 style="fill:#6B6C7E;"
323 symbol="globe"
324 />
325 </span>
326
327 <div class="d-flex flex-column">
328 <span class="text-black-50">${languageUtil.get(locale, "publisher-website", "Publisher Website")}</span>
329
330 <a href="${publisherURL}" target="_blank" class="font-weight-bold">
331 ${publisherURL}
332 </a>
333 </div>
334 </div>
335 </#if>
336
337 <#if supportEmail?has_content>
338 <div class="align-items-center d-flex flex-row mb-3">
339 <span class="align-items-center d-flex justify-content-center modal-icon-background mr-3" style="background: #E2E2E4; border-radius:50%; height:40px; overflow:hidden; width:40px;">
340 <@clay["icon"] style="fill:#6B6C7E;"symbol="envelope-closed" />
341 </span>
342
343 <div class="d-flex flex-column">
344 <span class="text-black-50">${languageUtil.get(locale, "support-email", "Support Email")}</span>
345
346 <a class="font-weight-bold" href="mailto:${supportEmail}" target="_blank">
347 ${supportEmail}
348 </a>
349 </div>
350 </div>
351 </#if>
352
353 <#if supportPhone?has_content>
354 <div class="d-flex flex-row align-items-center mb-3">
355 <span class="align-items-center d-flex justify-content-center modal-icon-background mr-3" style="background: #E2E2E4; border-radius:50%; height:40px; overflow:hidden; width:40px;">
356 <@clay["icon"]
357 style="fill:#6B6C7E;"
358 symbol="phone"
359 />
360 </span>
361
362 <div class="d-flex flex-column">
363 <span class="text-black-50">${languageUtil.get(locale, "phone")}</span>
364
365 <a class="font-weight-bold" href="tel:${supportPhone}" target="_blank">
366 ${supportPhone}
367 </a>
368 </div>
369 </div>
370 </#if>
371 `;
372 }
373
374 function openInstallationDocsModal() {
375 Liferay.Util.openModal({
376 bodyHTML: installationDocsModalBody(),
377 center: true,
378 headerHTML: "<h2>Installation Guide</h2>",
379 size: "md"
380 });
381 }
382
383 function openPublisherSupportModal() {
384 Liferay.Util.openModal({
385 bodyHTML: publisherSupportModalBody(),
386 center: true,
387 headerHTML: "<h2>Publisher Support Info</h2>",
388 size: "md"
389 });
390 }
391</script>
392
393<script ${nonceAttribute}>
394 function copyToClipboard(text) {
395 if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
396 navigator.clipboard.writeText(text);
397
398 Liferay.Util.openToast({ message: "Copied link to the clipboard" });
399 }
400 }
401</script>
402
403<style ${nonceAttribute}>
404 .copy-text {
405 color: #282934;
406 font-size: 16px;
407 }
408
409 .help-and-support-modal {
410 color: inherit;
411 text-decoration: none;
412 }
413
414 .help-and-support-modal-arrow {
415 margin-top: 3px;
416 fill: rgb(133, 140, 148);
417 }
418
419 .help-and-support-modal:hover {
420 color: inherit;
421 text-decoration: none;
422 }
423
424 .help-and-support-modal-icon {
425 color: rgb(133, 140, 148);
426 }
427
428 .help-and-support-link {
429 color: #0053F0 !important;
430 }
431
432 .help-and-support-link:hover {
433 color: #0041BE !important;
434 text-decoration: underline !important;
435 }
436
437 .help-and-support-link-icon {
438 color: #0053F0 !important;
439 }
440
441 .help-and-support-svg mask,
442 .link-arrow mask {
443 mask-type: alpha;
444 }
445</style>
DEVELOPER
24-11-21 下午6:20
Published date
24-11-21 下午6:20
Published Date
24-11-21 下午6:20
SUPPORTED OFFERINGS
Liferay PaaS
Supported Versions
6.2
Resource Requirements
Edition
Community
PRICE
Free
SHARE LINK
HTML Example
A paragraph is a self-contained unit of a discourse in writing dealing with a particular point or idea. Paragraphs are usually an expected part of formal writing, used to organize longer prose.