Last active
December 8, 2017 15:43
-
-
Save aertmann/0d280c31f787f889eab7 to your computer and use it in GitHub Desktop.
News with inline editable headline & lead & image, list view with ajax loading, overview, single view, tagging and RSS using News document node type and Elasticsearch for Neos – Included in https://speakerdeck.com/aertmann/tasty-recipes-for-every-day-neos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{namespace neos=TYPO3\Neos\ViewHelpers} | |
{namespace media=TYPO3\Media\ViewHelpers} | |
<f:layout name="Page" /> | |
<f:section name="body"> | |
<article itemscope="" itemtype="http://schema.org/Article" xmlns:f="http://www.w3.org/1999/html"> | |
<header> | |
<f:if condition="{tags}"> | |
<f:for each="{tags}" as="articleTag" iteration="iterator"> | |
<f:if condition="{iterator.isFirst}"> | |
<span class="tag">{articleTag.properties.title}</span> | |
</f:if> | |
</f:for> | |
</f:if> | |
<neos:contentElement.wrap node="{node}"> | |
<neos:contentElement.editable property="title" tag="h1" /> | |
</neos:contentElement.wrap> | |
<f:if condition="{author}"> | |
<span itemprop="author" itemscope="" itemtype="http://schema.org/Person">By <span itemprop="name">{author}</span></span> | |
</f:if> | |
<neos:contentElement.wrap node="{image}"> | |
<figure> | |
<f:if condition="{image.properties.image}"> | |
<f:then> | |
<f:alias map="{imageUrl: '{media:uri.image(asset: image.properties.image, maximumWidth: 720, maximumHeight: 500, allowCropping: 1, allowUpScaling: 1)}'}"> | |
<meta itemprop="image" content="{imageUrl}" /> | |
<img src="{imageUrl}" alt="{image.properties.alternativeText}" title="{image.properties.title}" /> | |
</f:alias> | |
<f:if condition="{image.properties.hasCaption}"> | |
<figcaption> | |
<neos:contentElement.editable property="caption" node="{image}" /> | |
</figcaption> | |
</f:if> | |
</f:then> | |
<f:else> | |
<f:security.ifAccess resource="TYPO3_Neos_Backend_GeneralAccess"> | |
<f:if condition="{node.context.workspace.name} != 'live'"> | |
<img src="{f:uri.resource(package: 'TYPO3.Neos', path: 'Images/dummy-image.svg')}" title="Dummy image" alt="Dummy image" /> | |
<figcaption> | |
<neos:contentElement.editable property="caption" node="{image}" /> | |
</figcaption> | |
</f:if> | |
</f:security.ifAccess> | |
</f:else> | |
</f:if> | |
</figure> | |
</neos:contentElement.wrap> | |
<neos:contentElement.wrap node="{node}"> | |
<neos:contentElement.editable property="lead" tag="p" class="lead" /> | |
</neos:contentElement.wrap> | |
<div class="byline"> | |
<time datetime="{f:format.date(date: node.properties.datePublished, format: 'c')}" itemprop="datePublished"><f:format.date format="d/m-Y">{node.properties.datePublished}</f:format.date></time> | |
</div> | |
</header> | |
<div itemprop="articleBody"> | |
{content.main -> f:format.raw()} | |
</div> | |
</article> | |
</f:section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
prototype(Acme.News:Article) > | |
prototype(Acme.News:Article) < prototype(Page) { | |
head.head { | |
openGraphImage = ${q(node).children('image').property('image')} | |
article = true | |
datePublished = ${q(node).property('datePublished')} | |
tags = ${q(node).property('tags')} | |
description = ${q(node).property('lead')} | |
} | |
body { | |
node = ${node} | |
title = ${q(node).property('title')} | |
datePublished = ${q(node).property('datePublished')} | |
lead = ${q(node).property('lead')} | |
image = ${q(node).children('image').get(0)} | |
caption = ${q(node).children('image').property('caption')} | |
alternativeText = ${q(node).property('alternativeText')} | |
author = ${q(node).property('author')} | |
tags = ${q(node).property('tags')} | |
tagSearchFilter = TYPO3.TypoScript:RawArray { | |
tags = ${Indexing.convertArrayOfNodesToArrayOfNodeIdentifiers(q(node).property('tags'))} | |
tags.@if.notEmpty = ${q(node).property('tags')} | |
} | |
# Can't use __identifier as a key name in TypoScript so we had to come up with this | |
identifierSearchFilter = Acme.News:RawArray { | |
key = '__identifier' | |
value = TYPO3.TypoScript:RawArray { | |
0 = ${node.nodeData.identifier} | |
} | |
} | |
searchQuery = ${Search.query(site).nodeType('Acme.News:Article')} | |
filteredSearchQuery = ${this.tagSearchFilter.tags != null ? this.searchQuery.queryFilter('terms', this.tagSearchFilter) : this.searchQuery} | |
@override.searchResults = ${this.filteredSearchQuery.queryFilter('terms', this.identifierSearchFilter, 'must_not').sortDesc('datePublished').limit(5).execute().nodes} | |
searchResults = ${searchResults} | |
hasRelated = ${this.searchResults != null && Array.length(this.searchResults) > 0} | |
relatedArticles = TYPO3.TypoScript:Collection { | |
collection = ${searchResults} | |
itemRenderer = 'Acme.News:RelatedArticle' | |
itemName = 'article' | |
prototype(TYPO3.Neos:Content) { | |
@process.contentElementWrapping > | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{namespace neos=TYPO3\Neos\ViewHelpers} | |
<section{attributes -> f:format.raw()}> | |
<f:if condition="{node.properties.header}"> | |
<h1 class="news-list-header">{node.properties.header -> f:format.raw()}</h1> | |
</f:if> | |
<f:render partial="NewsListArticles" arguments="{_all}" /> | |
<f:if condition="{canLoadMore}"> | |
<a href="?offset={nextOffset}" class="view-more-link">Load more</a> | |
</f:if> | |
</section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
prototype(Acme.News:List) { | |
attributes.class = 'news-list' | |
limit = 10 | |
count = ${Search.query(site).nodeType('Acme.News:Article').count()} | |
articles = ${Search.query(site).nodeType('Acme.News:Article').sortDesc('datePublished').limit(this.limit).execute().nodes} | |
nextOffset = ${this.limit} | |
canLoadMore = ${this.nextOffset < this.count} | |
@cache { | |
mode = 'cached' | |
entryIdentifier { | |
node = ${node} | |
} | |
entryTags { | |
1 = ${'NodeType_Acme.News:Article'} | |
2 = ${'Node_' + node.identifier} | |
} | |
maximumLifetime = 3600 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<f:if condition="{nextOffset} <= {count}"> | |
<f:render partial="NewsListArticles" arguments="{_all}" /> | |
<f:if condition="{nextOffset} < {count}"> | |
<a href="?offset={nextOffset}" class="view-more-link">Load more</a> | |
</f:if> | |
</f:if> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
listAjax = TYPO3.TypoScript:Template { | |
templatePath = 'resource://Acme.News/Private/Templates/NodeTypes/ListAjax.html' | |
count = ${Search.query(site).nodeType('Acme.News:Article').count()} | |
limit = 10 | |
offset = ${String.toInteger(request.arguments.offset)} | |
nextOffset = ${this.limit + this.offset} | |
canLoadMore = ${this.nextOffset < this.count} | |
articles = ${Search.query(site).nodeType('Acme.News:Article').sortDesc('datePublished').limit(this.limit).from(this.offset).execute().nodes} | |
@cache { | |
mode = 'cached' | |
entryIdentifier { | |
identifier = 'listAjax' | |
offset = ${'offset' + request.arguments.offset} | |
} | |
entryTags { | |
1 = ${'NodeType_Acme.News:Article'} | |
} | |
maximumLifetime = 3600 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{namespace neos=TYPO3\Neos\ViewHelpers} | |
<f:if condition="{f:count(subject: articles)} > 0"> | |
<f:then> | |
<div class="articles"> | |
<f:if condition="{offset}"> | |
<f:else> | |
<a class="rss-link" href="{neos:uri.node(node: '~', format: 'xml')}"> | |
<img src="{f:uri.resource(path: 'Images/rss.png', package: 'Acme.News')}" /> | |
</a> | |
</f:else> | |
</f:if> | |
<f:for each="{articles}" as="article"> | |
<article> | |
<div class="byline"> | |
<time datetime="{f:format.date(date: node.properties.datePublished, format: 'c')}" itemprop="datePublished"><f:format.date format="d.m.Y">{article.node.properties.datePublished}</f:format.date></time> | |
</div> | |
<header> | |
<h3> | |
<f:format.stripTags>{article.node.properties.title}</f:format.stripTags> | |
</h3> | |
</header> | |
<f:if condition="{article.node.properties.lead}"> | |
<summary> | |
<p class="sub-header">{article.node.properties.lead -> f:format.raw()}… <neos:link.node node="{article.node}">Read more</neos:link.node></p> | |
</summary> | |
</f:if> | |
</article> | |
</f:for> | |
</div> | |
</f:then> | |
<f:else> | |
<p>No articles were found</p> | |
</f:else> | |
</f:if> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Acme.News:Article': | |
superTypes: ['TYPO3.Neos.NodeTypes:Page'] | |
ui: | |
label: 'Article' | |
icon: 'icon-file-text' | |
inspector: | |
groups: | |
options: | |
label: 'Options' | |
position: 1 | |
properties: | |
_hiddenInIndex: | |
defaultValue: TRUE | |
datePublished: | |
type: date | |
defaultValue: 'now' | |
ui: | |
label: 'Publication Date' | |
reloadIfChanged: true | |
inspector: | |
group: 'options' | |
editorOptions: | |
format: 'd-m-Y' | |
tags: | |
type: 'references' | |
ui: | |
label: 'Tags' | |
reloadIfChanged: TRUE | |
inspector: | |
group: 'options' | |
editorOptions: | |
nodeTypes: ['Acme.News:Tag'] | |
author: | |
type: 'string' | |
ui: | |
label: 'Author' | |
reloadIfChanged: TRUE | |
inspector: | |
group: 'options' | |
editorOptions: | |
placeholder: 'Author' | |
title: | |
type: string | |
defaultValue: '' | |
ui: | |
inlineEditable: TRUE | |
inspector: | |
group: ~ | |
aloha: | |
placeholder: 'Headline' | |
'format': | |
'b': FALSE | |
'i': FALSE | |
'u': FALSE | |
'sub': FALSE | |
'sup': FALSE | |
'p': FALSE | |
'h1': TRUE | |
'h2': TRUE | |
'h3': FALSE | |
'pre': FALSE | |
'removeFormat': TRUE | |
'table': | |
'table': FALSE | |
'list': | |
'ol': FALSE | |
'ul': FALSE | |
'link': | |
'a': TRUE | |
lead: | |
type: string | |
ui: | |
label: 'Lead' | |
inlineEditable: TRUE | |
aloha: | |
placeholder: 'Lead' | |
'format': | |
'b': FALSE | |
'i': FALSE | |
'u': FALSE | |
'sub': FALSE | |
'sup': FALSE | |
'p': FALSE | |
'h1': TRUE | |
'h2': TRUE | |
'h3': FALSE | |
'pre': FALSE | |
'removeFormat': TRUE | |
'table': | |
'table': FALSE | |
'list': | |
'ol': FALSE | |
'ul': FALSE | |
'link': | |
'a': TRUE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Acme.News:List': | |
superTypes: ['TYPO3.Neos:Content'] | |
ui: | |
label: 'News article list' | |
icon: 'icon-list' | |
group: 'plugins' | |
inspector: | |
groups: | |
options: | |
label: 'Settings' | |
position: 40 | |
properties: | |
tags: | |
type: 'references' | |
ui: | |
label: 'Tags' | |
reloadIfChanged: TRUE | |
inspector: | |
group: 'options' | |
editorOptions: | |
nodeTypes: ['Acme.News:Tag'] | |
header: | |
type: string | |
defaultValue: 'News' | |
ui: | |
label: 'Header' | |
inlineEditable: TRUE | |
aloha: | |
'format': | |
'b': FALSE | |
'i': FALSE | |
'u': FALSE | |
'sub': FALSE | |
'sup': FALSE | |
'p': FALSE | |
'h1': FALSE | |
'h2': TRUE | |
'h3': FALSE | |
'pre': FALSE | |
'removeFormat': TRUE | |
'table': | |
'table': FALSE | |
'list': | |
'ol': FALSE | |
'ul': FALSE | |
'link': | |
'a': FALSE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Acme.News:Overview': | |
superTypes: ['TYPO3.Neos:Content'] | |
ui: | |
label: 'News overview' | |
icon: 'icon-list' | |
group: 'plugins' | |
inspector: | |
groups: | |
options: | |
label: 'Settings' | |
position: 30 | |
properties: | |
header: | |
type: string | |
defaultValue: 'News' | |
ui: | |
label: 'Header' | |
inlineEditable: TRUE | |
aloha: | |
'format': | |
'b': FALSE | |
'i': FALSE | |
'u': FALSE | |
'sub': FALSE | |
'sup': FALSE | |
'p': FALSE | |
'h1': FALSE | |
'h2': TRUE | |
'h3': FALSE | |
'pre': FALSE | |
'removeFormat': TRUE | |
'table': | |
'table': FALSE | |
'list': | |
'ol': FALSE | |
'ul': FALSE | |
'link': | |
'a': FALSE | |
numberOfArticles: | |
type: integer | |
defaultValue: 10 | |
ui: | |
label: 'Number of articles' | |
reloadIfChanged: TRUE | |
inspector: | |
group: 'options' | |
linkToList: | |
type: reference | |
ui: | |
label: 'Link to list page' | |
reloadIfChanged: TRUE | |
inspector: | |
group: 'options' | |
editorOptions: | |
nodeTypes: | |
- 'TYPO3.Neos.NodeTypes:Page' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Acme.News:Tag': | |
superTypes: ['TYPO3.Neos:Document'] | |
ui: | |
label: 'Tag' | |
icon: 'icon-tag' | |
properties: | |
_hiddenInIndex: | |
defaultValue: TRUE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{namespace neos=TYPO3\Neos\ViewHelpers} | |
<section{attributes -> f:format.raw()}> | |
<f:security.ifAccess resource="TYPO3_Neos_Backend_GeneralAccess"> | |
<f:then> | |
<neos:contentElement.editable property="header" tag="h2" /> | |
</f:then> | |
<f:else> | |
<f:if condition="{node.properties.header}"> | |
<h2>{node.properties.header}</h2> | |
</f:if> | |
</f:else> | |
</f:security.ifAccess> | |
<f:if condition="{f:count(subject: articles)} > 0"> | |
<f:then> | |
<ul class="articles"> | |
<f:for each="{articles}" as="article"> | |
<li> | |
<h6><neos:link.node node="{article.node}"><f:format.stripTags>{article.node.properties.title -> f:format.raw()}</f:format.stripTags></neos:link.node></h6> | |
<f:if condition="{article.node.properties.lead}"> | |
<p class="small">{article.node.properties.lead -> f:format.raw()}</p> | |
</f:if> | |
</li> | |
</f:for> | |
</ul> | |
</f:then> | |
<f:else> | |
<p>No articles were found</p> | |
</f:else> | |
</f:if> | |
<f:if condition="{node.properties.linkToList}"> | |
<div class="news-link-to-list"> | |
<neos:link.node node="{node.properties.linkToList}">See all articles</neos:link.node> | |
</div> | |
</f:if> | |
</section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
prototype(Acme.News:Overview) { | |
attributes.class = 'news-overview' | |
articles = ${Search.query(site).nodeType('Acme.News:Article').sortDesc('datePublished').limit(q(node).property('numberOfArticles')).execute().nodes} | |
filteredSearchQuery = ${this.tagSearchFilter.tags != null ? this.searchQuery.queryFilter('terms', this.tagSearchFilter) : this.searchQuery} | |
@cache { | |
mode = 'cached' | |
entryIdentifier { | |
node = ${node} | |
} | |
entryTags { | |
1 = ${'NodeType_Acme.News:Article'} | |
2 = ${'Node_' + node.identifier} | |
} | |
maximumLifetime = 3600 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root { | |
news { | |
@position = 'before default' | |
condition = ${q(node).is('[instanceof Acme.News:Article]')} | |
type = 'Acme.News:Article' | |
} | |
rss { | |
@position = 'before format' | |
condition = ${request.parentRequest.uri.path == '/rss.xml'} | |
renderPath = '/rss' | |
} | |
listAjax { | |
@position = 'before format' | |
condition = ${request.arguments.offset != null && request.arguments.offset != ''} | |
renderPath = '/listAjax' | |
} | |
@cache { | |
entryIdentifier { | |
path = ${request.parentRequest.uri.path} | |
offset = ${'offset' + request.arguments.offset} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- | |
name: 'RSS Feed' | |
uriPattern: '{node}rss.xml' | |
defaults: | |
'@package': 'TYPO3.Neos' | |
'@controller': 'Frontend\Node' | |
'@action': 'show' | |
'@format': 'xml' | |
routeParts: | |
'node': | |
handler: 'TYPO3\Neos\Routing\FrontendNodeRoutePartHandlerInterface' | |
options: | |
onlyMatchSiteNodes: TRUE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rss = TYPO3.TypoScript:Http.Message { | |
feed = TYPO3.TypoScript:Template { | |
templatePath = 'resource://Acme.News/Private/Templates/NodeTypes/Rss.xml' | |
articles = ${Search.query(site).nodeType('Acme.News:Article').sortDesc('datePublished').limit(100).execute().nodes} | |
site = ${site} | |
@cache { | |
mode = 'cached' | |
entryIdentifier { | |
identifier = 'rss' | |
} | |
entryTags { | |
1 = ${'NodeType_Acme.News:Article'} | |
} | |
maximumLifetime = 3600 | |
} | |
} | |
httpResponseHead.headers.Content-Type = 'application/xml' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{namespace neos=TYPO3\Neos\ViewHelpers}<?xml version="1.0" encoding="utf-8"?> | |
<rss version="2.0"> | |
<channel> | |
<title>{siteRoot.label} - Nyheder</title> | |
<link><neos:uri.node node="{site}" format="html" absolute="1" /></link> | |
<description>Latest news</description> | |
<language>da</language> | |
<lastBuildDate>{f:format.date(date: 'now', format: 'D, d M Y H:i:s O')}</lastBuildDate> | |
<f:if condition="{f:count(subject: articles)} > 0"><f:for each="{articles}" as="article"><item> | |
<title>{article.node.properties.title -> f:format.stripTags()}</title> | |
<link><neos:uri.node node="{article.node}" format="html" absolute="1" /></link> | |
<f:if condition="{article.node.properties.tags -> f:count()} > 0"><category><f:for each="{article.node.properties.tags}" as="tag" iteration="iterator"><f:if condition="{iterator.isFirst}">{tag.properties.title}</f:if></f:for></category></f:if> | |
<description><f:format.stripTags value="{article.node.properties.lead}" /></description> | |
<pubDate>{f:format.date(date: article.node.properties.datePublished, format: 'D, d M Y H:i:s O')}</pubDate> | |
</item></f:for></f:if> | |
</channel> | |
</rss> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<f:if condition="{node.context.workspace.name} != 'live'"> | |
<f:then> | |
<neos:contentElement.wrap node="{node}"> | |
<div> | |
<neos:contentElement.editable property="title" tag="h1" /> | |
</div> | |
</neos:contentElement.wrap> | |
</f:then> | |
<f:else> | |
<h1>{title}</h1> | |
</f:else> | |
</f:if> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
prototype(Acme.News:Tag) > | |
prototype(Acme.News:Tag) < prototype(Page) { | |
body { | |
node = ${node} | |
title = ${q(node).property('title')} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment