From cb653089d13104a7b1026143c6e45132bdcf6069 Mon Sep 17 00:00:00 2001 From: Ralf Zimmermann <ralf.zimmermann@tritum.de> Date: Tue, 12 Sep 2017 14:49:40 +0200 Subject: [PATCH] [BUGFIX] EXT:form - show message if a form could not be saved Notify the user if the form could not be saved. Also remove the timeout of the error messages to ensure editors have enough time to read and understand the message. Resolves: #82255 Resolves: #82381 Releases: master, 8.7 Change-Id: I1377b7a85347107e7d03079b5a31179873a81e60 Reviewed-on: https://review.typo3.org/54126 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Daniel Lorenz <daniel.lorenz@extco.de> Tested-by: Daniel Lorenz <daniel.lorenz@extco.de> Reviewed-by: Bjoern Jacob <bjoern.jacob@tritum.de> Tested-by: Bjoern Jacob <bjoern.jacob@tritum.de> Reviewed-by: Susanne Moog <susanne.moog@typo3.org> Tested-by: Susanne Moog <susanne.moog@typo3.org> --- .../Controller/FormEditorController.php | 37 +++++++- .../Controller/FormManagerController.php | 95 +++++++++++++++---- .../Exception/FileWriteException.php | 24 +++++ .../Classes/Mvc/Configuration/YamlSource.php | 26 ++++- .../Persistence/FormPersistenceManager.php | 19 +++- .../Configuration/Yaml/FormEditorSetup.yaml | 2 + .../Config/configuration/Index.rst | 2 + .../formElements/formElementTypes/Form.rst | 6 ++ .../formElementTypes/Form/formEditor.rst | 2 + .../saveErrorFlashMessageMessage.rst | 29 ++++++ .../formEditor/saveErrorFlashMessageTitle.rst | 29 ++++++ .../Resources/Private/Language/Database.xlf | 7 ++ .../locallang_formManager_javascript.xlf | 14 ++- .../JavaScript/Backend/FormEditor/Core.js | 8 +- .../JavaScript/Backend/FormEditor/Mediator.js | 13 +++ .../Backend/FormEditor/ViewModel.js | 21 +++- .../Backend/FormManager/ViewModel.js | 34 ++++++- 17 files changed, 331 insertions(+), 37 deletions(-) create mode 100644 typo3/sysext/form/Classes/Mvc/Configuration/Exception/FileWriteException.php create mode 100644 typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageMessage.rst create mode 100644 typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageTitle.rst diff --git a/typo3/sysext/form/Classes/Controller/FormEditorController.php b/typo3/sysext/form/Classes/Controller/FormEditorController.php index b0eae72e6030..1c54bed90e6f 100644 --- a/typo3/sysext/form/Classes/Controller/FormEditorController.php +++ b/typo3/sysext/form/Classes/Controller/FormEditorController.php @@ -22,6 +22,7 @@ use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\View\JsonView; use TYPO3\CMS\Fluid\View\TemplateView; use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService; use TYPO3\CMS\Form\Domain\Exception\RenderingException; @@ -129,15 +130,25 @@ class FormEditorController extends AbstractBackendController $this->view->assign('addInlineSettings', $addInlineSettings); } + /** + * Initialize the save action. + * This action uses the Fluid JsonView::class as view. + * + * @internal + */ + public function initializeSaveFormAction() + { + $this->defaultViewObjectName = JsonView::class; + } + /** * Save a formDefinition which was build by the form editor. * * @param string $formPersistenceIdentifier * @param array $formDefinition - * @return string * @internal */ - public function saveFormAction(string $formPersistenceIdentifier, array $formDefinition): string + public function saveFormAction(string $formPersistenceIdentifier, array $formDefinition) { $formDefinition = ArrayUtility::stripTagsFromValuesRecursive($formDefinition); $formDefinition = $this->convertJsonArrayToAssociativeArray($formDefinition); @@ -152,8 +163,26 @@ class FormEditorController extends AbstractBackendController } } - $this->formPersistenceManager->save($formPersistenceIdentifier, $formDefinition); - return ''; + $response = [ + 'status' => 'success', + ]; + + try { + $this->formPersistenceManager->save($formPersistenceIdentifier, $formDefinition); + } catch (PersistenceManagerException $e) { + $response = [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ]; + } + + $this->view->assign('response', $response); + // saveFormAction uses the extbase JsonView::class. + // That's why we have to set the view variables in this way. + $this->view->setVariablesToRender([ + 'response', + ]); } /** diff --git a/typo3/sysext/form/Classes/Controller/FormManagerController.php b/typo3/sysext/form/Classes/Controller/FormManagerController.php index 609cb34d3de4..71f5639b647d 100644 --- a/typo3/sysext/form/Classes/Controller/FormManagerController.php +++ b/typo3/sysext/form/Classes/Controller/FormManagerController.php @@ -30,6 +30,7 @@ use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\View\JsonView; use TYPO3\CMS\Form\Exception as FormException; +use TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException; use TYPO3\CMS\Form\Service\TranslationService; /** @@ -47,17 +48,6 @@ class FormManagerController extends AbstractBackendController */ protected $defaultViewObjectName = BackendTemplateView::class; - /** - * Initialize the references action. - * This action use the Fluid JsonView::class as view. - * - * @internal - */ - public function initializeReferencesAction() - { - $this->defaultViewObjectName = JsonView::class; - } - /** * Displays the Form Manager * @@ -78,6 +68,17 @@ class FormManagerController extends AbstractBackendController } } + /** + * Initialize the create action. + * This action uses the Fluid JsonView::class as view. + * + * @internal + */ + public function initializeCreateAction() + { + $this->defaultViewObjectName = JsonView::class; + } + /** * Creates a new Form and redirects to the Form Editor * @@ -85,11 +86,10 @@ class FormManagerController extends AbstractBackendController * @param string $templatePath * @param string $prototypeName * @param string $savePath - * @return string * @throws FormException * @internal */ - public function createAction(string $formName, string $templatePath, string $prototypeName, string $savePath): string + public function createAction(string $formName, string $templatePath, string $prototypeName, string $savePath) { if (!$this->isValidTemplatePath($prototypeName, $templatePath)) { throw new FormException(sprintf('The template path "%s" is not allowed', $templatePath), 1329233410); @@ -116,9 +116,38 @@ class FormManagerController extends AbstractBackendController } } - $this->formPersistenceManager->save($formPersistenceIdentifier, $form); + $response = [ + 'status' => 'success', + 'url' => $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor') + ]; + + try { + $this->formPersistenceManager->save($formPersistenceIdentifier, $form); + } catch (PersistenceManagerException $e) { + $response = [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ]; + } + + $this->view->assign('response', $response); + // createAction uses the Extbase JsonView::class. + // That's why we have to set the view variables in this way. + $this->view->setVariablesToRender([ + 'response', + ]); + } - return $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor'); + /** + * Initialize the duplicate action. + * This action uses the Fluid JsonView::class as view. + * + * @internal + */ + public function initializeDuplicateAction() + { + $this->defaultViewObjectName = JsonView::class; } /** @@ -127,10 +156,9 @@ class FormManagerController extends AbstractBackendController * @param string $formName * @param string $formPersistenceIdentifier persistence identifier of the form to duplicate * @param string $savePath - * @return string * @internal */ - public function duplicateAction(string $formName, string $formPersistenceIdentifier, string $savePath): string + public function duplicateAction(string $formName, string $formPersistenceIdentifier, string $savePath) { $formToDuplicate = $this->formPersistenceManager->load($formPersistenceIdentifier); $formToDuplicate['label'] = $formName; @@ -148,9 +176,38 @@ class FormManagerController extends AbstractBackendController } } - $this->formPersistenceManager->save($formPersistenceIdentifier, $formToDuplicate); + $response = [ + 'status' => 'success', + 'url' => $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor') + ]; + + try { + $this->formPersistenceManager->save($formPersistenceIdentifier, $formToDuplicate); + } catch (PersistenceManagerException $e) { + $response = [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ]; + } + + $this->view->assign('response', $response); + // createAction uses the Extbase JsonView::class. + // That's why we have to set the view variables in this way. + $this->view->setVariablesToRender([ + 'response', + ]); + } - return $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor'); + /** + * Initialize the references action. + * This action uses the Fluid JsonView::class as view. + * + * @internal + */ + public function initializeReferencesAction() + { + $this->defaultViewObjectName = JsonView::class; } /** diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/Exception/FileWriteException.php b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/FileWriteException.php new file mode 100644 index 000000000000..60b33f4c83ea --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/FileWriteException.php @@ -0,0 +1,24 @@ +<?php +namespace TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/** + * Exception for file write errors + */ +class FileWriteException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php b/typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php index a82c83dcf2e8..abce0d4c9a10 100644 --- a/typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php +++ b/typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php @@ -19,9 +19,11 @@ namespace TYPO3\CMS\Form\Mvc\Configuration; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Yaml; +use TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\FileWriteException; use TYPO3\CMS\Form\Mvc\Configuration\Exception\NoSuchFileException; use TYPO3\CMS\Form\Mvc\Configuration\Exception\ParseErrorException; @@ -122,17 +124,35 @@ class YamlSource * * @param File|string $fileToSave The file to write to. * @param array $configuration The configuration to save + * @throws FileWriteException if the file could not be written * @internal */ public function save($fileToSave, array $configuration) { - $header = $this->getHeaderFromFile($fileToSave); + try { + $header = $this->getHeaderFromFile($fileToSave); + } catch (InsufficientFileAccessPermissionsException $e) { + throw new FileWriteException($e->getMessage(), 1512584488, $e); + } + $yaml = Yaml::dump($configuration, 99, 2); + if ($fileToSave instanceof File) { - $fileToSave->setContents($header . LF . $yaml); + try { + $fileToSave->setContents($header . LF . $yaml); + } catch (InsufficientFileAccessPermissionsException $e) { + throw new FileWriteException($e->getMessage(), 1512582753, $e); + } } else { - @file_put_contents($fileToSave, $header . LF . $yaml); + $byteCount = @file_put_contents($fileToSave, $header . LF . $yaml); + + if ($byteCount === false) { + $error = error_get_last(); + throw new FileWriteException($error['message'], 1512582929); + } } + + return $return; } /** diff --git a/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php b/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php index fa5365eab8d0..a0b7c52ecde3 100644 --- a/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php +++ b/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php @@ -27,6 +27,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Form\Mvc\Configuration\ConfigurationManagerInterface; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\FileWriteException; use TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniqueIdentifierException; use TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniquePersistenceIdentifierException; use TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException; @@ -154,7 +155,15 @@ class FormPersistenceManager implements FormPersistenceManagerInterface $fileToSave = $this->getOrCreateFile($persistenceIdentifier); } - $this->yamlSource->save($fileToSave, $formDefinition); + try { + $this->yamlSource->save($fileToSave, $formDefinition); + } catch (FileWriteException $e) { + throw new PersistenceManagerException(sprintf( + 'The file "%s" could not be saved: %s', + $persistenceIdentifier, + $e->getMessage() + ), 1512582637, $e); + } } /** @@ -503,7 +512,13 @@ class FormPersistenceManager implements FormPersistenceManagerInterface if (!$storage->hasFolder($pathinfo['dirname'])) { throw new PersistenceManagerException(sprintf('Could not create folder "%s".', $pathinfo['dirname']), 1471630579); } - $folder = $storage->getFolder($pathinfo['dirname']); + + try { + $folder = $storage->getFolder($pathinfo['dirname']); + } catch (InsufficientFolderAccessPermissionsException $e) { + throw new PersistenceManagerException(sprintf('No read access to folder "%s".', $pathinfo['dirname']), 1512583307); + } + if (!$storage->checkFolderActionPermission('write', $folder)) { throw new PersistenceManagerException(sprintf('No write access to folder "%s".', $pathinfo['dirname']), 1471630580); } diff --git a/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml b/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml index b66c86a64013..61d1dd1b29e3 100644 --- a/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml +++ b/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml @@ -137,6 +137,8 @@ TYPO3: saveSuccessFlashMessageTitle: 'formEditor.elements.Form.saveSuccessFlashMessageTitle' saveSuccessFlashMessageMessage: 'formEditor.elements.Form.saveSuccessFlashMessageMessage' + saveErrorFlashMessageTitle: 'formEditor.elements.Form.saveErrorFlashMessageTitle' + saveErrorFlashMessageMessage: 'formEditor.elements.Form.saveErrorFlashMessageMessage' modalValidationErrorsDialogTitle: 'formEditor.modals.validationErrors.dialogTitle' modalValidationErrorsConfirmButton: 'formEditor.modals.validationErrors.confirmButton' diff --git a/typo3/sysext/form/Documentation/Config/configuration/Index.rst b/typo3/sysext/form/Documentation/Config/configuration/Index.rst index 6e816a09ebc0..56c6f8842b9c 100644 --- a/typo3/sysext/form/Documentation/Config/configuration/Index.rst +++ b/typo3/sysext/form/Documentation/Config/configuration/Index.rst @@ -61,6 +61,8 @@ Full default configuration _isTopLevelFormElement: true saveSuccessFlashMessageTitle: formEditor.elements.Form.saveSuccessFlashMessageTitle saveSuccessFlashMessageMessage: formEditor.elements.Form.saveSuccessFlashMessageMessage + saveErrorFlashMessageTitle: formEditor.elements.Form.saveErrorFlashMessageTitle + saveErrorFlashMessageMessage: formEditor.elements.Form.saveErrorFlashMessageMessage modalValidationErrorsDialogTitle: formEditor.modals.validationErrors.dialogTitle modalValidationErrorsConfirmButton: formEditor.modals.validationErrors.confirmButton modalInsertElementsDialogTitle: formEditor.modals.insertElements.dialogTitle diff --git a/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form.rst b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form.rst index 8b8443eec866..db8d454def10 100644 --- a/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form.rst +++ b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form.rst @@ -90,6 +90,12 @@ Properties .. _typo3.cms.form.prototypes.<prototypeIdentifier>.formelementsdefinition.form.formeditor.savesuccessflashmessagemessage: .. include:: Form/formEditor/saveSuccessFlashMessageMessage.rst +.. _typo3.cms.form.prototypes.<prototypeIdentifier>.formelementsdefinition.form.formeditor.saveerrorflashmessagetitle: +.. include:: Form/formEditor/saveErrorFlashMessageTitle.rst + +.. _typo3.cms.form.prototypes.<prototypeIdentifier>.formelementsdefinition.form.formeditor.saveerrorflashmessagemessage: +.. include:: Form/formEditor/saveErrorFlashMessageMessage.rst + .. _typo3.cms.form.prototypes.<prototypeIdentifier>.formelementsdefinition.form.formeditor.modalvalidationerrorsdialogtitle: .. include:: Form/formEditor/modalValidationErrorsDialogTitle.rst diff --git a/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor.rst b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor.rst index a0573114c884..4d72513368d4 100644 --- a/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor.rst +++ b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor.rst @@ -61,6 +61,8 @@ formEditor _isTopLevelFormElement: true saveSuccessFlashMessageTitle: formEditor.elements.Form.saveSuccessFlashMessageTitle saveSuccessFlashMessageMessage: formEditor.elements.Form.saveSuccessFlashMessageMessage + saveErrorFlashMessageTitle: formEditor.elements.Form.saveErrorFlashMessageTitle + saveErrorFlashMessageMessage: formEditor.elements.Form.saveErrorFlashMessageMessage modalValidationErrorsDialogTitle: formEditor.modals.validationErrors.dialogTitle modalValidationErrorsConfirmButton: formEditor.modals.validationErrors.confirmButton modalInsertElementsDialogTitle: formEditor.modals.insertElements.dialogTitle diff --git a/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageMessage.rst b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageMessage.rst new file mode 100644 index 000000000000..4779f1053259 --- /dev/null +++ b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageMessage.rst @@ -0,0 +1,29 @@ +formEditor.saveErrorFlashMessageMessage +--------------------------------------- + +:aspect:`Option path` + TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.formElementsDefinition.Form.formEditor.saveErrorFlashMessageMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + saveErrorFlashMessageMessage: formEditor.elements.Form.saveErrorFlashMessageMessage + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"<concepts-formeditor-translation-formeditor>` + +:aspect:`Description` + Internal setting. diff --git a/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageTitle.rst b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageTitle.rst new file mode 100644 index 000000000000..d14ae4980f68 --- /dev/null +++ b/typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageTitle.rst @@ -0,0 +1,29 @@ +formEditor.saveErrorFlashMessageTitle +------------------------------------- + +:aspect:`Option path` + TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.formElementsDefinition.Form.formEditor.saveErrorFlashMessageTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + saveErrorFlashMessageTitle: formEditor.elements.Form.saveErrorFlashMessageTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"<concepts-formeditor-translation-formeditor>` + +:aspect:`Description` + Internal setting. diff --git a/typo3/sysext/form/Resources/Private/Language/Database.xlf b/typo3/sysext/form/Resources/Private/Language/Database.xlf index 92877d9f1626..11d758839631 100644 --- a/typo3/sysext/form/Resources/Private/Language/Database.xlf +++ b/typo3/sysext/form/Resources/Private/Language/Database.xlf @@ -274,6 +274,13 @@ <source>The form has been successfully saved.</source> </trans-unit> + <trans-unit id="formEditor.elements.Form.saveErrorFlashMessageTitle" xml:space="preserve"> + <source>Save</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.saveErrorFlashMessageMessage" xml:space="preserve"> + <source>The form could not be saved:</source> + </trans-unit> + <trans-unit id="formEditor.modals.validationErrors.dialogTitle" xml:space="preserve"> <source>Alert</source> </trans-unit> diff --git a/typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf b/typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf index c2dfda26d1f1..3e269d5fd249 100644 --- a/typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf +++ b/typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf @@ -48,9 +48,21 @@ <trans-unit id="formManager.newFormWizard.step3.message" xml:space="preserve"> <source>Now you are ready to create your new form.</source> </trans-unit> + <trans-unit id="formManager.newFormWizard.step4.errorTitle" xml:space="preserve"> + <source>Create</source> + </trans-unit> + <trans-unit id="formManager.newFormWizard.step4.errorMessage" xml:space="preserve"> + <source>The form could not be saved:</source> + </trans-unit> <trans-unit id="formManager.duplicateFormWizard.step1.title" xml:space="preserve"> <source>Duplicate form "{0}"</source> </trans-unit> + <trans-unit id="formManager.duplicateFormWizard.step2.errorTitle" xml:space="preserve"> + <source>Duplicate</source> + </trans-unit> + <trans-unit id="formManager.duplicateFormWizard.step2.errorMessage" xml:space="preserve"> + <source>The form could not be saved:</source> + </trans-unit> <trans-unit id="formManager.no_references" xml:space="preserve"> <source>There are no references yet</source> </trans-unit> @@ -68,4 +80,4 @@ </trans-unit> </body> </file> -</xliff> \ No newline at end of file +</xliff> 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 a2ef8c85b51d..73f5165bab75 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js @@ -546,7 +546,7 @@ define(['jquery'], function($) { if ('array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'])) { continue; } - + if ( !utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode']) && formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'] === 'OR' @@ -1989,7 +1989,11 @@ define(['jquery'], function($) { return; } _runningAjaxRequests['saveForm'] = null; - publisherSubscriber().publish('core/ajax/saveFormDefinition/success', [data]); + if (data['status'] === 'success') { + publisherSubscriber().publish('core/ajax/saveFormDefinition/success', [data]); + } else { + publisherSubscriber().publish('core/ajax/saveFormDefinition/error', [data]); + } }).fail(function(jqXHR, textStatus, errorThrown) { publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js index c9c6e6d27329..8a30e1068131 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js @@ -209,6 +209,19 @@ define(['jquery', getViewModel().showSaveSuccessMessage(); }); + /** + * @private + * + * @param string + * @param array + * args[0] = object + * @return void + * @subscribe core/ajax/saveFormDefinition/error + */ + getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/error', function(topic, args) { + getViewModel().showSaveErrorMessage(args[0]); + }); + /** * @private * 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 c162a21bfd3a..761b60626d13 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js @@ -518,7 +518,7 @@ define(['jquery', /** * @public * - * @param bool + * @param bool * @return void */ function setPreviewMode(previewMode) { @@ -747,7 +747,7 @@ define(['jquery', /** * @public * - * @param bool + * @param bool * @return void */ function showValidationErrorsModal() { @@ -1310,7 +1310,7 @@ define(['jquery', function removeAllStageElementSelectionsBatch() { getStage().getAllFormElementDomElements().removeClass(getHelper().getDomElementClassName('selectedFormElement')); removeStagePanelSelection(); - getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); }; /** @@ -1625,6 +1625,20 @@ define(['jquery', ); }; + /** + * @public + * + * @return void + */ + function showSaveErrorMessage(response) { + Notification.error( + getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageTitle'), + getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageMessage') + + " " + + response.message + ); + }; + /** * @public * @@ -1725,6 +1739,7 @@ define(['jquery', showSaveButtonSaveIcon: showSaveButtonSaveIcon, showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon, showSaveSuccessMessage: showSaveSuccessMessage, + showSaveErrorMessage: showSaveErrorMessage, showValidationErrorsModal: showValidationErrorsModal }; })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js index 1d2bc79fe246..b7f5225870fe 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js @@ -62,7 +62,11 @@ define(['jquery', showReferences: { identifier: '[data-identifier="showReferences"]' }, referenceLink: { identifier: '[data-identifier="referenceLink"]' }, - tooltip: { identifier: '[data-toggle="tooltip"]' } + tooltip: { identifier: '[data-toggle="tooltip"]' }, + + moduleBody: { class: '.module-body.t3js-module-body' }, + t3Logo: { class: '.t3-message-page-logo' }, + t3Footer: { id: '#t3-footer' } } }; @@ -270,11 +274,23 @@ define(['jquery', savePath: Wizard.setup.settings['savePath'] } }, function(data, textStatus, jqXHR) { - document.location = data; + if (data['status'] === 'success') { + document.location = data.url; + } else { + Notification.error(TYPO3.lang['formManager.newFormWizard.step4.errorTitle'], TYPO3.lang['formManager.newFormWizard.step4.errorMessage'] + " " + data['message']); + } Wizard.dismiss(); }).fail(function(jqXHR, textStatus, errorThrown) { + var parser = new DOMParser(), + responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"), + responseBody = $(responseDocument.body); + Notification.error(textStatus, errorThrown, 2); Wizard.dismiss(); + + $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove(); + $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove(); + $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html()); }); }).done(function() { Wizard.show(); @@ -403,11 +419,23 @@ define(['jquery', savePath: Wizard.setup.settings['savePath'] } }, function(data, textStatus, jqXHR) { - document.location = data; + if (data['status'] === 'success') { + document.location = data.url; + } else { + Notification.error(TYPO3.lang['formManager.duplicateFormWizard.step2.errorTitle'], TYPO3.lang['formManager.duplicateFormWizard.step2.errorMessage'] + " " + data['message']); + } Wizard.dismiss(); }).fail(function(jqXHR, textStatus, errorThrown) { + var parser = new DOMParser(), + responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"), + responseBody = $(responseDocument.body); + Notification.error(textStatus, errorThrown, 2); Wizard.dismiss(); + + $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove(); + $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove(); + $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html()); }); }).done(function() { Wizard.show(); -- GitLab