inspiring conference 2014 - node kingdom

48
Inspiring Conference 2014 TYPO3 Neos Node Kingdom

Upload: dfeyer

Post on 19-May-2015

3.434 views

Category:

Internet


4 download

DESCRIPTION

Basics about Structured Content and how your content inventory can help you configure TYPO3 Neos to have a proper Editor experience

TRANSCRIPT

Page 1: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

TYPO3 NeosNode Kingdom

Page 2: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Dominique Feyer

Cofounder of ttree ltd + medialib.tv ltd

Page 3: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

What’s nextShort introduction to Structured Content

Think about content

Your first custom Node Type

A bit more advanced example

Page 4: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Let’s start with some definitions

Page 5: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

What’s a Kingdom ?A really nice place to live in

Where a king take care of each citizen

A really romantic vision, no ?

Page 6: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Do you see the magic ?

Page 7: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

What’s a Node ?

A node is a small piece of content

Content is your first class citizen

Can be structured

Nodes can contain other node

Page 8: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Entity or NodeA different way to interact with content

In Neos, try to focus on Node

- Inline editing, Workspace, Content Dimension

- FlowQuery & EEL, Import / Export, …

!

Standard Doctrine Entity can be used for specific needs

Page 9: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

We are not Page Centric

Page 10: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

It’s not a Page Tree

It’s a Document Tree

Page 11: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

A Page is just a specific Document

A document can be anything

Page 12: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

When did you need a new Document TypeYou need an URL to access this content

- Customer

- Project Reference

- People

- Blog post, News, …

Page 13: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Do you remember your first jQuery plugin ?

That was maybe not « yours »

What about JavaScript internals ?

Page 14: Inspiring conference 2014 - Node Kingdom
Page 15: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Keep your content cleanAs an editor

I need special formatting for some paragraph

Page 16: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Page 17: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Page 18: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

How it’s done ?

A new Node Type based on the default Text Node Type

A small piece of TypoScript

Page 19: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Please defineNode TypeA Node Type define the structure of a node

A Node Type can have Super Type (inheritance)

The structure of a node can change

Page 20: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Add a Node Type'Ttree.OfficialWebsite:Teaser': superTypes: - 'TYPO3.Neos.NodeTypes:Text' ui: label: Teaser inspector: groups: theme: label: Theme position: 5 properties: reverse: type: boolean ui: label: 'Gray Theme' reloadIfChanged: true inspector: group: theme

Page 21: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

A short TypoScript

prototype(Ttree.OfficialWebsite:Teaser) > prototype(Ttree.OfficialWebsite:Teaser) < prototype(TYPO3.Neos.NodeTypes:Text) { attributes.class = ${node.properties.reverse ? 'teaser teaser-reverse' : 'teaser'} }

Page 22: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

A bit more advancedAs a client

I need to display a list of persons on my website

Each person has their own profile

I need to be able to insert person address and a link to the profile on any page

Page 23: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

What’s a Person

Your first Abstract Node Type

'Ttree.InspiringConf:Schema.Person': abstract: true ui: inspector: groups: person: label: 'Person' position: 1 properties: personName: type: string ui: label: 'Name' reloadIfChanged: TRUE inspector: group: person

Page 24: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Your second Abstract Node Type

What’s a Postal Address

'Ttree.InspiringConf:Schema.PostalAddress': abstract: true ui: inspector: groups: postalAddress: label: 'Postal Address' position: 2 properties: postalAddressStreetAddress: type: string ui: label: 'Street Address' reloadIfChanged: TRUE inspector: group: postalAddress postalAddressPostalCode: type: string ui: label: 'Postal Code' reloadIfChanged: TRUE inspector: group: postalAddress postalAddressLocality: type: string ui: label: 'Locality' reloadIfChanged: TRUE

Page 25: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Document Node Type

Extend the TYPO3.Neos:Document

Extend your abstract nodes

Add a content collection

'Ttree.InspiringConf:Person': superTypes: - 'TYPO3.Neos:Document' - 'Ttree.InspiringConf:Schema.PostalAddress' - 'Ttree.InspiringConf:Schema.Person' ui: label: 'Person' icon: 'icon-user' group: inspiringCon childNodes: profile: type: 'TYPO3.Neos:ContentCollection'

Page 26: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

