Inspiring conference 2014 - Node Kingdom

5,223 views

Published on

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

Published in: Internet
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,223
On SlideShare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
16
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Inspiring conference 2014 - Node Kingdom

  1. 1. Inspiring Conference 2014 TYPO3 Neos Node Kingdom
  2. 2. Inspiring Conference 2014 Dominique Feyer Cofounder of ttree ltd + medialib.tv ltd
  3. 3. Inspiring Conference 2014 What’s next Short introduction to Structured Content Think about content Your first custom Node Type A bit more advanced example
  4. 4. Inspiring Conference 2014 Let’s start with some definitions
  5. 5. 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 ?
  6. 6. Inspiring Conference 2014 Do you see the magic ?
  7. 7. 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
  8. 8. Inspiring Conference 2014 Entity or Node A 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
  9. 9. Inspiring Conference 2014 We are not 
 Page Centric
  10. 10. Inspiring Conference 2014 It’s not a 
 Page Tree It’s a 
 Document Tree
  11. 11. Inspiring Conference 2014 A Page is just a specific Document A document can be anything
  12. 12. Inspiring Conference 2014 When did you need a new Document Type You need an URL to access this content - Customer - Project Reference - People - Blog post, News, …
  13. 13. Inspiring Conference 2014 Do you remember your first jQuery plugin ? That was maybe not « yours » What about JavaScript internals ?
  14. 14. Inspiring Conference 2014 Keep your 
 content clean As an editor I need special formatting for some paragraph
  15. 15. Inspiring Conference 2014
  16. 16. Inspiring Conference 2014
  17. 17. Inspiring Conference 2014 How it’s done ? A new Node Type based on the default Text Node Type A small piece of TypoScript
  18. 18. Inspiring Conference 2014 Please define
 Node Type A Node Type define the structure of a node A Node Type can have Super Type (inheritance) The structure of a node can change
  19. 19. 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
  20. 20. 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'} }
  21. 21. Inspiring Conference 2014 A bit more advanced As 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
  22. 22. 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
  23. 23. 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
  24. 24. 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'
  25. 25. Inspiring Conference 2014 TypoScript prototype(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/Perso ! 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} …
  26. 26. 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' }
  27. 27. 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/Pers ! 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' } }
  28. 28. Inspiring Conference 2014 The Fluid template {namespace neos=TYPO3NeosViewHelpers} <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>
  29. 29. Inspiring Conference 2014 The final rendering
  30. 30. Inspiring Conference 2014 Link to the profile from any page ?
  31. 31. Inspiring Conference 2014
  32. 32. Inspiring Conference 2014 What about a new node type ? As an editor I need to insert on any page a contact address
  33. 33. Inspiring Conference 2014 Node Type 'Ttree.InspiringConf:ContactAddress': superTypes: - 'TYPO3.Neos:Content' nodeLabelGenerator: 'TtreeInspiringConfDomainModelPersonNodeLabelGenerator' 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'
  34. 34. Inspiring Conference 2014 TypoScript prototype(Ttree.InspiringConf:ContactAddress) > prototype(Ttree.InspiringConf:ContactAddress) < prototype(TYPO3.Neos:Content) { templatePath = 'resource://Ttree.InspiringConf/Private/Templates/NodeTypes/ContactAdd ! 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} }
  35. 35. Inspiring Conference 2014 Template{namespace neos=TYPO3NeosViewHelpers} <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/PostalAddres <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>
  36. 36. Inspiring Conference 2014
  37. 37. Inspiring Conference 2014 nodeLabelGenerator: 'TtreeInspiringConfDomainModelPersonNodeLabelGenerator' Custom node label, but why ?
  38. 38. 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 = TYPO3FlowUtilityUnicodeFunctions::substr($label, 0, NodeInterface::LABEL_MAXIMUM_CHARACTERS); return $croppedLabel . (strlen($croppedLabel) < strlen($label) ? ' …’ : ''); } }
  39. 39. 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 = TYPO3FlowUtilityUnicodeFunctions::substr($label, 0, NodeInterface::LABEL_MAXIMUM_CHARACTERS); return $croppedLabel . (strlen($croppedLabel) < strlen($label) ? ' …’ : ''); } }
  40. 40. Inspiring Conference 2014 class PersonNodeLabelGenerator extends DefaultNodeLabelGen public function getLabel(AbstractNodeData $nodeData, $cr if ($nodeData->hasProperty('person') === TRUE && $no $label = 'Link to: ' . strip_tags($nodeData->getPrope getProperty('personName')); } else { $label = parent::getLabel($nodeData, FALSE); } if ($crop === FALSE) { return $label; } ! $croppedLabel = TYPO3FlowUtilityUnicodeFunction return $croppedLabel . (strlen($croppedLabel) < strlen($ } }
  41. 41. Inspiring Conference 2014 Lazy mode pseudo live demonstration
  42. 42. Inspiring Conference 2014
  43. 43. Inspiring Conference 2014 We, as a community, are currently redefining the future of CMS Thanks
  44. 44. Inspiring Conference 2014 Fork me on Github
 https://github.com/dfeyer/Ttree.InspiringConf
  45. 45. Follow us @ttreeagency Follow me @dfeyer Questions

×