[BUGFIX] EXT:form - show message if a form could not be saved 26/54126/8
authorRalf Zimmermann <ralf.zimmermann@tritum.de>
Tue, 12 Sep 2017 12:49:40 +0000 (14:49 +0200)
committerSusanne Moog <susanne.moog@typo3.org>
Thu, 7 Dec 2017 07:34:51 +0000 (08:34 +0100)
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>
17 files changed:
typo3/sysext/form/Classes/Controller/FormEditorController.php
typo3/sysext/form/Classes/Controller/FormManagerController.php
typo3/sysext/form/Classes/Mvc/Configuration/Exception/FileWriteException.php [new file with mode: 0644]
typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php
typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php
typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml
typo3/sysext/form/Documentation/Config/configuration/Index.rst
typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form.rst
typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor.rst
typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageMessage.rst [new file with mode: 0644]
typo3/sysext/form/Documentation/Config/proto/formElements/formElementTypes/Form/formEditor/saveErrorFlashMessageTitle.rst [new file with mode: 0644]
typo3/sysext/form/Resources/Private/Language/Database.xlf
typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js

index b0eae72..1c54bed 100644 (file)
@@ -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;
@@ -130,14 +131,24 @@ class FormEditorController extends AbstractBackendController
     }
 
     /**
+     * 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',
+        ]);
     }
 
     /**
index 609cb34..71f5639 100644 (file)
@@ -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;
 
 /**
@@ -48,17 +49,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
      *
      * @internal
@@ -79,17 +69,27 @@ 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
      *
      * @param string $formName
      * @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 (file)
index 0000000..60b33f4
--- /dev/null
@@ -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
+{
+}
index a82c83d..abce0d4 100644 (file)
@@ -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;
     }
 
     /**
index fa5365e..a0b7c52 100644 (file)
@@ -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);
         }
index b66c86a..61d1dd1 100644 (file)
@@ -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'
index 6e816a0..56c6f88 100644 (file)
@@ -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
index 8b8443e..db8d454 100644 (file)
@@ -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
 
index a057311..4d72513 100644 (file)
@@ -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 (file)
index 0000000..4779f10
--- /dev/null
@@ -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 (file)
index 0000000..d14ae49
--- /dev/null
@@ -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.
index 92877d9..11d7588 100644 (file)
                 <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>
index c2dfda2..3e269d5 100644 (file)
             <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>
index a2ef8c8..73f5165 100644 (file)
@@ -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]);
                 });
index c9c6e6d..8a30e10 100644 (file)
@@ -214,6 +214,19 @@ define(['jquery',
              *
              * @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
+             *
+             * @param string
+             * @param array
              *              args[0] = html
              *              args[1] = pageIndex
              * @return void
index c162a21..761b606 100644 (file)
@@ -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'));
         };
 
         /**
@@ -1628,6 +1628,20 @@ define(['jquery',
         /**
          * @public
          *
+         * @return void
+         */
+        function showSaveErrorMessage(response) {
+            Notification.error(
+                getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageTitle'),
+                getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageMessage') +
+                  " " +
+                  response.message
+            );
+        };
+
+        /**
+         * @public
+         *
          * @param string
          * @param string
          * @return void
@@ -1725,6 +1739,7 @@ define(['jquery',
             showSaveButtonSaveIcon: showSaveButtonSaveIcon,
             showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon,
             showSaveSuccessMessage: showSaveSuccessMessage,
+            showSaveErrorMessage: showSaveErrorMessage,
             showValidationErrorsModal: showValidationErrorsModal
         };
     })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification);
index 1d2bc79..b7f5225 100644 (file)
@@ -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();