diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/GridRow.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/GridRow.php index 06f03b32fa52b9997fbd2bdde8ca8c42e65f7a99..5be61bd435c1731b1c9bcc49f250c967dc581eef 100644 --- a/typo3/sysext/form/Classes/Domain/Model/FormElements/GridRow.php +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/GridRow.php @@ -30,24 +30,6 @@ use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotValidException; class GridRow extends Section implements GridRowInterface { - /** - * Register this element at the parent form, if there is a connection to the parent form. - * - * @return void - * @throws TypeDefinitionNotValidException - * @internal - */ - public function registerInFormIfPossible() - { - if (!$this->getParentRenderable() instanceof GridContainerInterface) { - throw new TypeDefinitionNotValidException( - sprintf('Grid rows ("%s") only allowed within grid containers.', $this->getIdentifier()), - 1489413805 - ); - } - parent::registerInFormIfPossible(); - } - /** * Add a new form element at the end of the grid row * @@ -63,11 +45,6 @@ class GridRow extends Section implements GridRowInterface sprintf('Grid containers ("%s") within grid rows ("%s") are not allowed.', $formElement->getIdentifier(), $this->getIdentifier()), 1489413379 ); - } elseif ($formElement instanceof GridRowInterface) { - throw new TypeDefinitionNotValidException( - sprintf('Grid rows ("%s") within grid rows ("%s") are not allowed.', $formElement->getIdentifier(), $this->getIdentifier()), - 1489413696 - ); } $this->addRenderable($formElement); @@ -91,11 +68,6 @@ class GridRow extends Section implements GridRowInterface sprintf('Grid containers ("%s") within grid rows ("%s") are not allowed.', $element->getIdentifier(), $this->getIdentifier()), 1489413538 ); - } elseif ($element instanceof GridRowInterface) { - throw new TypeDefinitionNotValidException( - sprintf('Grid rows ("%s") within grid rows ("%s") are not allowed.', $element->getIdentifier(), $this->getIdentifier()), - 1489413697 - ); } return $element; diff --git a/typo3/sysext/form/Classes/ViewHelpers/GridColumnClassAutoConfigurationViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/GridColumnClassAutoConfigurationViewHelper.php index e70c5f3bcb1d4b8666b1f1dd95a866dd0f98bcac..93bf6e28afaea52098999ace7dcb34d9f19d8d7b 100644 --- a/typo3/sysext/form/Classes/ViewHelpers/GridColumnClassAutoConfigurationViewHelper.php +++ b/typo3/sysext/form/Classes/ViewHelpers/GridColumnClassAutoConfigurationViewHelper.php @@ -16,6 +16,7 @@ namespace TYPO3\CMS\Form\ViewHelpers; */ use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3\CMS\Form\Domain\Model\FormElements\GridContainerInterface; use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; @@ -63,23 +64,27 @@ class GridColumnClassAutoConfigurationViewHelper extends AbstractViewHelper $gridContainerElement = $gridRowElement->getParentRenderable(); $gridRowEChildElements = $gridRowElement->getElementsRecursively(); - $gridContainerViewPortConfiguration = $gridContainerElement->getProperties()['gridColumnClassAutoConfiguration']; - if (empty($gridContainerViewPortConfiguration)) { - return ''; + if ($gridContainerElement instanceof GridContainerInterface) { + $gridViewPortConfiguration = $gridContainerElement->getProperties()['gridColumnClassAutoConfiguration']; + } else { + $gridViewPortConfiguration = $gridRowElement->getProperties()['gridColumnClassAutoConfiguration']; } - $gridSize = (int)$gridContainerViewPortConfiguration['gridSize']; + if (empty($gridViewPortConfiguration)) { + return ''; + } + $gridSize = (int)$gridViewPortConfiguration['gridSize']; $columnsToCalculate = []; $usedColumns = []; foreach ($gridRowEChildElements as $childElement) { if (empty($childElement->getProperties()['gridColumnClassAutoConfiguration'])) { - foreach ($gridContainerViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { + foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { $columnsToCalculate[$viewPortName]['elements']++; } } else { $gridColumnViewPortConfiguration = $childElement->getProperties()['gridColumnClassAutoConfiguration']; - foreach ($gridContainerViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { + foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { $configuration = $gridColumnViewPortConfiguration['viewPorts'][$viewPortName]; if ( isset($configuration['numbersOfColumnsToUse']) @@ -100,7 +105,7 @@ class GridColumnClassAutoConfigurationViewHelper extends AbstractViewHelper } $classes = []; - foreach ($gridContainerViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { + foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { if (isset($usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'])) { $numbersOfColumnsToUse = $usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse']; } else { diff --git a/typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml b/typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml index a8b4fd30af2f7be7bae547f096bded5526f8c7b3..a0a500b2c30bac8226231f731962cdd1a5784ed9 100644 --- a/typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml +++ b/typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml @@ -77,6 +77,7 @@ TYPO3: _isGridContainerFormElement: true properties: elementClassAttribute: 'container' + # overrules 'GridRow.properties.gridColumnClassAutoConfiguration' gridColumnClassAutoConfiguration: gridSize: 12 viewPorts: @@ -95,6 +96,17 @@ TYPO3: implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\GridRow' properties: elementClassAttribute: 'row' + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-xs-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' renderingOptions: _isCompositeFormElement: true _isGridRowFormElement: true diff --git a/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml b/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml index 8716b328bd696019b3c280b9c97fa64fb45f5122..142d4204552131e4c1bb3daa4839215da55f1e1f 100644 --- a/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml +++ b/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml @@ -304,8 +304,6 @@ TYPO3: GridContainer: formEditor: label: 'formEditor.elements.GridContainer.label' - group: container - groupSorting: 200 _isCompositeFormElement: true _isGridContainerFormElement: true iconIdentifier: 't3-form-icon-gridcontainer' diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js index 14e42a55d5ca3e14d2e138526b54fae4afa790c0..9f620eb8fe67a59870ea2c171f6974bca2d15e12 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js @@ -812,6 +812,18 @@ define(['jquery', ); }; + /** + * @public + * + * @param object formElement + * @return object|null + */ + function findEnclosingGridRowFormElement(formElement) { + return _getRepository().findEnclosingGridRowFormElement( + _getRepository().findFormElement(formElement) + ); + }; + /** * @public * @@ -1071,6 +1083,7 @@ define(['jquery', getLastTopLevelElementOnCurrentPage: getLastTopLevelElementOnCurrentPage, findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement, + findEnclosingGridRowFormElement: findEnclosingGridRowFormElement, isRootFormElementSelected: isRootFormElementSelected, getLastFormElementWithinParentFormElement: getLastFormElementWithinParentFormElement, getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements, diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js index d1824db065658fce57abd2b375a198a89fe794eb..9be812ad9890752b1255d32c3cf69257e14ef407 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js @@ -1353,6 +1353,29 @@ define(['jquery'], function($) { return formElement; }; + /** + * @param object formElement + * @return object|null + * @throws 1490520271 + */ + function findEnclosingGridRowFormElement(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1490520271); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + while (!formElementTypeDefinition['_isGridRowFormElement']) { + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + formElement = formElement.get('__parentRenderable'); + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + } + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + return formElement; + }; + /** * @param object formElement * @return object|null @@ -1706,6 +1729,7 @@ define(['jquery'], function($) { findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, findEnclosingCompositeFormElementWhichIsOnTopLevel: findEnclosingCompositeFormElementWhichIsOnTopLevel, findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement, + findEnclosingGridRowFormElement: findEnclosingGridRowFormElement, getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement: getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement, getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements, diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js index ff2a1174374adfcff3a74ebb41eee5635b4d0e02..69f7478e43ad0988e41d464148cf0bdefb0db5b1 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js @@ -372,14 +372,10 @@ define(['jquery', if ( formElementTypeDefinition['_isGridContainerFormElement'] - && getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) - ) { - return false; - } - - if ( - formElementTypeDefinition['_isGridRowFormElement'] - && !targetFormElementTypeDefinition['_isGridContainerFormElement'] + && ( + getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) + || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath) + ) ) { return false; } @@ -701,10 +697,21 @@ define(['jquery', disableElementTypes = []; onlyEnableElementTypes = []; if (formElementTypeDefinition['_isGridRowFormElement']) { - onlyEnableElementTypes = ['GridRow']; - disableElementTypes = []; + if (getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())) { + onlyEnableElementTypes = ['GridRow']; + } else if (getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement().get('__parentRenderable'))) { + disableElementTypes = ['GridContainer']; + } } else { - disableElementTypes = ['GridRow']; + if ( + !formElementTypeDefinition['_isGridContainerFormElement'] + && ( + getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement()) + || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement()) + ) + ) { + disableElementTypes = ['GridContainer']; + } } getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [ @@ -719,14 +726,18 @@ define(['jquery', $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonInside'), template).on('click', function(e) { var disableElementTypes, onlyEnableElementTypes; - disableElementTypes = ['GridRow']; + disableElementTypes = []; onlyEnableElementTypes = []; if (formElementTypeDefinition['_isGridContainerFormElement']) { onlyEnableElementTypes = ['GridRow']; - disableElementTypes = []; - } else if (formElementTypeDefinition['_isGridRowFormElement']) { - onlyEnableElementTypes = []; - disableElementTypes = ['GridContainer', 'GridRow']; + } else if ( + formElementTypeDefinition['_isGridRowFormElement'] + || ( + getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement()) + || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement()) + ) + ) { + disableElementTypes = ['GridContainer']; } getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [ @@ -742,14 +753,11 @@ define(['jquery', getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButton'), template)); $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template).on('click', function(e) { - var disableElementTypes, onlyEnableElementTypes; + var disableElementTypes; disableElementTypes = []; - onlyEnableElementTypes = []; - if (getFormEditorApp().findEnclosingGridContainerFormElement(formElement)) { - disableElementTypes = ['GridContainer', 'GridRow']; - } else { - disableElementTypes = ['GridRow']; + if (getFormEditorApp().findEnclosingGridRowFormElement(formElement)) { + disableElementTypes = ['GridContainer']; } getPublisherSubscriber().publish( diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js index f9c0ac090af6218bc9e858b7e2fef236e451e452..03a45127fc9509c0417ed09d93d649b26381f73d 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js @@ -325,14 +325,10 @@ define(['jquery', if ( formElementTypeDefinition['_isGridContainerFormElement'] - && getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) - ) { - return false; - } - - if ( - formElementTypeDefinition['_isGridRowFormElement'] - && !targetFormElementTypeDefinition['_isGridContainerFormElement'] + && ( + getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) + || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath) + ) ) { return false; } diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js index fe699912bcd77a20ee824088a9230901b0a8118c..cc4813a00c6981aaf7c4e2db29331fe790ae75c4 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js @@ -404,10 +404,7 @@ define(['jquery', $(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')).on('click', function(e) { getPublisherSubscriber().publish( 'view/stage/abstract/button/newElement/clicked', [ - 'view/insertElements/perform/bottom', - { - disableElementTypes: ['GridRow'] - } + 'view/insertElements/perform/bottom' ] ); });