From 9d523a143d58a501bd168ec10b04461b04e46048 Mon Sep 17 00:00:00 2001 From: ryzy Date: Sat, 13 Dec 2014 15:12:18 +0000 Subject: [PATCH 01/23] Removing custom M12.Foundation UI Inspector editors as now they are available in the core (Neos 1.2) --- Configuration/NodeTypes.Abstracts.yaml | 2 +- Configuration/NodeTypes.Forms.yaml | 10 +++-- Configuration/NodeTypes.Neos.Documents.yaml | 10 ++++- Configuration/Settings.yaml | 6 +-- .../Neos/Inspector/Editors/CssEditor.js | 45 ------------------- .../Neos/Inspector/Editors/JsEditor.js | 45 ------------------- .../Neos/Inspector/Editors/TextAreaEditor.js | 14 ------ .../Public/Styles/Neos/m12-foundation.css | 12 ----- 8 files changed, 19 insertions(+), 125 deletions(-) delete mode 100644 Resources/Public/JavaScript/Neos/Inspector/Editors/CssEditor.js delete mode 100644 Resources/Public/JavaScript/Neos/Inspector/Editors/JsEditor.js delete mode 100644 Resources/Public/JavaScript/Neos/Inspector/Editors/TextAreaEditor.js diff --git a/Configuration/NodeTypes.Abstracts.yaml b/Configuration/NodeTypes.Abstracts.yaml index c26d297..e6606ef 100644 --- a/Configuration/NodeTypes.Abstracts.yaml +++ b/Configuration/NodeTypes.Abstracts.yaml @@ -60,7 +60,7 @@ inspector: group: 'dev' position: 40 - editor: 'M12.Foundation/Inspector/Editors/TextAreaEditor' + editor: 'Content/Inspector/Editors/TextAreaEditor' editorOptions: placeholder: 'e.g. custom-data-attribute=value' diff --git a/Configuration/NodeTypes.Forms.yaml b/Configuration/NodeTypes.Forms.yaml index 23e991c..e7d528b 100644 --- a/Configuration/NodeTypes.Forms.yaml +++ b/Configuration/NodeTypes.Forms.yaml @@ -438,11 +438,16 @@ selectOptions: type: string ui: - label: 'List select options' + label: 'Select options (one per line)' reloadIfChanged: TRUE inspector: group: 'formInputSettings' - editor: 'M12.Foundation/Inspector/Editors/TextAreaEditor' + editor: Content/Inspector/Editors/TextAreaEditor + editorOptions: + placeholder: | + e.g.: value = Label + or: Just Label + rows: 10 # NodeType for textarea. @@ -453,4 +458,3 @@ ui: label: 'Textarea' icon: 'icon-align-left' - diff --git a/Configuration/NodeTypes.Neos.Documents.yaml b/Configuration/NodeTypes.Neos.Documents.yaml index 7e7ee7d..248b322 100644 --- a/Configuration/NodeTypes.Neos.Documents.yaml +++ b/Configuration/NodeTypes.Neos.Documents.yaml @@ -30,14 +30,20 @@ inspector: group: 'dev' position: 31 # after 'customCssCode' - editor: 'M12.Foundation/Inspector/Editors/JsEditor' + editor: 'TYPO3.Neos/Inspector/Editors/CodeEditor' + editorOptions: + buttonLabel: 'Add custom JS code' + highlightingMode: 'text/javascript' # Inherited from M12.Foundation:AbstractDevBase # Replace it with CssEditor customCssCode: ui: label: null inspector: - editor: 'M12.Foundation/Inspector/Editors/CssEditor' + editor: 'TYPO3.Neos/Inspector/Editors/CodeEditor' + editorOptions: + buttonLabel: 'Add custom CSS styles' + highlightingMode: 'text/css' # Inherited from M12.Foundation:DeveloperAbstract customHtmlId: ui: diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 26a2a11..821892f 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -4,9 +4,9 @@ TYPO3: autoInclude: 'M12.Foundation': TRUE - userInterface: - requireJsPathMapping: - 'M12.Foundation/Inspector/Editors': 'resource://M12.Foundation/Public/JavaScript/Neos/Inspector/Editors' +# userInterface: +# requireJsPathMapping: +# 'M12.Foundation/Inspector/Editors': 'resource://M12.Foundation/Public/JavaScript/Neos/Inspector/Editors' nodeTypes: groups: diff --git a/Resources/Public/JavaScript/Neos/Inspector/Editors/CssEditor.js b/Resources/Public/JavaScript/Neos/Inspector/Editors/CssEditor.js deleted file mode 100644 index 5f8e4fb..0000000 --- a/Resources/Public/JavaScript/Neos/Inspector/Editors/CssEditor.js +++ /dev/null @@ -1,45 +0,0 @@ -define( -[ - 'emberjs', - 'Content/Inspector/SecondaryInspectorController', - 'Library/codemirror' -], -function(Ember, SecondaryInspectorController, CodeMirror) { - return SecondaryInspectorController.SecondaryInspectorButton.extend({ - label: 'Add custom CSS styles', - - viewClass: function() { - var that = this; - - return Ember.View.extend({ - classNames: ['neos-secondary-inspector-html-editor'], - template: Ember.Handlebars.compile(''), - - didInsertElement: function() { - var $editorContent = this.$().find('textarea'), - value = that.get('value'); - /* - * inserting the content into the textarea before creating the editor - * causes all contained inline-javascript to be executed - * we don't want that, additionally it breaks stuff (#33010) - * - * set the value of the editor instead - */ - var editor = CodeMirror.fromTextArea($editorContent.get(0), { - mode: 'css', - theme: 'solarized dark', - indentWithTabs: true, - styleActiveLine: true, - lineNumbers: true, - lineWrapping: false, - autofocus: true - }); - editor.on('change', function() { - that.set('value', editor.getValue()); - }); - editor.setValue(value); - } - }); - }.property() - }); -}); diff --git a/Resources/Public/JavaScript/Neos/Inspector/Editors/JsEditor.js b/Resources/Public/JavaScript/Neos/Inspector/Editors/JsEditor.js deleted file mode 100644 index 14c2482..0000000 --- a/Resources/Public/JavaScript/Neos/Inspector/Editors/JsEditor.js +++ /dev/null @@ -1,45 +0,0 @@ -define( -[ - 'emberjs', - 'Content/Inspector/SecondaryInspectorController', - 'Library/codemirror' -], -function(Ember, SecondaryInspectorController, CodeMirror) { - return SecondaryInspectorController.SecondaryInspectorButton.extend({ - label: 'Add custom JS code', - - viewClass: function() { - var that = this; - - return Ember.View.extend({ - classNames: ['neos-secondary-inspector-html-editor'], - template: Ember.Handlebars.compile(''), - - didInsertElement: function() { - var $editorContent = this.$().find('textarea'), - value = that.get('value'); - /* - * inserting the content into the textarea before creating the editor - * causes all contained inline-javascript to be executed - * we don't want that, additionally it breaks stuff (#33010) - * - * set the value of the editor instead - */ - var editor = CodeMirror.fromTextArea($editorContent.get(0), { - mode: 'javascript', - theme: 'solarized dark', - indentWithTabs: true, - styleActiveLine: true, - lineNumbers: true, - lineWrapping: false, - autofocus: true - }); - editor.on('change', function() { - that.set('value', editor.getValue()); - }); - editor.setValue(value); - } - }); - }.property() - }); -}); diff --git a/Resources/Public/JavaScript/Neos/Inspector/Editors/TextAreaEditor.js b/Resources/Public/JavaScript/Neos/Inspector/Editors/TextAreaEditor.js deleted file mode 100644 index 587a2b0..0000000 --- a/Resources/Public/JavaScript/Neos/Inspector/Editors/TextAreaEditor.js +++ /dev/null @@ -1,14 +0,0 @@ -define( -[ - 'emberjs' -], -function(Ember) { - Ember.TextSupport.reopen({ - attributeBindings: ['name', 'required', 'pattern', 'step', 'min', 'max'] - }); - - return Ember.TextArea.extend({ - classNames: ['expand'], - validators: {} - }); -}); diff --git a/Resources/Public/Styles/Neos/m12-foundation.css b/Resources/Public/Styles/Neos/m12-foundation.css index d473fe2..e55d111 100644 --- a/Resources/Public/Styles/Neos/m12-foundation.css +++ b/Resources/Public/Styles/Neos/m12-foundation.css @@ -4,16 +4,4 @@ height: 75%; overflow-y: scroll; } - -.neos #neos-inspector .neos-inspector-form textarea { - width: 91%; - margin: 0; - padding: 5px 14px; - color: #fff; - font-family: 'Noto Sans', sans-serif; - -webkit-font-smoothing: antialiased; - border: 2px solid #323232; - background-color: #323232; -} -.neos #neos-inspector .neos-inspector-form textarea:focus { } From 49fd69c362483258ac482b0d4ae71dd0aefdf1e0 Mon Sep 17 00:00:00 2001 From: ryzy Date: Sat, 13 Dec 2014 15:22:21 +0000 Subject: [PATCH 02/23] TypoScript/MenuImplementation: making it compatible with Neos 1.2 --- Classes/M12/Foundation/TypoScript/MenuImplementation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/M12/Foundation/TypoScript/MenuImplementation.php b/Classes/M12/Foundation/TypoScript/MenuImplementation.php index 682896b..184acc0 100644 --- a/Classes/M12/Foundation/TypoScript/MenuImplementation.php +++ b/Classes/M12/Foundation/TypoScript/MenuImplementation.php @@ -33,7 +33,7 @@ protected function buildMenuLevelRecursive(array $menuLevelCollection) { $item['cssClasses'] = ''; /** @var NodeInterface $node */ - $node = $item['originalNode']; + $node = $item['node']; // // [FEATURE] From 2f2f0b37d58510cc0aea2f7c31ae220675b8bf7d Mon Sep 17 00:00:00 2001 From: ryzy Date: Sat, 13 Dec 2014 15:23:25 +0000 Subject: [PATCH 03/23] TS: including .ts2 files via '*' This is a new feature in Neos 1.2 and it's much easier to maintain TS codebase using it. --- Resources/Private/TypoScript/Root.ts2 | 62 +++------------------------ 1 file changed, 5 insertions(+), 57 deletions(-) diff --git a/Resources/Private/TypoScript/Root.ts2 b/Resources/Private/TypoScript/Root.ts2 index 24ed92c..19f006a 100644 --- a/Resources/Private/TypoScript/Root.ts2 +++ b/Resources/Private/TypoScript/Root.ts2 @@ -1,60 +1,8 @@ # Custom TypoScript objects -include: TypoScriptObjects/ValueOptionsList.ts2 +include: TypoScriptObjects/* -include: Neos/Attributes.ts2 -include: Neos/Content.ts2 -include: Neos/ContentCollection.ts2 -include: Neos/Form.ts2 -include: Neos/Menu.ts2 -include: Neos/NodeTypes.ts2 -include: Neos/Page.ts2 - - -# M12.Foundation prototypes - Generic -include: Prototypes/Content.ts2 -include: Prototypes/Container.ts2 -include: Prototypes/FontIcon.ts2 - - -# M12.Foundation prototypes - Structure -include: Prototypes/Grid.ts2 -include: Prototypes/BlockGrid.ts2 - - -# M12.Foundation prototypes - Navigation -include: Prototypes/Menu.ts2 -include: Prototypes/SideNav.ts2 -include: Prototypes/SubNav.ts2 -include: Prototypes/NavItem.ts2 - - -# M12.Foundation prototypes - Media -include: Prototypes/Orbit.ts2 -include: Prototypes/Video.ts2 - - -# M12.Foundation prototypes - Forms -include: Prototypes/Form.ts2 - - -# M12.Foundation prototypes - Buttons -include: Prototypes/Button.ts2 -include: Prototypes/ButtonGroup.ts2 -include: Prototypes/ButtonGroupItem.ts2 -include: Prototypes/ButtonBar.ts2 - - -# M12.Foundation prototypes - Typography - - -# M12.Foundation prototypes - Callouts & Prompts -include: Prototypes/RevealModal.ts2 -include: Prototypes/Alert.ts2 -include: Prototypes/Panel.ts2 - - -# M12.Foundation prototypes - Content -include: Prototypes/Dropdown.ts2 -include: Prototypes/Accordion.ts2 -include: Prototypes/Tabs.ts2 +# TYPO3 Neos objects amends +include: Neos/* +# M12.Foundation prototypes +include: Prototypes/* From 7d0ef561defa2cc91453876155d664dc404bfdd0 Mon Sep 17 00:00:00 2001 From: ryzy Date: Sat, 13 Dec 2014 15:25:04 +0000 Subject: [PATCH 04/23] CSS: no need anymore for custom styles for Neos modal window Before 1.2 we needed custom styles to add scroll on modal window, in case there's more content element than available space. It is no more the case, now modal window support such a case. --- Resources/Public/Styles/Neos/m12-foundation.css | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Resources/Public/Styles/Neos/m12-foundation.css b/Resources/Public/Styles/Neos/m12-foundation.css index e55d111..88d0eeb 100644 --- a/Resources/Public/Styles/Neos/m12-foundation.css +++ b/Resources/Public/Styles/Neos/m12-foundation.css @@ -1,7 +1,6 @@ /** Custom M12.Foundation code for Neos backend **/ -.neos .neos-modal.neos-modal-wide { - height: 75%; - overflow-y: scroll; -} +/** Restore Neos colors after they were overridden by Foundation **/ +.neos label { + color: inherit; } From 937c8ddfa89c18882404103cd2f5947b0717383d Mon Sep 17 00:00:00 2001 From: ryzy Date: Sat, 13 Dec 2014 19:28:09 +0000 Subject: [PATCH 05/23] CI tests added --- circle.yml | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ composer.json | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..3e3b6d1 --- /dev/null +++ b/circle.yml @@ -0,0 +1,52 @@ +machine: + services: + - docker + hosts: + neos: 127.0.0.1 + dev.neos: 127.0.0.1 + +dependencies: + pre: + - docker info && docker version + + override: + - docker pull tutum/mariadb:latest + - docker pull million12/behat-selenium:latest + - docker pull million12/neos-typostrap-distribution:latest + + post: + # Launch DB backend + - docker run -d --name=db --env="MARIADB_PASS=my-pass" tutum/mariadb + - docker logs -f db | tee -a ${CIRCLE_ARTIFACTS}/docker-db.log: + background: true + +# Run tests +test: + override: + # ###################################################### + # Run Typostrap Neos container, which includes + # M12.Foundation / M12.FoundationSite packages + # and do some basics checks. + # ###################################################### + - docker run -d --name=neos -p=8080:80 --link=db:db --env="T3APP_NAME=neos" --env="T3APP_VHOST_NAMES=neos dev.neos behat.dev.neos" --env="T3APP_DO_INIT_TESTS=true" --env="T3APP_ALWAYS_DO_PULL=true" million12/neos-typostrap-distribution + - docker logs -f neos > ${CIRCLE_ARTIFACTS}/docker-neos.log: + background: true + # Wait till TYPO3 Neos is fully configured + - while true; do if grep "nginx entered RUNNING state" ${CIRCLE_ARTIFACTS}/docker-neos.log; then break; else sleep 1; fi done + + # Test: do basic front-end tests + - curl -L --head http://neos:8080 && curl -s -L http://neos:8080 + - curl -s --head http://neos:8080 | grep "HTTP/1.1 200 OK" && curl -s --head http://neos:8080 | grep "X-Flow-Powered" + - curl -s -L http://neos:8080/neos | grep "TYPO3 Neos Login" + + # Run Neos unit tests. + - | + docker run -ti --volumes-from=neos --link=neos:web --link=db:db million12/behat-selenium " + env && \ + echo \$WEB_PORT_80_TCP_ADDR \$WEB_ENV_T3APP_VHOST_NAMES >> /etc/hosts && cat /etc/hosts && \ + su www -c \" + cd ~/neos && \ + echo -e '\n\n======== RUNNING UNIT TESTS =======\n\n' && \ + bin/phpunit -c Build/BuildEssentials/PhpUnit/UnitTests.xml --colors + \" + " diff --git a/composer.json b/composer.json index c76405b..b645d8b 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ } ], "require": { - "typo3/neos-nodetypes": "*", + "typo3/neos-nodetypes": "1.2.*", "m12/neos-utils": "*" }, "autoload": { From 705f7162b328f31cd78ab3264cc3a4e02b51fc67 Mon Sep 17 00:00:00 2001 From: ryzy Date: Sat, 13 Dec 2014 21:10:04 +0000 Subject: [PATCH 06/23] TS: AttributesImplementation update so it's compatible with Neos 1.2 + unit tests --- .../Core/ViewHelper/TagBuilderAspect.php | 6 +- .../AttributesImplementation.php | 39 ++++++--- .../Private/TypoScript/Neos/Attributes.ts2 | 2 +- .../AttributesImplementationTest.php | 79 +++++++++++++++++++ 4 files changed, 110 insertions(+), 16 deletions(-) rename Classes/M12/Foundation/{TypoScript => TypoScriptObjects}/AttributesImplementation.php (71%) create mode 100644 Tests/Unit/TypoScriptObjects/AttributesImplementationTest.php diff --git a/Classes/M12/Foundation/Fluid/Core/ViewHelper/TagBuilderAspect.php b/Classes/M12/Foundation/Fluid/Core/ViewHelper/TagBuilderAspect.php index e15118a..b0362e1 100644 --- a/Classes/M12/Foundation/Fluid/Core/ViewHelper/TagBuilderAspect.php +++ b/Classes/M12/Foundation/Fluid/Core/ViewHelper/TagBuilderAspect.php @@ -17,7 +17,7 @@ * Modifies globally how TagBuilder behaves for NULL attributes. * We're taking here the same strategy as with AttributesImplementation * - we don't want any attributes to render at all if the value - * was set to NULL. + * was set to NULL or FALSE. * * @see \TYPO3\Fluid\Core\ViewHelper\TagBuilder * @see \M12\Foundation\TypoScript\AttributesImplementation @@ -28,7 +28,7 @@ class TagBuilderAspect { /** * This changes how TagBuilder->addAttribute() method works. - * When attribute's value is NULL, it does *unset* the value. + * When attribute's value is NULL or FALSE, it does *unset* the value. * Otherwise addAttribute() method is called as usually. * * @param \TYPO3\Flow\AOP\JoinPointInterface $joinPoint @@ -36,7 +36,7 @@ class TagBuilderAspect { * @return void */ public function catchAddAttribute(\TYPO3\Flow\AOP\JoinPointInterface $joinPoint) { - if (NULL === $joinPoint->getMethodArgument('attributeValue')) { + if (NULL === $joinPoint->getMethodArgument('attributeValue') || FALSE === $joinPoint->getMethodArgument('attributeValue')) { /** @var \TYPO3\Fluid\Core\ViewHelper\TagBuilder $tagBuilder */ $tagBuilder = $joinPoint->getProxy(); $tagBuilder->removeAttribute($joinPoint->getMethodArgument('attributeName')); diff --git a/Classes/M12/Foundation/TypoScript/AttributesImplementation.php b/Classes/M12/Foundation/TypoScriptObjects/AttributesImplementation.php similarity index 71% rename from Classes/M12/Foundation/TypoScript/AttributesImplementation.php rename to Classes/M12/Foundation/TypoScriptObjects/AttributesImplementation.php index d495a64..f318f45 100644 --- a/Classes/M12/Foundation/TypoScript/AttributesImplementation.php +++ b/Classes/M12/Foundation/TypoScriptObjects/AttributesImplementation.php @@ -1,5 +1,5 @@ parseCustomUserAttributes(); + $allowEmpty = $this->getAllowEmpty(); $attributes = array(); $renderedAttributes = ''; foreach (array_keys($this->properties) as $attributeName) { + if ($attributeName === '__meta') continue; + $encodedAttributeName = htmlspecialchars($attributeName, ENT_COMPAT, 'UTF-8', FALSE); $attributeValue = $this->tsValue($attributeName); - if (null === $attributeValue) { - continue; - } else if (is_string($attributeValue) && 0 === strlen($attributeValue)) { + if ($attributeValue === NULL || $attributeValue === FALSE) { + // No op + } elseif ($attributeValue === TRUE || $attributeValue === '') { $attributes[$attributeName] = $attributeValue; - $renderedAttributes .= ' ' . $encodedAttributeName; + $renderedAttributes .= ' ' . $encodedAttributeName . ($allowEmpty ? '' : '=""'); } else { if (is_array($attributeValue)) { - $attributeValue = implode(' ', $attributeValue); + $joinedAttributeValue = ''; + foreach ($attributeValue as $attributeValuePart) { + if ((string)$attributeValuePart !== '') { + $joinedAttributeValue .= ' ' . trim($attributeValuePart); + } + } + $attributeValue = trim($joinedAttributeValue); } $encodedAttributeValue = htmlspecialchars($attributeValue, ENT_COMPAT, 'UTF-8', FALSE); - + $attributes[$attributeName] = $attributeValue; $renderedAttributes .= ' ' . $encodedAttributeName . '="' . $encodedAttributeValue . '"'; } diff --git a/Resources/Private/TypoScript/Neos/Attributes.ts2 b/Resources/Private/TypoScript/Neos/Attributes.ts2 index 12dc195..6dc9b72 100644 --- a/Resources/Private/TypoScript/Neos/Attributes.ts2 +++ b/Resources/Private/TypoScript/Neos/Attributes.ts2 @@ -1,5 +1,5 @@ # Override original TypoScript Attributes implementation # to filter out out attributes with NULL values prototype(TYPO3.TypoScript:Attributes) { - @class = 'M12\\Foundation\\TypoScript\\AttributesImplementation' + @class = 'M12\\Foundation\\TypoScriptObjects\\AttributesImplementation' } diff --git a/Tests/Unit/TypoScriptObjects/AttributesImplementationTest.php b/Tests/Unit/TypoScriptObjects/AttributesImplementationTest.php new file mode 100644 index 0000000..d33036b --- /dev/null +++ b/Tests/Unit/TypoScriptObjects/AttributesImplementationTest.php @@ -0,0 +1,79 @@ +mockTsRuntime = $this->getMockBuilder('TYPO3\TypoScript\Core\Runtime')->disableOriginalConstructor()->getMock(); + } + + public function attributeExamples() { + return array( + 'null' => array(NULL, '', []), + 'empty array' => array(array(), '', []), + 'boolean values' => array(array('booleanTrueAttribute' => TRUE, 'booleanFalseAttribute' => FALSE), ' booleanTrueAttribute', ['booleanTrueAttribute'=>TRUE]), + 'empty string value' => array(array('emptyStringAttribute' => ''), ' emptyStringAttribute', ['emptyStringAttribute'=>'']), + 'null value' => array(array('nullAttribute' => NULL), '', []), + 'simple array' => array(array('attributeName1' => 'attributeValue1'), ' attributeName1="attributeValue1"', ['attributeName1'=>'attributeValue1']), + 'encoding' => array(array('spec 'chara>cters'), ' spec<ial="chara>cters"', ['spec 'chara>cters']), + 'array attributes' => array(array('class' => array('icon', NULL, 'icon-neos', '')), ' class="icon icon-neos"', ['class' => 'icon icon-neos']), + 'empty attribute value without allowEmpty' => array(array('emptyStringAttribute' => '', '__meta' => array('allowEmpty' => FALSE)), ' emptyStringAttribute=""', ['emptyStringAttribute'=>'']), + ); + } + + /** + * @test + * @dataProvider attributeExamples + */ + public function evaluateTests($properties, $expectedOutput, $expectedOutputAsArray) { +// print_r(func_get_args()); + $path = 'attributes/test'; + $this->mockTsRuntime->expects($this->any())->method('evaluate')->will($this->returnCallback(function($evaluatePath, $that) use ($path, $properties) { + $relativePath = str_replace($path . '/', '', $evaluatePath); + return ObjectAccess::getPropertyPath($properties, str_replace('/', '.', $relativePath)); + })); + + $typoScriptObjectName = 'TYPO3.TypoScript:Attributes'; + $renderer = new AttributesImplementation($this->mockTsRuntime, $path, $typoScriptObjectName); + + if ($properties !== NULL) { + foreach ($properties as $name => $value) { + ObjectAccess::setProperty($renderer, $name, $value); + } + } + + $result = $renderer->evaluate(); + + $this->assertInstanceOf('M12\Foundation\TypoScriptObjects\AttributesImplementation', $result); + $this->assertTrue(is_string($result->getAsString())); + $this->assertTrue(is_array($result->getAsArray())); + + $this->assertEquals($expectedOutput, $result); + $this->assertEquals($expectedOutput, $result->getAsString()); + $this->assertEquals($expectedOutputAsArray, $result->getAsArray()); + } +} From 15093cdda2e6dc0a6cb008f9f70a6e3470ac9139 Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 14:24:10 +0000 Subject: [PATCH 07/23] Grid: refactored, so it uses new multiple SelectBoxEditor With this change we have less properties in UI Inspector, as now it's possible to select e.g. column size for different devices in single select box editor. --- .../AbstractGridNodeTypePostprocessor.php | 71 +++++++++++-------- Configuration/NodeTypes.Neos.Content.yaml | 8 +++ Configuration/NodeTypes.Structure.yaml | 35 +++++---- Configuration/Settings.yaml | 34 ++++----- .../TypoScript/Prototypes/BlockGrid.ts2 | 8 +-- .../Private/TypoScript/Prototypes/Grid.ts2 | 22 ++---- 6 files changed, 94 insertions(+), 84 deletions(-) diff --git a/Classes/M12/Foundation/NodeTypePostprocessor/AbstractGridNodeTypePostprocessor.php b/Classes/M12/Foundation/NodeTypePostprocessor/AbstractGridNodeTypePostprocessor.php index 9b7f9f1..9b4ec05 100644 --- a/Classes/M12/Foundation/NodeTypePostprocessor/AbstractGridNodeTypePostprocessor.php +++ b/Classes/M12/Foundation/NodeTypePostprocessor/AbstractGridNodeTypePostprocessor.php @@ -62,28 +62,42 @@ public function injectSettings(array $settings) { public function process(NodeType $nodeType, array &$configuration, array $options) { $this->validateSettings(); - /** @var string $device: small, medium, large */ - foreach ($this->settings['devices'] as $device => $deviceData) { - foreach ($this->settings[static::$SETTINGS_SECTION] as $set => $setData) { - $propertyName = sprintf('class%s%s', ucfirst($device), ucfirst($set)); - $defaultValue = isset($setData['defaults'][$device]) ? $setData['defaults'][$device] : ''; - $configuration['properties'][$propertyName] = array( - 'type' => 'string', - 'defaultValue' => $defaultValue, - 'ui' => array( -// 'label' => $propertyName, - 'reloadIfChanged' => true, - 'inspector' => array( - 'group' => $setData['uiInspectorGroup'], - 'position' => 1, - 'editor' => 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor', - 'editorOptions' => $this->getEditorOptions($device, $set, $setData), - ), - ), - ); + $k = 0; + foreach ($this->settings[static::$SETTINGS_SECTION] as $set => $setData) { + $propertyName = sprintf('classGrid%s', ucfirst($set)); + + $editorValues = []; + $defaultValue = isset($setData['defaults']) ? $setData['defaults'] : ['']; + + /** @var string $device: small, medium, large */ + foreach ($this->settings['devices'] as $device => $deviceData) { + $groupLabel = $deviceData['label']; + $editorValues += $this->getEditorValues($set, $setData, $device, $groupLabel); } - } + $configuration['properties'][$propertyName] = [ + 'type' => 'array', + 'defaultValue' => $defaultValue, + 'ui' => [ + 'label' => $setData['label'], + 'reloadIfChanged' => true, + 'inspector' => [ + 'group' => $setData['uiInspectorGroup'], + 'position' => ($k+1)*10, + 'editor' => 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor', + 'editorOptions' => [ + 'multiple' => TRUE, + 'allowEmpty' => TRUE, + 'placeholder' => 'placeholder text...', + 'values' => $editorValues, + ], + ], + ], + ]; + + $k++; + } + // \TYPO3\Flow\var_dump($configuration); } @@ -95,12 +109,9 @@ public function process(NodeType $nodeType, array &$configuration, array $option * @param array $setData settings for the $set * @return array */ - protected function getEditorOptions($device, $set, array $setData) { - $editorOptions = array(); - - // empty 1st option - $editorOptions['placeholder'] = "- $device $set -"; - $editorOptions['values'][''] = array('label' => ''); + protected function getEditorValues($set, array $setData, $device, $groupLabel) { + $groupLabel = $groupLabel ? $groupLabel : $device; + $editorValues = []; $cssSuffixes = $this->settings[static::$SETTINGS_SECTION][$set]['cssClassSuffixes']; foreach ($cssSuffixes as $cssSuffix) { @@ -115,8 +126,9 @@ protected function getEditorOptions($device, $set, array $setData) { do { $valueName = $cssClass.$col; $labelName = $valueName; - $editorOptions['values'][$valueName] = array( + $editorValues[$valueName] = array( 'label' => $labelName, + 'group' => $groupLabel, ); $col++; } while (--$k); @@ -128,13 +140,14 @@ protected function getEditorOptions($device, $set, array $setData) { else { $valueName = $cssClass; $labelName = $valueName; - $editorOptions['values'][$valueName] = array( + $editorValues[$valueName] = array( 'label' => $labelName, + 'group' => $groupLabel, ); } } - return $editorOptions; + return $editorValues; } protected function validateSettings() { diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index a535ece..dae44cb 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -70,3 +70,11 @@ 'TYPO3.Neos.NodeTypes:Html': superTypes: abstractDevCustomTag: 'M12.Foundation:AbstractDevCustomTag' + + +'TYPO3.Neos:ContentCollection': + constraints: + nodeTypes: + # @see M12.Foundation:Column.ui.group description to see why we deny it here... + 'M12.Foundation:Column': FALSE + '*': TRUE diff --git a/Configuration/NodeTypes.Structure.yaml b/Configuration/NodeTypes.Structure.yaml index 59f0aec..f461b64 100644 --- a/Configuration/NodeTypes.Structure.yaml +++ b/Configuration/NodeTypes.Structure.yaml @@ -39,21 +39,26 @@ ui: label: 'Grid Column' icon: 'icon-th-large' - group: 'na' + + # 2014-12-13: Temporary workaround: + # + # There's some weird behaviour (since Neos 1.2) with node types in fake group. + # Before 1.2 you could assign node type to fake, non-existing group + # which made that node type available, but not via UI. + # + # Since 1.2 it results with problems TYPO3.Neos:Content.properties._nodeType + # which is a property with 'select' type. When that 'select' cannot find + # given node type (i.e. 'M12.Foundation:Column') because it's not "listed", + # it seems to try to invalidate the value and set the _nodeType to the + # 1st available value (usually: Headline). It makes editing 'M12.Foundation:Column' + # impossible as it would switch the _nodeType after any save. +# group: 'foundationStructure' + inspector: groups: - gridSize: - label: 'Grid size' + grid: + label: 'Grid options' position: 6 - gridOffset: - label: 'Grid offset' - position: 7 - gridPushPull: - label: 'Grid push / pull' - position: 8 - gridAlign: - label: 'Grid align' - position: 9 childNodes: column: type: 'TYPO3.Neos:ContentCollection' @@ -73,8 +78,8 @@ label: 'End column (for incomplete row)' reloadIfChanged: TRUE inspector: - group: 'gridSize' - position: 999 + group: 'grid' + position: 11 # Abstract NodeType for all M12.Foundation:GridColumnsX @@ -217,7 +222,7 @@ inlineEditable: TRUE inspector: groups: - blockGridSettings: + grid: label: 'Block Grid settings' position: 9 childNodes: diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 821892f..9cc0be2 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -49,30 +49,30 @@ M12: # to generate required properties for M12.Foundation:Column node type gridSettings: size: - label: 'Column width' + label: 'Grid column width' cssClassSuffixes: [ '-' ] # DEVICE-X, eg: small-X, medium-Y, large-Z appliedPerColumn: true - uiInspectorGroup: gridSize + uiInspectorGroup: grid offset: - label: 'Column offset' + label: 'Grid column offset' cssClassSuffixes: [ '-offset-' ] # DEVICE-offset-X, eg: small-offset-X, medium-offset-Y, large-offset-Z appliedPerColumn: true - uiInspectorGroup: gridOffset + uiInspectorGroup: grid pushPull: - label: 'Column push / pull' + label: 'Grid column push / pull' cssClassSuffixes: [ '-push-', '-pull-' ] # DEVICE-push-X, eg: small-push-X, medium-push-Y, large-push-Z appliedPerColumn: true - uiInspectorGroup: gridPushPull - resetOrder: - label: 'Column reset order' - cssClassSuffixes: [ '-reset-order' ] # e.g. small-reset-order - appliedPerColumn: false - uiInspectorGroup: gridPushPull + uiInspectorGroup: grid align: - label: 'Centered' + label: 'Grid column align' cssClassSuffixes: [ '-centered', '-uncentered' ] # e.g. small-centered, large-centered appliedPerColumn: false - uiInspectorGroup: gridAlign + uiInspectorGroup: grid + resetOrder: + label: 'Grid column reset order' + cssClassSuffixes: [ '-reset-order' ] # e.g. small-reset-order + appliedPerColumn: false + uiInspectorGroup: grid # @see AbstractGridNodeTypePostprocessor which utilizes these settings # to generate required properties for M12.Foundation:BlockGrid node type @@ -81,8 +81,8 @@ M12: label: 'Number of items per row' cssClassSuffixes: [ '-block-grid-' ] # DEVICE-block-grid-X, eg: small-block-grid-X, medium-block-grid-Y, large-block-grid-Z appliedPerColumn: true - uiInspectorGroup: blockGridSettings + uiInspectorGroup: grid defaults: # default values per-device - small: small-block-grid-1 - medium: medium-block-grid-2 - large: large-block-grid-3 + - small-block-grid-1 + - medium-block-grid-2 + - large-block-grid-3 diff --git a/Resources/Private/TypoScript/Prototypes/BlockGrid.ts2 b/Resources/Private/TypoScript/Prototypes/BlockGrid.ts2 index 096da88..206c9e3 100644 --- a/Resources/Private/TypoScript/Prototypes/BlockGrid.ts2 +++ b/Resources/Private/TypoScript/Prototypes/BlockGrid.ts2 @@ -1,13 +1,9 @@ prototype(M12.Foundation:BlockGrid) < prototype(M12.Foundation:Content) { templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/BlockGrid.html' sectionName = 'blockGrid' - node = ${node} - - attributes.class.smallItemsPerRow = ${q(node).property('classSmallItemsPerRow') ? q(node).property('classSmallItemsPerRow') : null} - attributes.class.mediumItemsPerRow = ${q(node).property('classMediumItemsPerRow') ? q(node).property('classMediumItemsPerRow') : null} - attributes.class.largeItemsPerRow = ${q(node).property('classLargeItemsPerRow') ? q(node).property('classLargeItemsPerRow') : null} - + + attributes.class.itemsPerRow = ${q(node).property('classGridItemsPerRow') ? String.trim(Array.join(q(node).property('classGridItemsPerRow'), ' ')) : null} @override.parentAttributes = ${this.attributes} blockGridContent = TYPO3.Neos:ContentCollection { diff --git a/Resources/Private/TypoScript/Prototypes/Grid.ts2 b/Resources/Private/TypoScript/Prototypes/Grid.ts2 index 225c95f..64f1a14 100644 --- a/Resources/Private/TypoScript/Prototypes/Grid.ts2 +++ b/Resources/Private/TypoScript/Prototypes/Grid.ts2 @@ -7,23 +7,11 @@ prototype(M12.Foundation:Column) < prototype(M12.Foundation:Content) { attributes.class.nodeType.@process.columns = ${value + ' columns'} attributes.class.endColumn = ${q(node).property('classEndColumn') ? 'end' : null} - attributes.class.smallSize = ${q(node).property('classSmallSize') ? q(node).property('classSmallSize'): null} - attributes.class.smallOffset = ${q(node).property('classSmallOffset') ? q(node).property('classSmallOffset') : null} - attributes.class.smallPushPull = ${q(node).property('classSmallPushPull') ? q(node).property('classSmallPushPull') : null} - attributes.class.smallResetOrder = ${q(node).property('classSmallResetOrder') ? q(node).property('classSmallResetOrder') : null} - attributes.class.smallAlign = ${q(node).property('classSmallAlign') ? q(node).property('classSmallAlign') : null} - - attributes.class.mediumSize = ${q(node).property('classMediumSize') ? q(node).property('classMediumSize') : null} - attributes.class.mediumOffset = ${q(node).property('classMediumOffset') ? q(node).property('classMediumOffset') : null} - attributes.class.mediumPushPull = ${q(node).property('classMediumPushPull') ? q(node).property('classMediumPushPull') : null} - attributes.class.mediumResetOrder = ${q(node).property('classMediumResetOrder') ? q(node).property('classMediumResetOrder') : null} - attributes.class.mediumAlign = ${q(node).property('classMediumAlign') ? q(node).property('classMediumAlign') : null} - - attributes.class.largeSize = ${q(node).property('classLargeSize') ? q(node).property('classLargeSize') : null} - attributes.class.largeOffset = ${q(node).property('classLargeOffset') ? q(node).property('classLargeOffset') : null} - attributes.class.largePushPull = ${q(node).property('classLargePushPull') ? q(node).property('classLargePushPull') : null} - attributes.class.largeResetOrder = ${q(node).property('classLargeResetOrder') ? q(node).property('classLargeResetOrder') : null} - attributes.class.largeAlign = ${q(node).property('classLargeAlign') ? q(node).property('classLargeAlign') : null} + attributes.class.gridSize = ${q(node).property('classGridSize') ? Array.join(q(node).property('classGridSize'), ' '): null} + attributes.class.gridOffset = ${q(node).property('classGridOffset') ? Array.join(q(node).property('classGridOffset'), ' ') : null} + attributes.class.gridPushPull = ${q(node).property('classGridPushPull') ? Array.join(q(node).property('classGridPushPull'), ' ') : null} + attributes.class.gridResetOrder = ${q(node).property('classGridResetOrder') ? Array.join(q(node).property('classGridResetOrder'), ' ') : null} + attributes.class.gridAlign = ${q(node).property('classGridAlign') ? Array.join(q(node).property('classGridAlign'), ' ') : null} columnContent = TYPO3.Neos:ContentCollection { nodePath = 'column' From b536ebc6b51c7a17de4ec3c09286ccc1f88089e9 Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 14:25:48 +0000 Subject: [PATCH 08/23] Custom ContentCollectionImplementation removed as not necessary anymore Setting default node properties, where needed, should be done in more fashionable way, using events/signals when node is created. --- .../ContentCollectionImplementation.php | 136 ------------------ .../TypoScript/Neos/ContentCollection.ts2 | 2 - 2 files changed, 138 deletions(-) delete mode 100644 Classes/M12/Foundation/TypoScript/ContentCollectionImplementation.php diff --git a/Classes/M12/Foundation/TypoScript/ContentCollectionImplementation.php b/Classes/M12/Foundation/TypoScript/ContentCollectionImplementation.php deleted file mode 100644 index 4ea4101..0000000 --- a/Classes/M12/Foundation/TypoScript/ContentCollectionImplementation.php +++ /dev/null @@ -1,136 +0,0 @@ -settings = $settings; - } - - /** - * Inside live workspace, it does NOT render extra DIV.content-collection. - * - * This is rather dirty/temporary hack as it breaks the rule, that rendered markup - * is the same in the Neos back-end and in the front-end. - * - * @return string - */ - public function evaluate() { - $contentCollectionNode = $this->getContentCollectionNode(); - if ($contentCollectionNode === null) { - return parent::evaluate(); - } - - $this->setDefaultProperties($contentCollectionNode); - - return parent::evaluate(); - } - - /** - * Set essential default properties on some nodes - * - * E.g. when Grid with 2 columns is inserted, it sets default size for each column, - * before user sets its own values. - * - * This is experimental, probably there's a better way to inject these properties. - * - * @param NodeInterface $contentCollectionNode - */ - protected function setDefaultProperties(NodeInterface $contentCollectionNode) { - $parentNode = $contentCollectionNode->getParent(); - $parentNodeType = $parentNode->getNodeType()->getName(); - $nodeType = $contentCollectionNode->getNodeType()->getName(); - - switch ($parentNodeType) { - // Set 1st tab as active tab (otherwise all are hidden and it's hard to add any content there. - case 'M12.Foundation:Tabs2': - case 'M12.Foundation:Tabs3': - case 'M12.Foundation:Tabs4': - case 'M12.Foundation:Tabs5': - case 'M12.Foundation:Tabs6': - // already set? - if ($contentCollectionNode->getProperty('activeTab')) - break; - - // otherwise check if any child has it set - /** @var NodeInterface[] $children */ - if (!($children = $parentNode->getChildNodes())) - return; - - foreach ($children as $node) { - if ($node->getProperty('activeTab')) - return; - } - - // pick up the 1st tab and mark it as active - $node = array_shift($children); - $node->setProperty('activeTab', true); - $this->persistenceManager->persistAll(); - break; - } - - switch ($nodeType) { - case 'M12.Foundation:Column': - case 'M12.Foundation:ColumnEnd': - $gridSize = $this->settings['gridSize']; - // extract num of columns from 'M12.Foundation:GridRowXCol' node type - $columns = (int)substr($parentNodeType, strlen('M12.Foundation:GridRow'), 1); - - // In case M12.Foundation:Column has been placed as a child of element - // different than M12.Foundation:GridColumnsX, make sure we do not divide by 0! - $defaultColumns = $columns ? floor($gridSize / $columns) : $gridSize; - - $sizeSettings = array(); - foreach (array_keys($this->settings['devices']) as $device) { - $name = 'class'.ucfirst($device).'Size'; - $sizeSettings[$name] = $contentCollectionNode->getProperty($name); - } - if (!array_filter($sizeSettings)) { - $keys = array_keys($sizeSettings); - $property = $keys[0]; - $contentCollectionNode->setProperty($property, 'small-'.$defaultColumns); - $this->persistenceManager->persistAll(); - } - break; - } - } -} diff --git a/Resources/Private/TypoScript/Neos/ContentCollection.ts2 b/Resources/Private/TypoScript/Neos/ContentCollection.ts2 index 18f85ee..5879365 100644 --- a/Resources/Private/TypoScript/Neos/ContentCollection.ts2 +++ b/Resources/Private/TypoScript/Neos/ContentCollection.ts2 @@ -1,6 +1,4 @@ prototype(TYPO3.Neos:ContentCollection) { - @class = 'M12\\Foundation\\TypoScript\\ContentCollectionImplementation' - # Due to (unknown?) reasons ContentCollection inherits 'attributes' properties # set in the parent node (incl. tagName). Re-set those values # so it renders default
container, From cb82f7adc81ea33b8fc081372943acf550571bcc Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 14:27:35 +0000 Subject: [PATCH 09/23] FontIcon: re-factored, uses multiple SelectBoxEditor --- Configuration/NodeTypes.Abstracts.yaml | 74 ++++++++----------- Configuration/NodeTypes.Content.yaml | 2 + .../Private/Templates/NodeTypes/FontIcon.html | 2 +- .../TypoScript/Prototypes/FontIcon.ts2 | 20 +++-- 4 files changed, 44 insertions(+), 54 deletions(-) diff --git a/Configuration/NodeTypes.Abstracts.yaml b/Configuration/NodeTypes.Abstracts.yaml index e6606ef..1c6c966 100644 --- a/Configuration/NodeTypes.Abstracts.yaml +++ b/Configuration/NodeTypes.Abstracts.yaml @@ -227,9 +227,9 @@ inspector: groups: fontIconOptions: - label: 'Font Awesome icon' - # Put this group somewhere in the middle... - position: 96 + label: 'FontAwesome.io icon' + position: 90 + tab: view properties: faName: type: string @@ -240,77 +240,67 @@ group: 'fontIconOptions' editorOptions: placeholder: '...as listed on fontawesome.io' - faSize: - type: string + faOptions: + type: array + defaultValue: [''] ui: + label: 'Icon options' reloadIfChanged: TRUE inspector: group: 'fontIconOptions' editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: - placeholder: 'Icon size' + placeholder: 'Icon options' + allowEmpty: TRUE values: - '': - label: '' + # Icon size fa-lg: label: 'Size: large' + group: 'Icon size' fa-2x: label: 'Size: x2' + group: 'Icon size' fa-3x: label: 'Size: x3' + group: 'Icon size' fa-4x: label: 'Size: x4' + group: 'Icon size' fa-5x: label: 'Size: x5' - faRotation: - type: string - ui: - reloadIfChanged: TRUE - inspector: - group: 'fontIconOptions' - editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' - editorOptions: - placeholder: 'Icon rotation' - values: - '': - label: '' + group: 'Icon size' + # Icon rotation: fa-rotate-90: label: 'Rotate 90 degree' + group: 'Icon rotation' fa-rotate-180: label: 'Rotate 180 degree' + group: 'Icon rotation' fa-rotate-270: label: 'Rotate 270 degree' + group: 'Icon rotation' fa-flip-horizontal: label: 'Flip horizontal' + group: 'Icon rotation' fa-flip-vertical: label: 'Flip vertical' + group: 'Icon rotation' + # Make it... + fa-spin: + label: 'a spinner' + group: 'Make it...' + fa-fw: + label: 'have a fixed width' + group: 'Make it...' + right: + label: 'right aligned' + group: 'Make it...' faCustomCss: type: string ui: - label: 'Font Awesome icon custom css' + label: 'Icon custom inline CSS' reloadIfChanged: TRUE inspector: group: 'fontIconOptions' editorOptions: placeholder: 'e.g. padding-right: 5px;' - faSpin: - type: boolean - ui: - label: 'Make it a spinner' - reloadIfChanged: TRUE - inspector: - group: 'fontIconOptions' - faFixedWidth: - type: boolean - ui: - label: 'Make it have a fixed with' - reloadIfChanged: TRUE - inspector: - group: 'fontIconOptions' - faRightAlign: - type: boolean - ui: - label: 'Make it right aligned' - reloadIfChanged: TRUE - inspector: - group: 'fontIconOptions' diff --git a/Configuration/NodeTypes.Content.yaml b/Configuration/NodeTypes.Content.yaml index 202f9ee..57db9c3 100644 --- a/Configuration/NodeTypes.Content.yaml +++ b/Configuration/NodeTypes.Content.yaml @@ -340,7 +340,9 @@ groups: fontIconOptions: # Put this group at the very beginning for this content element + # Also move it to the very 1st, default tab position: 10 + tab: default properties: faName: defaultValue: 'circle-o-notch' diff --git a/Resources/Private/Templates/NodeTypes/FontIcon.html b/Resources/Private/Templates/NodeTypes/FontIcon.html index 900a0b5..d02af86 100644 --- a/Resources/Private/Templates/NodeTypes/FontIcon.html +++ b/Resources/Private/Templates/NodeTypes/FontIcon.html @@ -1,3 +1,3 @@ - style="{faCustomCss}"> + style="{faCustomCss}"> diff --git a/Resources/Private/TypoScript/Prototypes/FontIcon.ts2 b/Resources/Private/TypoScript/Prototypes/FontIcon.ts2 index 31f2e9d..4a83d78 100644 --- a/Resources/Private/TypoScript/Prototypes/FontIcon.ts2 +++ b/Resources/Private/TypoScript/Prototypes/FontIcon.ts2 @@ -1,20 +1,18 @@ -prototype(M12.Foundation:FontIcon) < prototype(M12.Foundation:Content) { - node = ${node} -} - # Create separate TypoScript object which will be rendered inside another NodeType. # It's done this way to avoid default TYPO3.Neos:Content behaviour in Neos backend -# (ie. we don't want there toolbar with add/remove icons etc as it's misleading). +# (ie. we don't want there toolbar with add/remove icons etc as it would be misleading). prototype(M12.Foundation:FontIconSimple) < prototype(TYPO3.TypoScript:Template) { templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/FontIcon.html' node = ${node} faName = ${q(node).property('faName')} - faSize = ${q(node).property('faSize')} - faRotation = ${q(node).property('faRotation')} - faSpin = ${q(node).property('faSpin')} - faFixedWidth = ${q(node).property('faFixedWidth')} - faRightAlign = ${q(node).property('faRightAlign')} - + faOptions = ${q(node).property('faOptions') ? String.trim(Array.join(q(node).property('faOptions'), ' ')) : null} faCustomCss = ${q(node).property('faCustomCss')} } + +prototype(M12.Foundation:FontIcon) < prototype(M12.Foundation:Content) { + node = ${node} + + # Join 'faOptions' same way as in M12.Foundation:FontIconSimple + faOptions < prototype(M12.Foundation:FontIconSimple).faOptions +} From 902b4900444ed0fb0b0e6f398cd3c25ffbb0f4bf Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 14:31:04 +0000 Subject: [PATCH 10/23] magellanSupport, fragmentId: support for few more node types (Headline, Menu) + cosmetic improvements --- Configuration/NodeTypes.Abstracts.yaml | 42 +++++++++---------- Configuration/NodeTypes.Navigation.yaml | 16 +++++-- Configuration/NodeTypes.Neos.Content.yaml | 1 + Configuration/NodeTypes.Neos.Documents.yaml | 8 +++- .../Private/Templates/Neos/Headline.html | 1 + Resources/Private/Templates/Neos/Menu.html | 2 + Resources/Private/Templates/Neos/Partials | 1 + .../Templates/NodeTypes/Partials/Anchor.html | 2 +- .../Private/Templates/NodeTypes/TopBar.html | 2 + 9 files changed, 48 insertions(+), 27 deletions(-) create mode 120000 Resources/Private/Templates/Neos/Partials diff --git a/Configuration/NodeTypes.Abstracts.yaml b/Configuration/NodeTypes.Abstracts.yaml index 1c6c966..ce74d27 100644 --- a/Configuration/NodeTypes.Abstracts.yaml +++ b/Configuration/NodeTypes.Abstracts.yaml @@ -140,9 +140,12 @@ label: 'FOOTER' # -# Mixin for content nodes where 'magellanSupport' property is needed +# Mixin: +# Navigation: #fragment, magellan support # -'M12.Foundation:AbstractNavMagellanSupport': +'M12.Foundation:AbstractNavSailingType': + superTypes: + - 'M12.Foundation:AbstractNavFragmentId' abstract: TRUE properties: magellanSupport: @@ -152,6 +155,7 @@ reloadIfChanged: TRUE inspector: group: 'sailingOptions' + position: 9 # # Mixin for document/content nodes with 'fragmentId' property @@ -160,6 +164,13 @@ # 'M12.Foundation:AbstractNavFragmentId': abstract: TRUE + ui: + inspector: + groups: + sailingOptions: + label: 'Sailing options' + position: 96 + tab: meta properties: fragmentId: type: string @@ -185,6 +196,12 @@ # 'M12.Foundation:AbstractNavFixedSticky': abstract: TRUE + ui: + inspector: + groups: + menuPosition: + label: 'Menu positioning' + position: 31 # After Neos menu 'options' group properties: classNavFixed: type: boolean @@ -192,31 +209,14 @@ label: 'Fixed' reloadIfChanged: TRUE inspector: - group: 'options' + group: 'menuPosition' classNavSticky: type: boolean ui: label: 'Sticky' reloadIfChanged: TRUE inspector: - group: 'options' - -# -# Mixin: -# Navigation: #fragment, magellan support -# -'M12.Foundation:AbstractNavSailingType': - superTypes: - - 'M12.Foundation:AbstractNavFragmentId' - - 'M12.Foundation:AbstractNavMagellanSupport' - abstract: TRUE - ui: - inspector: - groups: - sailingOptions: - label: 'Sailing options' - position: 96 - + group: 'menuPosition' # # Mixin: Font Awesome icon diff --git a/Configuration/NodeTypes.Navigation.yaml b/Configuration/NodeTypes.Navigation.yaml index 897547e..13ae61a 100644 --- a/Configuration/NodeTypes.Navigation.yaml +++ b/Configuration/NodeTypes.Navigation.yaml @@ -11,7 +11,7 @@ superTypes: - 'TYPO3.Neos.NodeTypes:Menu' - 'M12.Foundation:AbstractNavFixedSticky' - - 'M12.Foundation:AbstractNavMagellanSupport' + - 'M12.Foundation:AbstractNavSailingType' ui: label: 'Top Bar' icon: 'icon-sitemap' @@ -21,6 +21,8 @@ navOptions: label: 'Top Bar options' position: 9 + sailingOptions: + tab: default properties: topBarTitle: type: string @@ -67,6 +69,7 @@ label: 'Side Nav' icon: 'icon-th-list' group: 'foundationNavigation' + inlineEditable: TRUE childNodes: content: type: 'TYPO3.Neos:ContentCollection' @@ -79,10 +82,14 @@ superTypes: - 'TYPO3.Neos.NodeTypes:Menu' - 'M12.Foundation:AbstractNavFixedSticky' - - 'M12.Foundation:AbstractNavMagellanSupport' + - 'M12.Foundation:AbstractNavSailingType' ui: label: 'Side Nav (live)' group: 'foundationNavigation' + inspector: + groups: + sailingOptions: + tab: default # @@ -95,6 +102,7 @@ label: 'Sub Nav' icon: 'icon-barcode' group: 'foundationNavigation' + inlineEditable: TRUE inspector: groups: options: @@ -122,7 +130,7 @@ superTypes: - 'TYPO3.Neos.NodeTypes:Menu' - 'M12.Foundation:AbstractNavFixedSticky' - - 'M12.Foundation:AbstractNavMagellanSupport' + - 'M12.Foundation:AbstractNavSailingType' ui: label: 'Sub Nav (live)' group: 'foundationNavigation' @@ -131,6 +139,8 @@ navOptions: label: 'Sub Nav options' position: 9 + sailingOptions: + tab: default properties: title: type: string diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index dae44cb..17e0516 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -41,6 +41,7 @@ 'TYPO3.Neos.NodeTypes:Headline': superTypes: + abstractNavSailingType: 'M12.Foundation:AbstractNavSailingType' abstractDevCustomTag: 'M12.Foundation:AbstractDevCustomTag' abstractFontIcon: 'M12.Foundation:AbstractFontIcon' properties: diff --git a/Configuration/NodeTypes.Neos.Documents.yaml b/Configuration/NodeTypes.Neos.Documents.yaml index 248b322..3d51724 100644 --- a/Configuration/NodeTypes.Neos.Documents.yaml +++ b/Configuration/NodeTypes.Neos.Documents.yaml @@ -10,12 +10,16 @@ ui: inspector: position: 20 + uriPathSegment: + ui: + inspector: + position: 30 fragmentId: ui: - label: '#Fragment (URL)' + label: 'URL #fragment id' inspector: group: 'document' - position: 30 + position: 40 'TYPO3.Neos.NodeTypes:Page': diff --git a/Resources/Private/Templates/Neos/Headline.html b/Resources/Private/Templates/Neos/Headline.html index 7a41ba9..62025ad 100644 --- a/Resources/Private/Templates/Neos/Headline.html +++ b/Resources/Private/Templates/Neos/Headline.html @@ -2,6 +2,7 @@ {namespace ts=TYPO3\TypoScript\ViewHelpers} <{tagName}{attributes -> f:format.raw()}> + {neos:contentElement.editable(property: 'title')} diff --git a/Resources/Private/Templates/Neos/Menu.html b/Resources/Private/Templates/Neos/Menu.html index 7043d36..c542591 100644 --- a/Resources/Private/Templates/Neos/Menu.html +++ b/Resources/Private/Templates/Neos/Menu.html @@ -1,6 +1,8 @@ {namespace neos=TYPO3\Neos\ViewHelpers} {namespace ts=TYPO3\TypoScript\ViewHelpers} + + f:format.raw()}> <{tag}{attributes -> f:format.raw()}> diff --git a/Resources/Private/Templates/Neos/Partials b/Resources/Private/Templates/Neos/Partials new file mode 120000 index 0000000..6b69e3c --- /dev/null +++ b/Resources/Private/Templates/Neos/Partials @@ -0,0 +1 @@ +../NodeTypes/Partials \ No newline at end of file diff --git a/Resources/Private/Templates/NodeTypes/Partials/Anchor.html b/Resources/Private/Templates/NodeTypes/Partials/Anchor.html index ff22e07..97df44b 100644 --- a/Resources/Private/Templates/NodeTypes/Partials/Anchor.html +++ b/Resources/Private/Templates/NodeTypes/Partials/Anchor.html @@ -1,6 +1,6 @@ data-magellan-destination="{fragmentId}" name="{fragmentId}"> diff --git a/Resources/Private/Templates/NodeTypes/TopBar.html b/Resources/Private/Templates/NodeTypes/TopBar.html index ae218d5..a7eecee 100644 --- a/Resources/Private/Templates/NodeTypes/TopBar.html +++ b/Resources/Private/Templates/NodeTypes/TopBar.html @@ -1,6 +1,8 @@ {namespace neos=TYPO3\Neos\ViewHelpers} {namespace ts=TYPO3\TypoScript\ViewHelpers} + + f:format.raw()}> f:format.raw()} data-topbar> From 85022e95b9b2a236d1df9245e53ab7af13115be2 Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 14:45:13 +0000 Subject: [PATCH 11/23] Aloha: formatting options improved --- Configuration/NodeTypes.Buttons.yaml | 26 ++++++++++++++++++++--- Configuration/NodeTypes.Content.yaml | 26 ++++++++++++++++++++--- Configuration/NodeTypes.Neos.Content.yaml | 11 +++++----- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/Configuration/NodeTypes.Buttons.yaml b/Configuration/NodeTypes.Buttons.yaml index 4b24eb7..85a504b 100644 --- a/Configuration/NodeTypes.Buttons.yaml +++ b/Configuration/NodeTypes.Buttons.yaml @@ -32,9 +32,29 @@ inspector: group: 'options' aloha: - 'format': ['b', 'i', 'u', 'sub', 'sup'] - 'link': - 'a': FALSE + format: + strong: TRUE + em: TRUE + u: TRUE + sub: TRUE + sup: TRUE + p: FALSE + h1: FALSE + h2: FALSE + h3: FALSE + h4: FALSE + h5: FALSE + link: + a: FALSE + alignment: + left: FALSE + center: FALSE + right: FALSE + justify: FALSE + formatlesspaste: + button: FALSE + formatlessPasteOption: TRUE + autoparagraph: FALSE renderAnchor: type: boolean ui: diff --git a/Configuration/NodeTypes.Content.yaml b/Configuration/NodeTypes.Content.yaml index 57db9c3..77e0311 100644 --- a/Configuration/NodeTypes.Content.yaml +++ b/Configuration/NodeTypes.Content.yaml @@ -164,9 +164,29 @@ ui: inlineEditable: TRUE aloha: - 'format': ['b', 'i', 'u', 'sub', 'sup'] - 'link': - 'a': FALSE + format: + strong: TRUE + em: TRUE + u: TRUE + sub: TRUE + sup: TRUE + p: FALSE + h1: FALSE + h2: FALSE + h3: FALSE + h4: FALSE + h5: FALSE + link: + a: FALSE + alignment: + left: FALSE + center: FALSE + right: FALSE + justify: FALSE + formatlesspaste: + button: FALSE + formatlessPasteOption: TRUE + autoparagraph: FALSE accordionItemId: type: string ui: diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index 17e0516..b42d359 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -59,14 +59,13 @@ abstractDevCustomTag: 'M12.Foundation:AbstractDevCustomTag' abstractFontIcon: 'M12.Foundation:AbstractFontIcon' properties: - 'text': + text: ui: aloha: - 'format': - 'h4': TRUE - 'h5': TRUE - 'h6': TRUE - 'div': TRUE + format: + h4: TRUE + h5: TRUE + h6: TRUE 'TYPO3.Neos.NodeTypes:Html': superTypes: From 43c84045d4bf7b1b6b77d34cd9f047a4916bae71 Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 14:45:59 +0000 Subject: [PATCH 12/23] UI Inspector: tabs defined, groups/properties reorganised --- Configuration/NodeTypes.Abstracts.yaml | 53 +++++++++++---------- Configuration/NodeTypes.Content.yaml | 1 + Configuration/NodeTypes.Media.yaml | 1 + Configuration/NodeTypes.Neos.Content.yaml | 9 ++-- Configuration/NodeTypes.Neos.Documents.yaml | 15 ++++-- Configuration/NodeTypes.yaml | 26 +++++++++- 6 files changed, 67 insertions(+), 38 deletions(-) diff --git a/Configuration/NodeTypes.Abstracts.yaml b/Configuration/NodeTypes.Abstracts.yaml index ce74d27..4b5efd0 100644 --- a/Configuration/NodeTypes.Abstracts.yaml +++ b/Configuration/NodeTypes.Abstracts.yaml @@ -7,14 +7,19 @@ inspector: groups: dev: - label: 'Advanced' + label: 'Advanced settings' position: 95 + tab: dev + devCode: + label: 'Custom code' + position: 95 + tab: dev properties: - customHtmlId: + customCssClass: type: string defaultValue: '' ui: - label: 'Wrapper custom HTML ID' + label: 'Wrapper custom class(es)' reloadIfChanged: TRUE inspector: group: 'dev' @@ -24,22 +29,22 @@ placeholder: 'None' validation: regularExpression: - regularExpression: '/^[a-z0-9\-]+$/i' - customCssClass: + regularExpression: '/^[a-z0-9\- ]+$/i' + customHtmlId: type: string defaultValue: '' ui: - label: 'Wrapper custom class(es)' + label: 'Wrapper custom HTML ID' reloadIfChanged: TRUE inspector: group: 'dev' - position: 20 + position: 11 editor: Content/Inspector/Editors/TextFieldEditor editorOptions: placeholder: 'None' validation: regularExpression: - regularExpression: '/^[a-z0-9\- ]+$/i' + regularExpression: '/^[a-z0-9\-]+$/i' customCssCode: type: string defaultValue: '' @@ -47,18 +52,18 @@ label: 'Wrapper inline CSS' reloadIfChanged: TRUE inspector: - group: 'dev' + group: 'devCode' position: 30 editor: Content/Inspector/Editors/TextFieldEditor editorOptions: - placeholder: 'None' + placeholder: 'e.g. margin-top: 3rem' customUserAttributes: type: string ui: label: 'Custom attributes (one per line)' reloadIfChanged: TRUE inspector: - group: 'dev' + group: 'devCode' position: 40 editor: 'Content/Inspector/Editors/TextAreaEditor' editorOptions: @@ -70,25 +75,24 @@ ui: inspector: groups: - dev: - label: 'Advanced' - position: 95 + devView: + position: 10 + tab: view + label: 'Custom look' properties: customLook: type: string - defaultValue: '' ui: label: 'Predefined style / look' reloadIfChanged: TRUE inspector: - group: 'dev' + group: 'devView' position: 40 editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'None' + allowEmpty: TRUE values: - '': - label: '' style-1: label: 'Style 1' style-2: @@ -105,25 +109,24 @@ ui: inspector: groups: - dev: - label: 'Advanced' - position: 95 + devSemantic: + label: 'Semantic Web' + position: 96 + tab: dev properties: customTagName: type: string - defaultValue: 'div' ui: label: 'Wrapper semantic tag type' reloadIfChanged: TRUE inspector: - group: 'dev' + group: 'devSemantic' position: 50 editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'Default / None' + allowEmpty: TRUE values: - '': - label: '' main: label: 'MAIN' header: diff --git a/Configuration/NodeTypes.Content.yaml b/Configuration/NodeTypes.Content.yaml index 77e0311..f2181ea 100644 --- a/Configuration/NodeTypes.Content.yaml +++ b/Configuration/NodeTypes.Content.yaml @@ -96,6 +96,7 @@ label: 'Dropdown Content' icon: 'icon-minus' group: 'foundationContent' + inlineEditable: TRUE childNodes: content: type: 'TYPO3.Neos:ContentCollection' diff --git a/Configuration/NodeTypes.Media.yaml b/Configuration/NodeTypes.Media.yaml index 3a4882f..966f799 100644 --- a/Configuration/NodeTypes.Media.yaml +++ b/Configuration/NodeTypes.Media.yaml @@ -10,6 +10,7 @@ label: 'Orbit' icon: 'icon-picture' group: 'foundationMedia' + inlineEditable: TRUE inspector: groups: orbitSettings: diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index b42d359..40876e9 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -29,14 +29,11 @@ 'TYPO3.Neos.NodeTypes:TwoColumn': - ui: - group: 'na' + abstract: true 'TYPO3.Neos.NodeTypes:ThreeColumn': - ui: - group: 'na' + abstract: true 'TYPO3.Neos.NodeTypes:FourColumn': - ui: - group: 'na' + abstract: true 'TYPO3.Neos.NodeTypes:Headline': diff --git a/Configuration/NodeTypes.Neos.Documents.yaml b/Configuration/NodeTypes.Neos.Documents.yaml index 3d51724..85e07b4 100644 --- a/Configuration/NodeTypes.Neos.Documents.yaml +++ b/Configuration/NodeTypes.Neos.Documents.yaml @@ -32,7 +32,7 @@ ui: reloadIfChanged: TRUE inspector: - group: 'dev' + group: 'devCode' position: 31 # after 'customCssCode' editor: 'TYPO3.Neos/Inspector/Editors/CodeEditor' editorOptions: @@ -42,21 +42,26 @@ # Replace it with CssEditor customCssCode: ui: - label: null + label: '' inspector: editor: 'TYPO3.Neos/Inspector/Editors/CodeEditor' editorOptions: buttonLabel: 'Add custom CSS styles' highlightingMode: 'text/css' - # Inherited from M12.Foundation:DeveloperAbstract + # Inherited from M12.Foundation:AbstractDevBase customHtmlId: ui: label: 'Custom body ID' - # Inherited from M12.Foundation:DeveloperAbstract + # Inherited from M12.Foundation:AbstractDevBase customCssClass: ui: label: 'Custom body class(es)' - # Inherited from M12.Foundation:DeveloperAbstract + # Inherited from M12.Foundation:AbstractDevBase customLook: ui: label: 'Predefined body style' + # Inherited from M12.Foundation:AbstractDevBase + customUserAttributes: + type: string + ui: + label: 'Custom body attributes (one per line)' diff --git a/Configuration/NodeTypes.yaml b/Configuration/NodeTypes.yaml index 5e2ac6a..cec874b 100644 --- a/Configuration/NodeTypes.yaml +++ b/Configuration/NodeTypes.yaml @@ -1,3 +1,23 @@ +# Base node: define extra inspector tabs +'TYPO3.Neos:Node': + ui: + inspector: + tabs: + view: + label: 'Visual options' + position: 30 + icon: 'icon-tint' + device: + label: 'Device settings' + position: 50 + icon: 'icon-desktop' + dev: + label: 'Developer options' + position: 80 + icon: 'icon-code' + + + # ----------------------------------------------------------------------------- # # Abstract: foundation helper classes @@ -11,9 +31,11 @@ utilityClasses: label: 'Utility classes' position: 93 + tab: meta visibilityClasses: - label: 'Show/hide classes' + label: 'Show/hide content' position: 94 + tab: device properties: classHide: type: boolean @@ -58,7 +80,7 @@ reloadIfChanged: TRUE inspector: group: 'utilityClasses' - position: 40 + position: 25 editor: Content/Inspector/Editors/SelectBoxEditor editorOptions: placeholder: 'None' From 0c6c286c18942a45626f95bf6ab9a6089eba705f Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 17:48:24 +0000 Subject: [PATCH 13/23] Grid, BlockGrid, Container: node constraints implemented --- Configuration/NodeTypes.Abstracts.yaml | 10 +-- Configuration/NodeTypes.Neos.Content.yaml | 3 +- Configuration/NodeTypes.Structure.yaml | 81 +++++------------------ 3 files changed, 21 insertions(+), 73 deletions(-) diff --git a/Configuration/NodeTypes.Abstracts.yaml b/Configuration/NodeTypes.Abstracts.yaml index 4b5efd0..15c81f8 100644 --- a/Configuration/NodeTypes.Abstracts.yaml +++ b/Configuration/NodeTypes.Abstracts.yaml @@ -19,7 +19,7 @@ type: string defaultValue: '' ui: - label: 'Wrapper custom class(es)' + label: 'Element custom CSS class(es)' reloadIfChanged: TRUE inspector: group: 'dev' @@ -34,7 +34,7 @@ type: string defaultValue: '' ui: - label: 'Wrapper custom HTML ID' + label: 'Element custom HTML ID' reloadIfChanged: TRUE inspector: group: 'dev' @@ -49,7 +49,7 @@ type: string defaultValue: '' ui: - label: 'Wrapper inline CSS' + label: 'Element inline CSS' reloadIfChanged: TRUE inspector: group: 'devCode' @@ -60,7 +60,7 @@ customUserAttributes: type: string ui: - label: 'Custom attributes (one per line)' + label: 'Element extra attributes (one per line)' reloadIfChanged: TRUE inspector: group: 'devCode' @@ -117,7 +117,7 @@ customTagName: type: string ui: - label: 'Wrapper semantic tag type' + label: 'Element semantic tag type' reloadIfChanged: TRUE inspector: group: 'devSemantic' diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index 40876e9..5c81730 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -72,6 +72,5 @@ 'TYPO3.Neos:ContentCollection': constraints: nodeTypes: - # @see M12.Foundation:Column.ui.group description to see why we deny it here... - 'M12.Foundation:Column': FALSE + 'M12.Foundation:Column': FALSE # M12.Foundation:Column makes sense only inside M12.Foundation:GridRow* '*': TRUE diff --git a/Configuration/NodeTypes.Structure.yaml b/Configuration/NodeTypes.Structure.yaml index f461b64..66c55ba 100644 --- a/Configuration/NodeTypes.Structure.yaml +++ b/Configuration/NodeTypes.Structure.yaml @@ -13,6 +13,9 @@ icon: 'icon-hdd' group: 'foundationStructure' inlineEditable: TRUE + constraints: + nodeTypes: + '*': FALSE # Disallow everything, all content must go into child ContentCollection childNodes: content: type: 'TYPO3.Neos:ContentCollection' @@ -39,26 +42,14 @@ ui: label: 'Grid Column' icon: 'icon-th-large' - - # 2014-12-13: Temporary workaround: - # - # There's some weird behaviour (since Neos 1.2) with node types in fake group. - # Before 1.2 you could assign node type to fake, non-existing group - # which made that node type available, but not via UI. - # - # Since 1.2 it results with problems TYPO3.Neos:Content.properties._nodeType - # which is a property with 'select' type. When that 'select' cannot find - # given node type (i.e. 'M12.Foundation:Column') because it's not "listed", - # it seems to try to invalidate the value and set the _nodeType to the - # 1st available value (usually: Headline). It makes editing 'M12.Foundation:Column' - # impossible as it would switch the _nodeType after any save. -# group: 'foundationStructure' - inspector: groups: grid: label: 'Grid options' position: 6 + constraints: + nodeTypes: + '*': FALSE # Disallow everything, all content must go into child ContentCollection childNodes: column: type: 'TYPO3.Neos:ContentCollection' @@ -71,6 +62,8 @@ 'M12.Foundation:ColumnEnd': superTypes: - 'M12.Foundation:Column' + ui: + label: 'Grid Column (end)' properties: classEndColumn: type: boolean @@ -98,6 +91,10 @@ gridOptions: label: 'Grid options' position: 9 + constraints: + nodeTypes: + 'M12.Foundation:Column': TRUE + '*': FALSE properties: gridExtraWrapper: type: boolean @@ -151,57 +148,6 @@ col3: type: 'M12.Foundation:ColumnEnd' -'M12.Foundation:GridRow4Col': - superTypes: - - 'M12.Foundation:GridRowAbstract' - ui: - label: 'Grid row: 4 columns' - childNodes: - col1: - type: 'M12.Foundation:Column' - col2: - type: 'M12.Foundation:Column' - col3: - type: 'M12.Foundation:Column' - col4: - type: 'M12.Foundation:ColumnEnd' - -'M12.Foundation:GridRow5Col': - superTypes: - - 'M12.Foundation:GridRowAbstract' - ui: - label: 'Grid row: 5 columns' - childNodes: - col1: - type: 'M12.Foundation:Column' - col2: - type: 'M12.Foundation:Column' - col3: - type: 'M12.Foundation:Column' - col4: - type: 'M12.Foundation:Column' - col5: - type: 'M12.Foundation:ColumnEnd' - -'M12.Foundation:GridRow6Col': - superTypes: - - 'M12.Foundation:GridRowAbstract' - ui: - label: 'Grid row: 6 columns' - childNodes: - col1: - type: 'M12.Foundation:Column' - col2: - type: 'M12.Foundation:Column' - col3: - type: 'M12.Foundation:Column' - col4: - type: 'M12.Foundation:Column' - col5: - type: 'M12.Foundation:Column' - col6: - type: 'M12.Foundation:ColumnEnd' - @@ -225,6 +171,9 @@ grid: label: 'Block Grid settings' position: 9 + constraints: + nodeTypes: + '*': FALSE # Disallow everything, all content must go into child ContentCollection childNodes: content: type: 'TYPO3.Neos:ContentCollection' From c6d87653786e42a4696fe0a9d8fed571b141d970 Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 18:17:06 +0000 Subject: [PATCH 14/23] Buttons: improved, content restrictions --- Configuration/NodeTypes.Buttons.yaml | 77 ++++++++----------- .../Private/Templates/NodeTypes/Button.html | 6 +- .../Private/TypoScript/Prototypes/Button.ts2 | 43 +++++++++++ .../TypoScript/Prototypes/ButtonBar.ts2 | 10 --- .../TypoScript/Prototypes/ButtonGroup.ts2 | 19 ----- .../TypoScript/Prototypes/ButtonGroupItem.ts2 | 14 ---- 6 files changed, 78 insertions(+), 91 deletions(-) delete mode 100644 Resources/Private/TypoScript/Prototypes/ButtonBar.ts2 delete mode 100644 Resources/Private/TypoScript/Prototypes/ButtonGroup.ts2 delete mode 100644 Resources/Private/TypoScript/Prototypes/ButtonGroupItem.ts2 diff --git a/Configuration/NodeTypes.Buttons.yaml b/Configuration/NodeTypes.Buttons.yaml index 85a504b..6fa9bb7 100644 --- a/Configuration/NodeTypes.Buttons.yaml +++ b/Configuration/NodeTypes.Buttons.yaml @@ -9,20 +9,20 @@ - 'M12.Foundation:AbstractNavSailingType' - 'M12.Foundation:AbstractFontIcon' ui: - label: 'Button & Link' - icon: 'icon-minus' + label: 'Button / Link' + icon: 'icon-sign-blank' group: 'foundationButtons' inspector: groups: options: label: 'Button options' position: 6 - dev: - label: 'Button advanced options' - position: 7 extraOptions: label: 'Reveal & Dropdown options' position: 8 + constraints: + nodeTypes: + '*': FALSE # No children items allowed properties: label: type: string @@ -64,7 +64,6 @@ group: 'options' buttonType: type: string - defaultValue: '' ui: label: 'Button type' reloadIfChanged: TRUE @@ -73,9 +72,8 @@ editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'Default' + allowEmpty: TRUE values: - '': - label: '' submit: label: 'Submit' reset: @@ -84,7 +82,6 @@ label: 'Button' classSize: type: string - defaultValue: '' ui: label: 'Button size' reloadIfChanged: TRUE @@ -93,9 +90,8 @@ editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'Default' + allowEmpty: TRUE values: - '': - label: '' tiny: label: 'Tiny' small: @@ -104,7 +100,6 @@ label: 'Large' classAppearance: type: string - defaultValue: '' ui: label: 'Button appearance' reloadIfChanged: TRUE @@ -113,9 +108,8 @@ editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'Default' + allowEmpty: TRUE values: - '': - label: '' primary: label: 'Primary' success: @@ -124,7 +118,6 @@ label: 'Alert' classShape: type: string - defaultValue: '' ui: label: 'Button shape' reloadIfChanged: TRUE @@ -133,27 +126,25 @@ editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'Default' + allowEmpty: TRUE values: - '': - label: '' radius: label: 'Radius' round: label: 'Round' htmlHref: type: string - defaultValue: '' ui: label: 'Link' reloadIfChanged: TRUE inspector: group: 'options' + # TODO: Replace with LinkEditor when it is fixed (Neos 1.2.0: seems to be buggy, does not allow external URLs) editor: 'TYPO3.Neos/Inspector/Editors/TextFieldEditor' editorOptions: placeholder: 'e.g. http://www.example.com' htmlTargetBlank: type: string - defaultValue: '' ui: label: 'Open in new window' reloadIfChanged: TRUE @@ -162,22 +153,21 @@ editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'No' + allowEmpty: TRUE values: - '': - label: '' _blank: label: 'Yes' classIsDisabled: type: boolean ui: - label: 'Disable' + label: 'Disabled state' reloadIfChanged: TRUE inspector: group: 'options' classIsExpanded: type: boolean ui: - label: 'Expand' + label: 'Expanded button' reloadIfChanged: TRUE inspector: group: 'options' @@ -207,7 +197,6 @@ placeholder: 'e.g. myDropdown' dropdownDirection: type: string - defaultValue: '' ui: label: 'Dropdown direction' reloadIfChanged: TRUE @@ -216,9 +205,8 @@ editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'Default / Bottom' + allowEmpty: TRUE values: - '': - label: '' 'top': label: 'Top' 'right': @@ -248,20 +236,9 @@ reloadIfChanged: TRUE inspector: group: 'extraOptions' - # Override inherited properties from M12.Foundation:AbstractDevBase - customHtmlId: - ui: - label: 'Element custom ID' - customCssClass: - ui: - label: 'Element extra CSS class(es)' - customCssCode: - ui: - label: 'Element inline CSS' - # Override inherited properties from M12.Foundation:AbstractDevBase -# Button Group +# Button Group (list of buttons) 'M12.Foundation:ButtonGroup': superTypes: - 'TYPO3.Neos:Content' @@ -269,12 +246,16 @@ label: 'Button Group' icon: 'icon-minus' group: 'foundationButtons' + inlineEditable: TRUE + constraints: + nodeTypes: + 'M12.Foundation:Button': TRUE + '*': FALSE childNodes: - content: - type: 'TYPO3.Neos:ContentCollection' - + btn1: + type: 'M12.Foundation:Button' -# Button Bar +# Button Bar (group of button groups) 'M12.Foundation:ButtonBar': superTypes: - 'TYPO3.Neos:Content' @@ -282,7 +263,13 @@ label: 'Button Bar' icon: 'icon-minus' group: 'foundationButtons' + inlineEditable: TRUE + constraints: + nodeTypes: + 'M12.Foundation:ButtonGroup': TRUE + '*': FALSE childNodes: - content: - type: 'TYPO3.Neos:ContentCollection' - + group1: + type: 'M12.Foundation:ButtonGroup' + group2: + type: 'M12.Foundation:ButtonGroup' diff --git a/Resources/Private/Templates/NodeTypes/Button.html b/Resources/Private/Templates/NodeTypes/Button.html index 2e7ee67..a18896b 100644 --- a/Resources/Private/Templates/NodeTypes/Button.html +++ b/Resources/Private/Templates/NodeTypes/Button.html @@ -13,7 +13,7 @@
- +
@@ -23,7 +23,7 @@ f:format.raw()}> -
  • +
  • @@ -33,6 +33,6 @@ f:format.raw()}> - + diff --git a/Resources/Private/TypoScript/Prototypes/Button.ts2 b/Resources/Private/TypoScript/Prototypes/Button.ts2 index 2944297..9eae470 100644 --- a/Resources/Private/TypoScript/Prototypes/Button.ts2 +++ b/Resources/Private/TypoScript/Prototypes/Button.ts2 @@ -26,3 +26,46 @@ prototype(M12.Foundation:Button) < prototype(M12.Foundation:Content) { tag = ${renderAnchor or htmlHref ? 'a' : 'button'} } + +prototype(M12.Foundation:ButtonGroup) < prototype(M12.Foundation:Content) { + templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Button.html' + sectionName = 'buttonGroup' + + attributes.class.base = 'button-group' + + @override.parentAttributes = ${this.attributes} + + buttons = TYPO3.TypoScript:Collection { + collection = ${q(node).children('[instanceof M12.Foundation:Button]')} + itemRenderer = M12.Foundation:ButtonGroupItem + itemName = 'node' + iterationName = 'iterator' + } + + @process.wrapRemover = M12.Utils:WrapRemover + @process.wrapRemover.wrapperClass = 'extra-wrapper-required-by-neos-backend' +} + +prototype(M12.Foundation:ButtonGroupItem) < prototype(M12.Foundation:Content) { + templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Button.html' + sectionName = 'buttonGroupItem' + + iterator = ${iterator} + parentAttributes = ${parentAttributes} + + button = TYPO3.Neos:ContentCase +} + +# ButtonBar: group of button group(s) +prototype(M12.Foundation:ButtonBar) < prototype(M12.Foundation:Content) { + templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Button.html' + sectionName = 'buttonBar' + + attributes.class.base = 'button-bar' + + buttonGroups = TYPO3.TypoScript:Collection { + collection = ${q(node).children('[instanceof M12.Foundation:ButtonGroup]')} + itemRenderer = M12.Foundation:ButtonGroup + itemName = 'node' + } +} diff --git a/Resources/Private/TypoScript/Prototypes/ButtonBar.ts2 b/Resources/Private/TypoScript/Prototypes/ButtonBar.ts2 deleted file mode 100644 index bb66ec9..0000000 --- a/Resources/Private/TypoScript/Prototypes/ButtonBar.ts2 +++ /dev/null @@ -1,10 +0,0 @@ -prototype(M12.Foundation:ButtonBar) < prototype(M12.Foundation:Content) { - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Button.html' - sectionName = 'buttonBar' - - attributes.class.base = 'button-bar' - - buttonBarContent = TYPO3.Neos:ContentCollection { - nodePath = 'content' - } -} diff --git a/Resources/Private/TypoScript/Prototypes/ButtonGroup.ts2 b/Resources/Private/TypoScript/Prototypes/ButtonGroup.ts2 deleted file mode 100644 index 20a715a..0000000 --- a/Resources/Private/TypoScript/Prototypes/ButtonGroup.ts2 +++ /dev/null @@ -1,19 +0,0 @@ -prototype(M12.Foundation:ButtonGroup) < prototype(M12.Foundation:Content) { - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Button.html' - sectionName = 'buttonGroup' - - attributes.class.base = 'button-group' - - @override.parentAttributes = ${this.attributes} - - buttonGroupContent = TYPO3.Neos:ContentCollection { - nodePath = 'content' - - iterationName = 'iterator' - itemName = 'buttonGroupNodeItem' - itemRenderer = M12.Foundation:ButtonGroupItem - } - - @process.wrapRemover = M12.Utils:WrapRemover - @process.wrapRemover.wrapperClass = 'extra-wrapper-required-by-neos-backend' -} diff --git a/Resources/Private/TypoScript/Prototypes/ButtonGroupItem.ts2 b/Resources/Private/TypoScript/Prototypes/ButtonGroupItem.ts2 deleted file mode 100644 index 35ba4ca..0000000 --- a/Resources/Private/TypoScript/Prototypes/ButtonGroupItem.ts2 +++ /dev/null @@ -1,14 +0,0 @@ -prototype(M12.Foundation:ButtonGroupItem) < prototype(M12.Foundation:Content) { - # templatePath is needed as there's no BlockGridItem NodeType defined - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Button.html' - sectionName = 'buttonGroupItem' - - iterator = ${iterator} - parentAttributes = ${parentAttributes} - - buttonGroupItemContent = TYPO3.TypoScript:Collection { - collection = ${q(buttonGroupNodeItem)} - itemName = 'node' - itemRenderer = TYPO3.Neos:ContentCase - } -} From 77b75690f176dcd7a546c2d48ee95dc926b522a3 Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 18:35:56 +0000 Subject: [PATCH 15/23] Callouts: cosmetics + node constraints --- Configuration/NodeTypes.Callouts.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Configuration/NodeTypes.Callouts.yaml b/Configuration/NodeTypes.Callouts.yaml index 5029fca..c1fcdf8 100644 --- a/Configuration/NodeTypes.Callouts.yaml +++ b/Configuration/NodeTypes.Callouts.yaml @@ -13,11 +13,15 @@ label: 'Reveal Modal' icon: 'icon-fullscreen' group: 'foundationCalloutsPrompts' + inlineEditable: TRUE inspector: groups: options: label: 'Reveal Modal options' position: 9 + constraints: + nodeTypes: + '*': FALSE # All content must go into child ContentCollection childNodes: content: type: 'TYPO3.Neos:ContentCollection' @@ -62,11 +66,15 @@ label: 'Alert' icon: 'icon-warning-sign' group: 'foundationCalloutsPrompts' + inlineEditable: TRUE inspector: groups: options: label: 'Alert box options' position: 9 + constraints: + nodeTypes: + '*': FALSE # All content must go into child ContentCollection childNodes: content: type: 'TYPO3.Neos:ContentCollection' @@ -101,11 +109,15 @@ label: 'Panel' icon: 'icon-check-empty' group: 'foundationCalloutsPrompts' + inlineEditable: TRUE inspector: groups: options: label: 'Panel options' position: 9 + constraints: + nodeTypes: + '*': FALSE # All content must go into child ContentCollection childNodes: content: type: 'TYPO3.Neos:ContentCollection' @@ -113,7 +125,7 @@ classCallout: type: boolean ui: - label: 'Callout' + label: 'Style: callout' reloadIfChanged: TRUE inspector: group: 'options' From 3c83df1df9e918769d0b082d1c503b9127e33d4b Mon Sep 17 00:00:00 2001 From: ryzy Date: Mon, 15 Dec 2014 19:20:39 +0000 Subject: [PATCH 16/23] !!! Tabs: node types renamed!!! + node constraints + cosmetic improvements * M12.Foundation:TabContentItem renamed to M12.Foundation:TabItem * M12.Foundation:TabsAbstract renamed to M12.Foundation:Tabs * M12.Foundation:TabsX removed: with Neos 1.2 interface + node constraints it's easy enough for editor to add desired amount of TabItems ad-hoc --- Configuration/NodeTypes.Content.yaml | 96 +++---------------- Configuration/NodeTypes.Neos.Content.yaml | 1 + .../Private/TypoScript/Prototypes/Tabs.ts2 | 59 +++--------- 3 files changed, 27 insertions(+), 129 deletions(-) diff --git a/Configuration/NodeTypes.Content.yaml b/Configuration/NodeTypes.Content.yaml index f2181ea..fd4f135 100644 --- a/Configuration/NodeTypes.Content.yaml +++ b/Configuration/NodeTypes.Content.yaml @@ -210,18 +210,20 @@ # ----------------------------------------------------------------------------- # Tabs # ----------------------------------------------------------------------------- -'M12.Foundation:TabContentItem': +'M12.Foundation:TabItem': superTypes: - 'TYPO3.Neos:Content' ui: - label: 'Tabs Item' + label: 'Tab Item' icon: 'icon-angle-right' - group: 'na' inspector: groups: tabSettings: label: 'Tab item options' position: 9 + constraints: + nodeTypes: + '*': FALSE # All content must go to child ContentCollection childNodes: content: type: 'TYPO3.Neos:ContentCollection' @@ -243,8 +245,7 @@ position: 20 -'M12.Foundation:TabsAbstract': - abstract: TRUE +'M12.Foundation:Tabs': superTypes: - 'TYPO3.Neos:Content' - 'M12.Foundation:AbstractDevCustomTag' @@ -259,6 +260,15 @@ tabSettings: label: 'Tab item options' position: 9 + constraints: + nodeTypes: + 'M12.Foundation:TabItem': TRUE + '*': FALSE + childNodes: + tab1: + type: 'M12.Foundation:TabItem' + tab2: + type: 'M12.Foundation:TabItem' properties: vertical: type: boolean @@ -270,82 +280,6 @@ position: 10 -'M12.Foundation:Tabs2': - superTypes: - - 'M12.Foundation:TabsAbstract' - ui: - label: 'Tabs 2' - childNodes: - tab1: - type: 'M12.Foundation:TabContentItem' - tab2: - type: 'M12.Foundation:TabContentItem' - -'M12.Foundation:Tabs3': - superTypes: - - 'M12.Foundation:TabsAbstract' - ui: - label: 'Tabs 3' - childNodes: - tab1: - type: 'M12.Foundation:TabContentItem' - tab2: - type: 'M12.Foundation:TabContentItem' - tab3: - type: 'M12.Foundation:TabContentItem' - -'M12.Foundation:Tabs4': - superTypes: - - 'M12.Foundation:TabsAbstract' - ui: - label: 'Tabs 4' - childNodes: - tab1: - type: 'M12.Foundation:TabContentItem' - tab2: - type: 'M12.Foundation:TabContentItem' - tab3: - type: 'M12.Foundation:TabContentItem' - tab4: - type: 'M12.Foundation:TabContentItem' - -'M12.Foundation:Tabs5': - superTypes: - - 'M12.Foundation:TabsAbstract' - ui: - label: 'Tabs 5' - childNodes: - tab1: - type: 'M12.Foundation:TabContentItem' - tab2: - type: 'M12.Foundation:TabContentItem' - tab3: - type: 'M12.Foundation:TabContentItem' - tab4: - type: 'M12.Foundation:TabContentItem' - tab5: - type: 'M12.Foundation:TabContentItem' - -'M12.Foundation:Tabs6': - superTypes: - - 'M12.Foundation:TabsAbstract' - ui: - label: 'Tabs 6' - childNodes: - tab1: - type: 'M12.Foundation:TabContentItem' - tab2: - type: 'M12.Foundation:TabContentItem' - tab3: - type: 'M12.Foundation:TabContentItem' - tab4: - type: 'M12.Foundation:TabContentItem' - tab5: - type: 'M12.Foundation:TabContentItem' - tab6: - type: 'M12.Foundation:TabContentItem' - - # ----------------------------------------------------------------------------- # Font Awesome Icon # ----------------------------------------------------------------------------- diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index 5c81730..3195a7b 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -73,4 +73,5 @@ constraints: nodeTypes: 'M12.Foundation:Column': FALSE # M12.Foundation:Column makes sense only inside M12.Foundation:GridRow* + 'M12.Foundation:TabItem': FALSE # M12.Foundation:TabItem makes sense only inside M12.Foundation:Tabs* '*': TRUE diff --git a/Resources/Private/TypoScript/Prototypes/Tabs.ts2 b/Resources/Private/TypoScript/Prototypes/Tabs.ts2 index 50932c5..aee27c5 100644 --- a/Resources/Private/TypoScript/Prototypes/Tabs.ts2 +++ b/Resources/Private/TypoScript/Prototypes/Tabs.ts2 @@ -1,33 +1,31 @@ # Basic implementation of a flexible Tabs element, # not exposed directly but inherited by all specific M12.Foundation:TabsX content elements -prototype(M12.Foundation:TabsAbstract) < prototype(M12.Foundation:Content) { +prototype(M12.Foundation:Tabs) < prototype(M12.Foundation:Content) { + templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Tabs.html' + sectionName = 'tabs' + node = ${node} @override.parentNode = ${node} - # Extract just 'tabsX' from nodeType name (e.g. m12-foundation-tabsX) - @override.tabsNodeCount = ${String.toLowerCase(String.substr(q(node).property('_nodeType.name'), 1+String.lastIndexOf(q(node).property('_nodeType.name'), ':')))} - - # Attributes for outer div - # Override default nodeType class to have one more generic class for all tabs (tabs1, tabs2, tabs3...) - attributes.class.nodeType = ${'m12-foundation-tabs ' + tabsNodeCount} - # Attributes around div.tabs-content extraAttributes.class.base = 'tabs-content' - extraAttributes.class.tabsCount = ${'tabs-content-' + tabsNodeCount} extraAttributes.class.vertical = ${q(node).property('vertical') ? 'vertical' : null} tabsNavContent = TYPO3.TypoScript:Collection { - collection = ${q(node).children('[instanceof M12.Foundation:TabContentItem]')} + collection = ${q(node).children('[instanceof M12.Foundation:TabItem]')} itemRenderer = M12.Foundation:TabNavItem itemRenderer.parentNode = ${parentNode} itemName = 'node' iterationName = 'iterator' } tabsContent = TYPO3.TypoScript:Collection { - collection = ${q(node).children('[instanceof M12.Foundation:TabContentItem]')} - itemRenderer = M12.Foundation:TabContentItem + collection = ${q(node).children('[instanceof M12.Foundation:TabItem]')} + itemRenderer = M12.Foundation:TabItem itemName = 'node' } + + @process.wrapRemover = M12.Utils:WrapRemover + @process.wrapRemover.wrapperClass = 'm12-foundation-tabs' } prototype(M12.Foundation:TabNavItem) < prototype(M12.Foundation:Content) { @@ -52,7 +50,7 @@ prototype(M12.Foundation:TabNavItem) < prototype(M12.Foundation:Content) { } # Abstract render definition for a grid column -prototype(M12.Foundation:TabContentItem) < prototype(M12.Foundation:Content) { +prototype(M12.Foundation:TabItem) < prototype(M12.Foundation:Content) { templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Tabs.html' sectionName = 'tabContentItem' node = ${node} @@ -65,38 +63,3 @@ prototype(M12.Foundation:TabContentItem) < prototype(M12.Foundation:Content) { nodePath = 'content' } } - -# -# Configure each TabsX object -# + remove default wrapper, if not modified -# -prototype(M12.Foundation:Tabs2) < prototype(M12.Foundation:TabsAbstract) { - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Tabs.html' - sectionName = 'tabs' - @process.wrapRemover = M12.Utils:WrapRemover - @process.wrapRemover.wrapperClass = 'm12-foundation-tabs tabs2' -} -prototype(M12.Foundation:Tabs3) < prototype(M12.Foundation:TabsAbstract) { - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Tabs.html' - sectionName = 'tabs' - @process.wrapRemover = M12.Utils:WrapRemover - @process.wrapRemover.wrapperClass = 'm12-foundation-tabs tabs3' -} -prototype(M12.Foundation:Tabs4) < prototype(M12.Foundation:TabsAbstract) { - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Tabs.html' - sectionName = 'tabs' - @process.wrapRemover = M12.Utils:WrapRemover - @process.wrapRemover.wrapperClass = 'm12-foundation-tabs tabs4' -} -prototype(M12.Foundation:Tabs5) < prototype(M12.Foundation:TabsAbstract) { - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Tabs.html' - sectionName = 'tabs' - @process.wrapRemover = M12.Utils:WrapRemover - @process.wrapRemover.wrapperClass = 'm12-foundation-tabs tabs5' -} -prototype(M12.Foundation:Tabs6) < prototype(M12.Foundation:TabsAbstract) { - templatePath = 'resource://M12.Foundation/Private/Templates/NodeTypes/Tabs.html' - sectionName = 'tabs' - @process.wrapRemover = M12.Utils:WrapRemover - @process.wrapRemover.wrapperClass = 'm12-foundation-tabs tabs6' -} From cd37bb9d52a131de3ef1619e429c0f2d16b4f6be Mon Sep 17 00:00:00 2001 From: ryzy Date: Tue, 16 Dec 2014 19:27:28 +0000 Subject: [PATCH 17/23] Button: options simplified --- Configuration/NodeTypes.Buttons.yaml | 140 +++++++----------- .../Private/TypoScript/Prototypes/Button.ts2 | 18 ++- 2 files changed, 66 insertions(+), 92 deletions(-) diff --git a/Configuration/NodeTypes.Buttons.yaml b/Configuration/NodeTypes.Buttons.yaml index 6fa9bb7..97253e6 100644 --- a/Configuration/NodeTypes.Buttons.yaml +++ b/Configuration/NodeTypes.Buttons.yaml @@ -55,83 +55,83 @@ button: FALSE formatlessPasteOption: TRUE autoparagraph: FALSE - renderAnchor: - type: boolean - ui: - label: 'Render as an anchor (link)' - reloadIfChanged: TRUE - inspector: - group: 'options' buttonType: type: string ui: - label: 'Button type' + label: '' reloadIfChanged: TRUE inspector: group: 'options' editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: - placeholder: 'Default' + placeholder: 'Button type' allowEmpty: TRUE values: + button: + label: 'Type: Button' submit: - label: 'Submit' + label: 'Type: Submit' reset: - label: 'Reset' - button: - label: 'Button' - classSize: - type: string + label: 'Type: Reset' + renderAnchor: + type: boolean ui: - label: 'Button size' + label: 'Render as an anchor (link)' reloadIfChanged: TRUE inspector: group: 'options' - editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' - editorOptions: - placeholder: 'Default' - allowEmpty: TRUE - values: - tiny: - label: 'Tiny' - small: - label: 'Small' - large: - label: 'Large' - classAppearance: - type: string + classOptions: + type: array + defaultValue: [''] ui: - label: 'Button appearance' + label: '' reloadIfChanged: TRUE inspector: group: 'options' editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: - placeholder: 'Default' + placeholder: 'Button options' allowEmpty: TRUE values: - primary: - label: 'Primary' + tiny: + label: 'Size: Tiny' + group: 'Size' + small: + label: 'Size: Small' + group: 'Size' + large: + label: 'Size: Large' + group: 'Size' success: - label: 'Success' + label: 'Appearance: Success' + group: 'Appearance' + secondary: + label: 'Appearance: Secondary' + group: 'Appearance' alert: - label: 'Alert' - classShape: - type: string - ui: - label: 'Button shape' - reloadIfChanged: TRUE - inspector: - group: 'options' - editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' - editorOptions: - placeholder: 'Default' - allowEmpty: TRUE - values: + label: 'Appearance: Alert' + group: 'Appearance' + info: + label: 'Appearance: Info' + group: 'Appearance' + disabled: + label: 'Appearance: Disabled' + group: 'Appearance' radius: - label: 'Radius' + label: 'Shape: Radius' + group: 'Shape' round: - label: 'Round' + label: 'Shape: Round' + group: 'Shape' + dropdown: + label: 'Render as dropdown button' + group: 'Dropdown options' + split: + label: 'Render as split button' + group: 'Dropdown options' + expand: + label: 'Expanded button' + group: 'Misc' htmlHref: type: string ui: @@ -157,20 +157,6 @@ values: _blank: label: 'Yes' - classIsDisabled: - type: boolean - ui: - label: 'Disabled state' - reloadIfChanged: TRUE - inspector: - group: 'options' - classIsExpanded: - type: boolean - ui: - label: 'Expanded button' - reloadIfChanged: TRUE - inspector: - group: 'options' # Reveal Modal related properties. htmlDataRevealId: type: string @@ -195,6 +181,13 @@ editor: 'TYPO3.Neos/Inspector/Editors/TextFieldEditor' editorOptions: placeholder: 'e.g. myDropdown' + dropdownHoverable: + type: boolean + ui: + label: 'Dropdown hoverable' + reloadIfChanged: TRUE + inspector: + group: 'extraOptions' dropdownDirection: type: string ui: @@ -215,27 +208,6 @@ label: 'Bottom' 'left': label: 'Left' - dropdownHoverable: - type: boolean - ui: - label: 'Dropdown hoverable' - reloadIfChanged: TRUE - inspector: - group: 'extraOptions' - isButtonSplit: - type: boolean - ui: - label: 'Render as split button' - reloadIfChanged: TRUE - inspector: - group: 'extraOptions' - isButtonDropdown: - type: boolean - ui: - label: 'Render as dropdown button' - reloadIfChanged: TRUE - inspector: - group: 'extraOptions' # Button Group (list of buttons) diff --git a/Resources/Private/TypoScript/Prototypes/Button.ts2 b/Resources/Private/TypoScript/Prototypes/Button.ts2 index 9eae470..4c6a9e8 100644 --- a/Resources/Private/TypoScript/Prototypes/Button.ts2 +++ b/Resources/Private/TypoScript/Prototypes/Button.ts2 @@ -3,14 +3,8 @@ prototype(M12.Foundation:Button) < prototype(M12.Foundation:Content) { @override.htmlHref = ${q(node).property('htmlHref') ? String.trim(q(node).property('htmlHref')) : null} @override.isButtonSplit = ${q(node).property('isButtonSplit')} - attributes.class.base = ${renderAnchor ? null : 'button'} - attributes.class.size = ${q(node).property('classSize') ? q(node).property('classSize') : null} - attributes.class.appearance = ${q(node).property('classAppearance') ? q(node).property('classAppearance') : null} - attributes.class.shape = ${q(node).property('classShape') ? q(node).property('classShape') : null} - attributes.class.disable = ${q(node).property('classIsDisabled') ? 'disabled' : null} - attributes.class.expand = ${q(node).property('classIsExpanded') ? 'expand' : null} - attributes.class.split = ${q(node).property('isButtonSplit') ? 'split' : null} - attributes.class.dropdown = ${q(node).property('isButtonDropdown') ? 'dropdown' : null} + attributes.class.base = ${renderAnchor ? 'button' : null} + attributes.class.buttonOptions = ${q(node).property('classOptions') ? String.trim(Array.join(q(node).property('classOptions'), ' ')) : null} attributes.href = ${htmlHref} attributes.type = ${q(node).property('buttonType') ? q(node).property('buttonType') : null} @@ -22,6 +16,14 @@ prototype(M12.Foundation:Button) < prototype(M12.Foundation:Content) { attributes.data-options = TYPO3.TypoScript:RawArray { dropdownDirection = ${q(node).property('dropdownDirection') ? 'align: ' + q(node).property('dropdownDirection') + ';' : null} dropdownHoverable = ${q(node).property('dropdownHoverable') ? 'is_hover: true;' : null} + @process.stringify { + expression = ${String.trim(String.pregReplace(Array.join(value,' '),'/\s+/',' '))} + @position = '1' + } + @process.nullify { + expression = ${value ? value : null} + @position = 'end' + } } tag = ${renderAnchor or htmlHref ? 'a' : 'button'} From 0123f6e7e43b19ee307540718e72c97d28d79bed Mon Sep 17 00:00:00 2001 From: ryzy Date: Tue, 16 Dec 2014 20:26:49 +0000 Subject: [PATCH 18/23] Dropdowns: cosmetic improvements --- Configuration/NodeTypes.Abstracts.yaml | 2 +- Configuration/NodeTypes.Content.yaml | 85 ++++++++++++++------------ 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/Configuration/NodeTypes.Abstracts.yaml b/Configuration/NodeTypes.Abstracts.yaml index 15c81f8..6c97bdb 100644 --- a/Configuration/NodeTypes.Abstracts.yaml +++ b/Configuration/NodeTypes.Abstracts.yaml @@ -77,7 +77,7 @@ groups: devView: position: 10 - tab: view + tab: dev label: 'Custom look' properties: customLook: diff --git a/Configuration/NodeTypes.Content.yaml b/Configuration/NodeTypes.Content.yaml index fd4f135..3486d87 100644 --- a/Configuration/NodeTypes.Content.yaml +++ b/Configuration/NodeTypes.Content.yaml @@ -6,30 +6,32 @@ # Dropdown abstract 'M12.Foundation:DropdownAbstract': + label: "${'Dropdown: ' + q(node).property('customHtmlId')}" abstract: TRUE superTypes: - 'M12.Foundation:AbstractDevBase' ui: inspector: groups: - dev: + dropdownOptions: label: 'Dropdown options' position: 9 + constraints: + nodeTypes: + '*': FALSE # No children items allowed properties: dropdownSize: type: string - defaultValue: '' ui: - label: 'Size' + label: 'Dropdown content size' reloadIfChanged: TRUE inspector: - group: 'dev' + group: 'dropdownOptions' editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor' editorOptions: placeholder: 'Default / Tiny' + allowEmpty: TRUE values: - '': - label: '' tiny: label: 'Tiny' small: @@ -38,16 +40,11 @@ label: 'Medium' large: label: 'Large' - # Override inherited properties from M12.Foundation:AbstractDevBase customHtmlId: ui: - label: 'Element custom ID' - customCssClass: - ui: - label: 'Element extra CSS class(es)' - customCssCode: - ui: - label: 'Element inline CSS' + label: 'Dropdown element ID' + inspector: + group: 'dropdownOptions' # Dropdown that can handle list of links only. @@ -56,36 +53,44 @@ - 'TYPO3.Neos:Content' - 'M12.Foundation:DropdownAbstract' ui: - label: 'Dropdown' - icon: 'icon-minus' + label: 'Dropdown: Links' + icon: 'icon-sort-down' group: 'foundationContent' properties: text: type: string - defaultValue: '' + defaultValue: | + ui: inlineEditable: TRUE aloha: - 'format': - 'b': TRUE - 'i': TRUE - 'u': TRUE - 'sub': FALSE - 'sup': FALSE - 'p': FALSE - 'h1': FALSE - 'h2': FALSE - 'h3': FALSE - 'pre': FALSE - 'removeFormat': TRUE - 'table': - 'table': FALSE - 'list': - 'ol': FALSE - 'ul': TRUE - 'link': - 'a': TRUE - + format: + strong: TRUE + em: TRUE + u: TRUE + sub: TRUE + sup: TRUE + p: FALSE + h1: FALSE + h2: FALSE + h3: FALSE + h4: FALSE + h5: FALSE + link: + a: TRUE + alignment: + left: FALSE + center: FALSE + right: FALSE + justify: FALSE + formatlesspaste: + button: FALSE + formatlessPasteOption: TRUE + autoparagraph: FALSE # Dropdown that can handle custom content. 'M12.Foundation:DropdownContent': @@ -93,8 +98,8 @@ - 'TYPO3.Neos:Content' - 'M12.Foundation:DropdownAbstract' ui: - label: 'Dropdown Content' - icon: 'icon-minus' + label: 'Dropdown: Content' + icon: 'icon-collapse' group: 'foundationContent' inlineEditable: TRUE childNodes: @@ -108,7 +113,7 @@ label: 'Add padding to dropdown container' reloadIfChanged: TRUE inspector: - group: 'dev' + group: 'dropdownOptions' From c3b96422d3e256a63d2126eb4330512c52a1e8b9 Mon Sep 17 00:00:00 2001 From: ryzy Date: Tue, 16 Dec 2014 20:27:38 +0000 Subject: [PATCH 19/23] Accordion: node constraints, template update, cosmetic improvements --- Configuration/NodeTypes.Content.yaml | 29 ++++++++++++++----- Configuration/NodeTypes.Neos.Content.yaml | 1 + .../Templates/NodeTypes/Accordion.html | 10 +++---- .../TypoScript/Prototypes/Accordion.ts2 | 8 +++-- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Configuration/NodeTypes.Content.yaml b/Configuration/NodeTypes.Content.yaml index 3486d87..a359cb1 100644 --- a/Configuration/NodeTypes.Content.yaml +++ b/Configuration/NodeTypes.Content.yaml @@ -130,9 +130,6 @@ accordionSettings: label: 'Accordion settings' position: 9 - childNodes: - content: - type: 'TYPO3.Neos:ContentCollection' 'M12.Foundation:Accordion': superTypes: @@ -140,8 +137,16 @@ - 'M12.Foundation:AccordionAbstract' ui: label: 'Accordion' - icon: 'icon-minus' + icon: 'icon-reorder' group: 'foundationContent' + inlineEditable: TRUE + constraints: + nodeTypes: + 'M12.Foundation:AccordionItem': TRUE + '*': FALSE # No children items allowed + childNodes: + content: + type: 'M12.Foundation:AccordionItem' properties: accordionGroupName: type: string @@ -150,6 +155,8 @@ reloadIfChanged: TRUE inspector: group: 'accordionSettings' + editorOptions: + placeholder: '...for distributed accordion groups only' validation: regularExpression: regularExpression: '/^[a-z0-9\-]+$/i' @@ -161,14 +168,21 @@ - 'M12.Foundation:AccordionAbstract' ui: label: 'Accordion Item' - icon: 'icon-minus' + icon: 'icon-reorder' group: 'foundationContent' + constraints: + nodeTypes: + '*': FALSE # No children items allowed apart of child ContentCollection + childNodes: + content: + type: 'TYPO3.Neos:ContentCollection' properties: accordionItemLabel: type: string defaultValue: 'Accordion item label' ui: - inlineEditable: TRUE + inspector: + group: 'accordionSettings' aloha: format: strong: TRUE @@ -205,6 +219,7 @@ regularExpression: '/^[a-z0-9\-]+$/i' isAccordionItemActive: type: boolean + defaultValue: TRUE ui: label: 'Make this accordion item active' reloadIfChanged: TRUE @@ -294,7 +309,7 @@ - 'M12.Foundation:AbstractFontIcon' ui: label: 'Font Awesome icon' - icon: 'icon-minus' + icon: 'icon-flag' group: 'foundationContent' inspector: groups: diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index 3195a7b..a13bbd3 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -74,4 +74,5 @@ nodeTypes: 'M12.Foundation:Column': FALSE # M12.Foundation:Column makes sense only inside M12.Foundation:GridRow* 'M12.Foundation:TabItem': FALSE # M12.Foundation:TabItem makes sense only inside M12.Foundation:Tabs* + 'M12.Foundation:AccordionItem': FALSE # M12.Foundation:AccordionItem makes sense only inside M12.Foundation:Accordion '*': TRUE diff --git a/Resources/Private/Templates/NodeTypes/Accordion.html b/Resources/Private/Templates/NodeTypes/Accordion.html index 29dc3cc..f5be70c 100644 --- a/Resources/Private/Templates/NodeTypes/Accordion.html +++ b/Resources/Private/Templates/NodeTypes/Accordion.html @@ -1,15 +1,15 @@ {namespace ts=TYPO3\TypoScript\ViewHelpers} {namespace neos=TYPO3\Neos\ViewHelpers} - f:format.raw()}> - - + f:format.raw()}> + + - f:format.raw()}> + f:format.raw()}> {neos:contentElement.editable(property: 'accordionItemLabel')} f:format.raw()}> - + diff --git a/Resources/Private/TypoScript/Prototypes/Accordion.ts2 b/Resources/Private/TypoScript/Prototypes/Accordion.ts2 index 927cd15..a6b9608 100644 --- a/Resources/Private/TypoScript/Prototypes/Accordion.ts2 +++ b/Resources/Private/TypoScript/Prototypes/Accordion.ts2 @@ -4,8 +4,10 @@ prototype(M12.Foundation:Accordion) < prototype(M12.Foundation:Content) { attributes.class.accordion = 'accordion' attributes.data-accordion = ${q(node).property('accordionGroupName') ? q(node).property('accordionGroupName') : ''} - accordionContent = TYPO3.Neos:ContentCollection { - nodePath = 'content' + accordionItems = TYPO3.TypoScript:Collection { + collection = ${q(node).children('[instanceof M12.Foundation:AccordionItem]')} + itemRenderer = M12.Foundation:AccordionItem + itemName = 'node' } } @@ -17,6 +19,8 @@ prototype(M12.Foundation:AccordionItem) < prototype(M12.Foundation:Content) { @override.accordionItemId = ${q(node).property('accordionItemId') ? q(node).property('accordionItemId') : ( 'acc-' + q(node).property('_nodeData.identifier') )} accordionItemLabelHref = ${'#' + accordionItemId} + attributes.class.base = 'accordion-navigation' + # These attributes are added to DIV content container. extraAttributes { class.base = 'content' From c1be766021be298bef2cac1c2d4cc7e6180f6f80 Mon Sep 17 00:00:00 2001 From: ryzy Date: Tue, 16 Dec 2014 20:36:49 +0000 Subject: [PATCH 20/23] Neos node types: cosmetics --- Configuration/NodeTypes.Neos.Content.yaml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Configuration/NodeTypes.Neos.Content.yaml b/Configuration/NodeTypes.Neos.Content.yaml index a13bbd3..81ed492 100644 --- a/Configuration/NodeTypes.Neos.Content.yaml +++ b/Configuration/NodeTypes.Neos.Content.yaml @@ -18,14 +18,6 @@ # Start level: default 1st level of the site startLevel: defaultValue: 1 - # Property 'startingPoint' exists in MenuImplementation and works OK when set, but it's never exposed. - # Caveat: it only works as intended when startLevel = 0 (Same level as current page) - startingPoint: - type: reference - ui: - label: 'Starting point' - inspector: - group: 'options' 'TYPO3.Neos.NodeTypes:TwoColumn': @@ -66,6 +58,7 @@ 'TYPO3.Neos.NodeTypes:Html': superTypes: + abstractNavSailingType: 'M12.Foundation:AbstractNavSailingType' abstractDevCustomTag: 'M12.Foundation:AbstractDevCustomTag' From 51e43abd6e39d68edfb52d0872542fe65948f468 Mon Sep 17 00:00:00 2001 From: ryzy Date: Tue, 16 Dec 2014 22:42:23 +0000 Subject: [PATCH 21/23] Forms: cosmetics + Button: extra prefix/postfix classes to use within forms --- Configuration/NodeTypes.Buttons.yaml | 7 + Configuration/NodeTypes.Forms.yaml | 125 ++++++++++++------ .../Private/Templates/NodeTypes/Form.html | 14 +- .../Private/TypoScript/Prototypes/Form.ts2 | 58 ++++---- 4 files changed, 119 insertions(+), 85 deletions(-) diff --git a/Configuration/NodeTypes.Buttons.yaml b/Configuration/NodeTypes.Buttons.yaml index 97253e6..3b1c53e 100644 --- a/Configuration/NodeTypes.Buttons.yaml +++ b/Configuration/NodeTypes.Buttons.yaml @@ -123,6 +123,13 @@ round: label: 'Shape: Round' group: 'Shape' + # Form options: prefix/postfix when used together with form fields + prefix: + label: 'Form: Prefix button' + group: 'Form options' + postfix: + label: 'Form: Postfix button' + group: 'Form options' dropdown: label: 'Render as dropdown button' group: 'Dropdown options' diff --git a/Configuration/NodeTypes.Forms.yaml b/Configuration/NodeTypes.Forms.yaml index e7d528b..8fddc1e 100644 --- a/Configuration/NodeTypes.Forms.yaml +++ b/Configuration/NodeTypes.Forms.yaml @@ -19,6 +19,9 @@ formSettings: label: 'Form settings' position: 5 + constraints: + nodeTypes: + '*': FALSE # All content must go into child ContentCollection childNodes: content: type: 'TYPO3.Neos:ContentCollection' @@ -32,6 +35,7 @@ group: 'formSettings' methodType: type: string + defaultValue: 'get' ui: label: 'Submit method' reloadIfChanged: TRUE @@ -60,21 +64,24 @@ dev: label: 'Advanced form element settings' position: 9 + constraints: + nodeTypes: + '*': FALSE # All content must go into child ContentCollection properties: inputName: type: string - defaultValue: 'input-name' ui: - label: 'Name attribute' + label: 'Element name attribute' reloadIfChanged: TRUE inspector: - group: 'formInputSettings' + group: 'dev' position: 10 + editorOptions: + placeholder: 'None' inputValue: type: string - defaultValue: '' ui: - label: 'Value attribute' + label: 'Field value' reloadIfChanged: TRUE inspector: group: 'formInputSettings' @@ -118,19 +125,6 @@ inspector: group: 'formInputSettings' position: 80 - # Override inherited properties from M12.Foundation:AbstractDevBase - customHtmlId: - ui: - label: 'Element custom ID' - customCssClass: - ui: - label: 'Element extra CSS class(es)' - customCssCode: - ui: - label: 'Element inline CSS' - customLook: - ui: - label: 'Element predefined style / look' # Abstract for all form elements that need