diff --git a/Documentation/Installation.rst b/Documentation/Installation.rst index b8cf472712374a8ca8d89331c91a4ed7ee7eec84..9b608db96dec23ca52281a9986dbb9e4c1c3c190 100644 --- a/Documentation/Installation.rst +++ b/Documentation/Installation.rst @@ -45,8 +45,8 @@ The following features are only tested / supported on linux hosts: * Concatenation of PDF files - command `pdfunite`. * Convert of images to PDF files - command `img2pdf`. * PDF decrypt (used for merge with pdfunite) - command `qpdf`. -* PDF decrypt (used for merge with pdfunite) - command `gs` - in case `qpdf` is not successful. -* PDF fix (used for merge with pdfunite) - command `pdf2ps` and `ps2pdf` - in case `qpdf` is not successful. +* PDF decrypt (used for merge with pdfunite) - command `gs` - if `qpdf` is not successful. +* PDF fix (used for merge with pdfunite) - command `pdf2ps` and `ps2pdf` - if `qpdf` is not successful. * Mime type detection for uploads - command `file`. * Split PDF into JPG - command `convert`. * Repair PDF - command `pdftocairo`. @@ -259,8 +259,11 @@ Setup CSS & JS file06 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap-datetimepicker.min.css file07 = typo3conf/ext/qfq/Resources/Public/Css/codemirror.css - # Only needed in case FullCalendar is used + # Only needed if FullCalendar is used file10 = typo3conf/ext/qfq/Resources/Public/Css/fullcalendar.min.css + + # Only needed if FormElement 'upload' filepond is used + file11 = typo3conf/ext/qfq/Resources/Public/Css/filepond.min.css } page.includeJS { @@ -279,15 +282,20 @@ Setup CSS & JS file13 = typo3conf/ext/qfq/Resources/Public/JavaScript/codemirror.min.js file14 = typo3conf/ext/qfq/Resources/Public/JavaScript/code-mirror-mode/sql/sql.min.js - # Only needed in case FormElement 'annotate' is used. + # Only needed if FormElement 'annotate' is used. file20 = typo3conf/ext/qfq/Resources/Public/JavaScript/fabric.min.js file21 = typo3conf/ext/qfq/Resources/Public/JavaScript/qfq.fabric.min.js - # Only needed in case FullCalendar is used. + # Only needed if FullCalendar is used. file22 = typo3conf/ext/qfq/Resources/Public/JavaScript/fullcalendar.min.js - # Only needed in case widget-output is used. + # Only needed if widget-output is used. file23 = typo3conf/ext/qfq/Resources/Public/JavaScript/widget-output.min.js + + # Only needed if FormElement 'upload' filepond is used. + file24 = typo3conf/ext/qfq/Resources/Public/JavaScript/filepond.min.js + file25 = typo3conf/ext/qfq/Resources/Public/JavaScript/filepond-plugin-file-validate-size.min.js + file25 = typo3conf/ext/qfq/Resources/Public/JavaScript/filepond-plugin-file-validate-type.min.js } @@ -889,8 +897,8 @@ Example: :: fillStoreSystemBySqlRow: SELECT gr.reference AS name, IF('{{pageLanguage:T}}'=0 OR gr.value2='', gr.value, gr.value2) AS value FROM Ggroup AS gr WHERE gr.storeSystem='yes' - -To retrieve the value, name is used as variable name. For example if the column reference from one record is named 'id_accepted' and related column value has the value '22': :: +To retrieve the value, name is used as variable name. For example if the column reference from one record is named +'id_accepted' and related column value has the value '22': :: {{id_accepted:Y}} diff --git a/extension/Classes/Core/AbstractBuildForm.php b/extension/Classes/Core/AbstractBuildForm.php index 5f3c673efbe58a8a7f4d9cb90bfcec54a9d1f8fe..ed76fb314b0176e9bd00cdeed73a4a5b80c8e906 100644 --- a/extension/Classes/Core/AbstractBuildForm.php +++ b/extension/Classes/Core/AbstractBuildForm.php @@ -170,6 +170,11 @@ abstract class AbstractBuildForm { ]; $this->symbol[SYMBOL_DELETE] = "<span class='glyphicon " . GLYPH_ICON_DELETE . "'></span>"; + + $this->ttContentUid = $this->store->getVar(TYPO3_TT_CONTENT_UID, STORE_TYPO3); + $this->formId = $this->formSpec[F_ID] ?? 0; + $this->recordId = $this->store->getVar(CLIENT_RECORD_ID, STORE_SIP . STORE_RECORD . STORE_TYPO3 . STORE_ZERO); + } abstract public function fillWrap(); @@ -620,7 +625,7 @@ abstract class AbstractBuildForm { */ public function getFormTagAttributes() { - $attribute['id'] = $this->getFormId(); + $attribute['id'] = $this->getFormId($this->ttContentUid, $this->formId, $this->recordId); $attribute['method'] = 'post'; $attribute['action'] = $this->getActionUrl(); $attribute['target'] = '_top'; @@ -638,14 +643,14 @@ abstract class AbstractBuildForm { * * @return string */ - public function getFormId() { - if ($this->formId === null) { -// $this->formId = uniqid('qfq-form-'); - $this->formId = 'qfq-form-' . $this->store->getVar(TYPO3_TT_CONTENT_UID, STORE_TYPO3) . '-' - . $this->formSpec[F_ID] . '-' . $this->store->getVar(CLIENT_RECORD_ID, STORE_TYPO3 . STORE_SIP . STORE_RECORD . STORE_ZERO); - } + public static function getFormId(string $ttContentUid, string $formId, string $recordId) { + // $this->formId = uniqid('qfq-form-'); +// $this->formId = 'qfq-form-' . $this->store->getVar(TYPO3_TT_CONTENT_UID, STORE_TYPO3) . '-' +// . $this->formSpec[F_ID] . '-' . $this->store->getVar(CLIENT_RECORD_ID, STORE_SIP . STORE_RECORD . STORE_TYPO3 . STORE_ZERO); - return $this->formId; + + //return $this->formId; + return 'qfq-form-' . $ttContentUid . '-' . $formId . '-' . $recordId; } /** @@ -906,9 +911,7 @@ abstract class AbstractBuildForm { // Typically: $htmlElementNameIdZero = true // After Saving a record, staying on the form, the FormElements on the Client are still known as '<feName>:0'. $htmlFormElementName = HelperFormElement::buildFormElementName($formElement, ($htmlElementNameIdZero) ? 0 : $recordId); - $formElement[FE_HTML_ID] = HelperFormElement::buildFormElementId($this->getFormId(), $formElement[FE_ID], - ($htmlElementNameIdZero) ? 0 : $recordId, - $formElement[FE_TG_INDEX]); + $formElement[FE_HTML_ID] = HelperFormElement::buildFormElementId($this->getFormId($this->ttContentUid, $this->formId, $this->recordId), $formElement[FE_ID], $formElement[FE_TG_INDEX]); $jsonElement = array(); $elementExtra = ''; @@ -3123,7 +3126,10 @@ abstract class AbstractBuildForm { // Check for upload type new or old and initialize json config for new upload type $jsonConfig = array(); $preloadedFiles = ''; - + $downloadButton = $formElement[FE_FILE_DOWNLOAD_BUTTON] ?? false; + if ($downloadButton) { + $downloadButton = substr($this->evaluate->parse($formElement[FE_FILE_DOWNLOAD_BUTTON]), 2); + } $jsonConfig[UPLOAD_MIME_TYPE_ACCEPT] = $formElement[FE_FILE_MIME_TYPE_ACCEPT] ?? null; $jsonConfig[UPLOAD_MAX_FILE_SIZE] = $arr[FE_FILE_MAX_FILE_SIZE] ?? null; $jsonConfig[UPLOAD_MULTI_UPLOAD] = false; @@ -3138,7 +3144,7 @@ abstract class AbstractBuildForm { $jsonConfig[UPLOAD_ID] = 1; $jsonConfig[UPLOAD_GROUP_ID] = $groupId ?? 0; $jsonConfig[UPLOAD_DROP_BACKGROUND] = 'white'; - $jsonConfig[UPLOAD_DOWNLOAD_BUTTON] = substr($this->evaluate->parse($formElement[FE_FILE_DOWNLOAD_BUTTON]), 2); + $jsonConfig[UPLOAD_DOWNLOAD_BUTTON] = $downloadButton; $jsonConfig[UPLOAD_TYPE_FORM] = true; $jsonConfig[UPLOAD_FORM_ID] = $formElement[FE_HTML_ID]; $jsonConfig[UPLOAD_SIP_DOWNLOAD_KEY] = $sipDownloadKey; diff --git a/extension/Classes/Core/BuildFormBootstrap.php b/extension/Classes/Core/BuildFormBootstrap.php index feb071a61f86b31cc1379483c3711adb38386918..dcd11ac46078ce15d14ea67f0ff45163680fbe11 100644 --- a/extension/Classes/Core/BuildFormBootstrap.php +++ b/extension/Classes/Core/BuildFormBootstrap.php @@ -448,7 +448,7 @@ class BuildFormBootstrap extends AbstractBuildForm { $class = Support::doAttribute('class', $class); $dataClassOnChange = Support::doAttribute('data-class-on-change', $buttonOnChangeClass); $tooltip = Support::doAttribute('title', $tooltip); - $formId = $this->getFormId(); + $formId = $this->getFormId($this->ttContentUid, $this->formSpec[F_ID], $this->recordId); return "<button id='$buttonHtmlId-$formId' type='button' $class $dataClassOnChange $tooltip $disabled>$element</button>"; } @@ -628,7 +628,7 @@ class BuildFormBootstrap extends AbstractBuildForm { $actionDelete = FILE_ACTION . '=' . FILE_ACTION_DELETE; # Replacing the attributes set via tail / javascript - $attribute["data-form-id"] = $this->getFormId(); + $attribute["data-form-id"] = $this->getFormId($this->ttContentUid, $this->formSpec[F_ID], $this->recordId); $attribute["data-tabs-id"] = $this->getTabId(); if (0 < ($recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP))) { $attribute["data-delete-url"] = $this->createDeleteUrl($this->formSpec[F_FINAL_DELETE_FORM], $recordId); diff --git a/extension/Classes/Core/Helper/HelperFormElement.php b/extension/Classes/Core/Helper/HelperFormElement.php index bdd88c9ee2015bd350449e71bfcf46b740379b06..0806d09e0daa744bbbfedff081d3989871dfc7a2 100644 --- a/extension/Classes/Core/Helper/HelperFormElement.php +++ b/extension/Classes/Core/Helper/HelperFormElement.php @@ -8,6 +8,7 @@ namespace IMATHUZH\Qfq\Core\Helper; +use IMATHUZH\Qfq\Core\AbstractBuildForm; use IMATHUZH\Qfq\Core\Evaluate; use IMATHUZH\Qfq\Core\Store\Store; @@ -180,8 +181,8 @@ class HelperFormElement { * * @return string */ - public static function buildFormElementId($formId, $formElementId, $recordId, $formElementCopy) { - return "$formId" . HTML_DELIMITER_ID . "$formElementId" . HTML_DELIMITER_ID . "$recordId" . HTML_DELIMITER_ID . "$formElementCopy"; + public static function buildFormElementId($formId, $formElementId, $formElementCopy) { + return "$formId" . HTML_DELIMITER_ID . "$formElementId" . HTML_DELIMITER_ID . "$formElementCopy"; } @@ -200,7 +201,9 @@ class HelperFormElement { switch ($fe[FE_CLASS]) { case FE_CLASS_CONTAINER: - $feSpecNative[$key][FE_HTML_ID] = self::buildFormElementId($formId, $fe[FE_ID], $recordId, $formElementCopy); + self::$store = Store::getInstance(); + $ttContentUid = self::$store->getVar(TYPO3_TT_CONTENT_UID, STORE_TYPO3); + $feSpecNative[$key][FE_HTML_ID] = self::buildFormElementId(AbstractBuildForm::getFormId($ttContentUid, $formId, $recordId), $fe[FE_ID], $formElementCopy); break; default: break; diff --git a/extension/Classes/Core/QuickFormQuery.php b/extension/Classes/Core/QuickFormQuery.php index 63e65e7c994e104ac4487651d731855eaddf711f..ac537cb9065593f066fb9048263255a76a2c01f4 100644 --- a/extension/Classes/Core/QuickFormQuery.php +++ b/extension/Classes/Core/QuickFormQuery.php @@ -385,7 +385,9 @@ class QuickFormQuery { } if ($this->store->getVar(TYPO3_DEBUG_SHOW_BODY_TEXT, STORE_TYPO3) === 'yes') { - $htmlId = HelperFormElement::buildFormElementId($this->formSpec[F_ID], 0, 0, 0); + $ttContentUid = $this->store->getVar(TYPO3_TT_CONTENT_UID, STORE_TYPO3); + + $htmlId = HelperFormElement::buildFormElementId($ttContentUid, 0, 0); $html .= Support::doTooltip($htmlId . HTML_ID_EXTENSION_TOOLTIP, $this->t3data[T3DATA_BODYTEXT]); } diff --git a/extension/Tests/Unit/Core/BuildFormPlainTest.php b/extension/Tests/Unit/Core/BuildFormPlainTest.php index c9733c71eb9ff035a61f1418bf3ae3162307faf3..7d717bc9ae4c4c2ead08e41f642c76b9f7ccf4df 100644 --- a/extension/Tests/Unit/Core/BuildFormPlainTest.php +++ b/extension/Tests/Unit/Core/BuildFormPlainTest.php @@ -38,11 +38,11 @@ class BuildFormPlainTest extends AbstractDatabaseTest { */ public function testGetFormId() { $build = new BuildFormPlain([F_DB_INDEX => DB_INDEX_DEFAULT], array(), array(), $this->dbArray); - - $formId1 = $build->getFormId(); + $formId = 0; + $formId1 = $build->getFormId($build->ttContentUid, $formId, $build->recordId); $this->assertMatchesRegularExpression('/qfq-form-[0-9]*-[0-9]*-[0-9]*/', $formId1); - $formId2 = $build->getFormId(); + $formId2 = $build->getFormId($build->ttContentUid, $formId, $build->recordId); $this->assertEquals($formId1, $formId2); /* diff --git a/javascript/build/copy.js b/javascript/build/copy.js index 4fe12050d189eefe93e5cea90e3a09970f49763e..aa07f9c3b7c3426d91ade30ddb56f6aadac1b686 100644 --- a/javascript/build/copy.js +++ b/javascript/build/copy.js @@ -158,10 +158,10 @@ const todos = [ css: "node_modules/filepond/dist/", custom: [ { - from: "node_modules/filepond-plugin-file-validate-type/dist/filepond-plugin-file-validate-type.js", + from: "node_modules/filepond-plugin-file-validate-type/dist/filepond-plugin-file-validate-type.min.js", to: target.js },{ - from: "node_modules/filepond-plugin-file-validate-size/dist/filepond-plugin-file-validate-size.js", + from: "node_modules/filepond-plugin-file-validate-size/dist/filepond-plugin-file-validate-size.min.js", to: target.js }, ] diff --git a/javascript/src/Main.js b/javascript/src/Main.js index c01bcbe92306fd428521c7dd187a219620484a54..675ff717a770027abbd063e8c8542c88bac899e7 100644 --- a/javascript/src/Main.js +++ b/javascript/src/Main.js @@ -247,8 +247,6 @@ $(document).ready( function () { FilePond.registerPlugin(FilePondPluginFileValidateSize); FilePond.registerPlugin(FilePondPluginFileValidateType); - FilePond.registerPlugin(FilePondPluginImagePreview); - FilePond.registerPlugin(FilePondPluginImageEdit); // Get a reference to the file input element const inputElements = document.querySelectorAll('input[type="file"].fileupload');