TypoScriptprototype(TYPO3.Neos:PrimaryContent).TtreeInspiringConfPerson { condition = ${q(node).is('[instanceof Ttree.InspiringConf:Person]')} type = 'Ttree.InspiringConf:Person' @position = 'start' } prototype(Ttree.InspiringConf:Person) < prototype(TYPO3.TypoScript:Template) { templatePath = 'resource://Ttree.InspiringConf/Private/Templates/NodeTypes/Person.html' ! attributes = TYPO3.TypoScript:Attributes { class = 'person-profile-page' data-ttree-region = ${node.properties.postalAddressRegion} data-ttree-country = ${node.properties.postalAddressCountry} } ! personName = ${node.properties.personName} postalAddressStreetAddress = ${node.properties.postalAddressStreetAddress} postalAddressCountry = ${node.properties.postalAddressCountry} postalAddressPostalCode = ${node.properties.postalAddressPostalCode} postalAddressLocality = ${node.properties.postalAddressLocality} postalAddressRegion = ${node.properties.postalAddressRegion} …

Page 27: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

You say PrimaryContent ?

Use it only one time in your page

Neos know where to render the main content

Don’t use it for your sidebar

prototype(TYPO3.Neos:PrimaryContent).TtreeInspiringConfPerson { condition = ${q(node).is('[instanceof Ttree.InspiringConf:Person]')} type = 'Ttree.InspiringConf:Person' @position = 'start' }

Page 28: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Let’s preparing the view …Will be rendered in your PrimaryContent area

!

prototype(Ttree.InspiringConf:Person) < prototype(TYPO3.TypoScript:Template) { templatePath = 'resource://Ttree.InspiringConf/Private/Templates/NodeTypes/Person.html' ! attributes = TYPO3.TypoScript:Attributes { class = 'person-profile-page' data-ttree-region = ${node.properties.postalAddressRegion} data-ttree-country = ${node.properties.postalAddressCountry} } ! personName = ${node.properties.personName} postalAddressStreetAddress = ${node.properties.postalAddressStreetAddress} postalAddressCountry = ${node.properties.postalAddressCountry} postalAddressPostalCode = ${node.properties.postalAddressPostalCode} postalAddressLocality = ${node.properties.postalAddressLocality} postalAddressRegion = ${node.properties.postalAddressRegion} ! profile = TYPO3.Neos:ContentCollection { nodePath = 'profile' } }

Page 29: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

The Fluid template{namespace neos=TYPO3\Neos\ViewHelpers} <div{attributes -> f:format.raw()}> <div itemscope itemtype="http://schema.org/Person"> <h1 itemprop="name">{personName}</h1> <span itemprop="address" itemscope itemtype="http://schema.org/PostalAddress"> <span itemprop="streetAddress"> {postalAddressStreetAddress} </span> | <span itemprop="addressCountry">{postalAddressCountry}</span>, <span itemprop="postalCode">{postalAddressPostalCode}</span>, <span itemprop="addressLocality">{postalAddressLocality}</span>, <span itemprop="addressRegion">{postalAddressRegion}</span> </span> </div> ! <div class="customer-profile"> {profile -> f:format.raw()} </div> </div>

Page 30: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

The final rendering

Page 31: Inspiring conference 2014 - Node Kingdom
Page 32: Inspiring conference 2014 - Node Kingdom
Page 33: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Link to the profile from any

page ?

Page 34: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Page 35: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

What about a new node type ?As an editor

I need to insert on any page a contact address

Page 36: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Node Type'Ttree.InspiringConf:ContactAddress': superTypes: - 'TYPO3.Neos:Content' nodeLabelGenerator: 'Ttree\InspiringConf\Domain\Model\PersonNodeLabelGenerator' ui: label: 'Contact Address' group: 'inspiringCon' inspector: groups: document: label: 'Address' position: 1 properties: person: type: reference ui: label: 'Person' reloadIfChanged: true inspector: group: 'document' editorOptions: nodeTypes: - 'Ttree.InspiringConf:Person'

Page 37: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

TypoScriptprototype(Ttree.InspiringConf:ContactAddress) > prototype(Ttree.InspiringConf:ContactAddress) < prototype(TYPO3.Neos:Content) { templatePath = 'resource://Ttree.InspiringConf/Private/Templates/NodeTypes/ContactAddress.html' ! person = ${node.properties.person} hasPerson = ${node.properties.person ? TRUE : FALSE} ! attributes = TYPO3.TypoScript:Attributes { class = 'person-profile-inline' style = 'background: #CCC; padding: 10px; margin-bottom: 10px;' data-ttree-region = ${this.person.properties.postalAddressRegion} data-ttree-country = ${this.person.properties.postalAddressCountry} } ! personName = ${this.person.properties.personName} postalAddressStreetAddress = ${this.person.properties.postalAddressStreetAddress} postalAddressCountry = ${this.person.properties.postalAddressCountry} postalAddressPostalCode = ${this.person.properties.postalAddressPostalCode} postalAddressLocality = ${this.person.properties.postalAddressLocality} postalAddressRegion = ${this.person.properties.postalAddressRegion} }

Page 38: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Template{namespace neos=TYPO3\Neos\ViewHelpers} <div{attributes -> f:format.raw()}> <f:if condition="{hasPerson}"> <f:then> <div itemscope itemtype="http://schema.org/Person"> <div style="font-weight: bold;" itemprop="name">{personName}</div> <div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress"> <div itemprop="streetAddress"> {postalAddressStreetAddress} </div> <div> <span itemprop="addressCountry">{postalAddressCountry}</span> - <span itemprop="postalCode">{postalAddressPostalCode}</span> <span itemprop="addressLocality">{postalAddressLocality}</span> </div> </div> </div> </f:then> <f:else> <strong> Please select a Person<br/> in the Inspector </strong> </f:else> </f:if> </div>

Page 39: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Page 40: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

nodeLabelGenerator: 'Ttree\InspiringConf\Domain\Model\PersonNodeLabelGenerator'

Custom node label, but why ?

Page 41: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

class PersonNodeLabelGenerator extends DefaultNodeLabelGenerator { public function getLabel(AbstractNodeData $nodeData, $crop = TRUE) { if ($nodeData->hasProperty('person') === TRUE && $nodeData->getProperty('person')) { $label = 'Link to: ' . strip_tags($nodeData->getProperty('person')-> getProperty('personName')); } else { $label = parent::getLabel($nodeData, FALSE); } if ($crop === FALSE) { return $label; } ! $croppedLabel = \TYPO3\Flow\Utility\Unicode\Functions::substr($label, 0, NodeInterface::LABEL_MAXIMUM_CHARACTERS); return $croppedLabel . (strlen($croppedLabel) < strlen($label) ? ' …’ : ''); } }

Page 42: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

class PersonNodeLabelGenerator extends DefaultNodeLabelGenerator { public function getLabel(AbstractNodeData $nodeData, $crop = TRUE) { if ($nodeData->hasProperty('person') === TRUE && $nodeData->getProperty('person')) { $label = 'Link to: ' . strip_tags($nodeData->getProperty('person')-> getProperty('personName')); } else { $label = parent::getLabel($nodeData, FALSE); } if ($crop === FALSE) { return $label; } ! $croppedLabel = \TYPO3\Flow\Utility\Unicode\Functions::substr($label, 0, NodeInterface::LABEL_MAXIMUM_CHARACTERS); return $croppedLabel . (strlen($croppedLabel) < strlen($label) ? ' …’ : ''); } }

Page 43: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

class PersonNodeLabelGenerator extends DefaultNodeLabelGenerator { public function getLabel(AbstractNodeData $nodeData, $crop = TRUE) { if ($nodeData->hasProperty('person') === TRUE && $nodeData->getProperty('person')) { $label = 'Link to: ' . strip_tags($nodeData->getProperty('person')-> getProperty('personName')); } else { $label = parent::getLabel($nodeData, FALSE); } if ($crop === FALSE) { return $label; } ! $croppedLabel = \TYPO3\Flow\Utility\Unicode\Functions::substr($label, 0,NodeInterface::LABEL_MAXIMUM_CHARACTERS); return $croppedLabel . (strlen($croppedLabel) < strlen($label) ? ' …’ : ''); } }

Page 44: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Lazy mode pseudo live

demonstration

Page 45: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Page 46: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

We, as a community, are currently redefining the future of CMS

Thanks

Page 47: Inspiring conference 2014 - Node Kingdom

Inspiring Conference 2014

Fork me on Github https://github.com/dfeyer/Ttree.InspiringConf

Page 48: Inspiring conference 2014 - Node Kingdom

Follow us @ttreeagency

Follow me @dfeyer

Questions