diff --git a/Classes/Domain/Repository/TransfusionRepository.php b/Classes/Domain/Repository/TransfusionRepository.php index 1fdd937..4a7e12c 100644 --- a/Classes/Domain/Repository/TransfusionRepository.php +++ b/Classes/Domain/Repository/TransfusionRepository.php @@ -13,6 +13,7 @@ use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Resource\FileRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -34,9 +35,15 @@ class TransfusionRepository */ protected IconFactory $iconFactory; + /** + * @var FileRepository + */ + protected FileRepository $fileRepository; + public function __construct() { $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); + $this->fileRepository = GeneralUtility::makeInstance(FileRepository::class); } /** @@ -105,7 +112,31 @@ protected function fetchDefaultLanguageRecordsAndConnectionsForTable( ) ->orderBy($transFusionFields['sorting']) ->executeQuery(); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference'); + $fileFields = $queryBuilder + ->select( + 'fieldname' + ) + ->from('sys_file_reference') + ->where( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($page, Connection::PARAM_INT)), + $queryBuilder->expr()->eq('tablenames', $queryBuilder->createNamedParameter($table)), + $queryBuilder->expr()->eq('l10n_parent', 0), + $queryBuilder->expr()->eq('sys_language_uid', 0), + ) + ->groupBy('fieldname') + ->executeQuery() + ->fetchAllAssociativeIndexed(); while ($record = $defaultLanguageQuery->fetchAssociative()) { + $files = []; + if (!empty($fileFields)) { + foreach (array_keys($fileFields) as $fieldName) { + $fileRecords = $this->fileRepository->findByRelation($table, $fieldName, $record['uid']); + if (!empty($fileRecords)) { + $files[$fieldName] = $fileRecords; + } + } + } $preparedRecord = [ 'uid' => $record['uid'], 'pid' => $record['pid'], @@ -118,6 +149,9 @@ protected function fetchDefaultLanguageRecordsAndConnectionsForTable( 'icon' => $this->getIconForRecord($table, $record, $record[$transFusionFields['label']]), 'previewData' => $record ]; + if (!empty($files)) { + $preparedRecord['relatedFiles'] = $files; + } $preparedRecord['column'] = ($table === 'tt_content' ? $record[$transFusionFields['column']] : ''); $connectedRecords = $this->getConnectedTranslations( $table, @@ -179,6 +213,7 @@ protected function fetchDefaultLanguageRecordsAndConnectionsForTable( !empty($dataMapRecord['brokenOrOrphaned']) && !isset($assigned[$dataMapRecord['uid']]) ) { + $preparedRecord['brokenConnections'] = []; foreach ($dataMapRecord['brokenOrOrphaned'] as $brokenOrOrphaned) { if ($brokenOrOrphaned['uid'] === $preparedRecord['uid']) { // These records are partly matching their translation parent but are not connected yet @@ -201,7 +236,7 @@ protected function fetchDefaultLanguageRecordsAndConnectionsForTable( foreach ($fullDataMap[$table] as $dataMapRecord) { if (!empty($dataMapRecord['uid']) && empty($assigned[$dataMapRecord['uid']])) { if (!empty($dataMapRecord['brokenOrOrphaned'])) { - $preparedRecord = ['brokenConnections' => []]; + $preparedRecord = ['orphanedConnections' => []]; foreach ($dataMapRecord['brokenOrOrphaned'] as $brokenOrOrphaned) { $preparedRecord['orphanedConnections'][] = [ 'uid' => $brokenOrOrphaned['uid'], @@ -213,9 +248,6 @@ protected function fetchDefaultLanguageRecordsAndConnectionsForTable( ]; } } - if (!empty($preparedRecord)) { - $defaultLanguageRecords[$dataMapRecord['uid']] = $preparedRecord; - } } } return $defaultLanguageRecords; @@ -404,8 +436,37 @@ public function fetchDisconnectedRecordsAndPrepareDataMap( $queryBuilder->expr()->eq($transFusionFields['language'], $language), ) ->executeQuery(); + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference'); + $queryBuilder + ->getRestrictions() + ->removeAll() + ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) + ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class)); + $fileFields = $queryBuilder + ->select( + 'fieldname' + ) + ->from('sys_file_reference') + ->where( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($page, Connection::PARAM_INT)), + $queryBuilder->expr()->eq('tablenames', $queryBuilder->createNamedParameter($table)), + $queryBuilder->expr()->eq('sys_language_uid', $language), + ) + ->groupBy('fieldname') + ->executeQuery() + ->fetchAllAssociativeIndexed(); while ($record = $disconnectedRecords->fetchAssociative()) { $fetchPossibleParents = false; + $files = []; + if (!empty($fileFields)) { + foreach (array_keys($fileFields) as $fieldName) { + $fileRecords = $this->fileRepository->findByRelation($table, $fieldName, $record['uid']); + if (!empty($fileRecords)) { + $files[$fieldName] = $fileRecords; + } + } + } $preparedRecord = [ 'uid' => $record['uid'], 'type' => $record[$transFusionFields['type']], @@ -415,6 +476,9 @@ public function fetchDisconnectedRecordsAndPrepareDataMap( 'original' => $record[$transFusionFields['original']], 'previewData' => $record ]; + if (!empty($files)) { + $preparedRecord['relatedFiles'] = $files; + } $preparedRecord['column'] = ($table === 'tt_content' ? $record[$transFusionFields['column']] : ''); $fetchFields = $transFusionFields['language'] . ',' . $transFusionFields['type']; diff --git a/Resources/Private/Partials/Preview.html b/Resources/Private/Partials/Preview.html index 0350a71..478bcc6 100644 --- a/Resources/Private/Partials/Preview.html +++ b/Resources/Private/Partials/Preview.html @@ -3,82 +3,14 @@
-
-
- - - - - - - - - - - - - - - - - - {record.icon} -
-
- {record.label} -
- -
- - - - - - - - - - - - - - - - - - - -
-
-
+ + + + + + + +
@@ -126,3 +58,174 @@
+ + + +
+
+ + + + + + + + + + + + + + + + + + {record.icon} +
+
+ {record.label} +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + {record.icon} +
+
+ +
+
+ {record.name} +
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+
+
diff --git a/Resources/Private/Partials/TableHead.html b/Resources/Private/Partials/TableHead.html index 742b34a..7cee15b 100644 --- a/Resources/Private/Partials/TableHead.html +++ b/Resources/Private/Partials/TableHead.html @@ -1,10 +1,17 @@ -

Original Record - -

+
+

Original Record + +

+ +

Confirmed Connection diff --git a/Resources/Private/Templates/Default/Wizard.html b/Resources/Private/Templates/Default/Wizard.html index ae9d730..bbc6545 100644 --- a/Resources/Private/Templates/Default/Wizard.html +++ b/Resources/Private/Templates/Default/Wizard.html @@ -37,11 +37,12 @@

TransFusion Connector

+ - + + + + + + + + + + + + + + + +
TransFusion Connector
+ + + + + +
diff --git a/Resources/Public/Css/transfusion-backend.css b/Resources/Public/Css/transfusion-backend.css index 9f0bc10..c1e22ea 100644 --- a/Resources/Public/Css/transfusion-backend.css +++ b/Resources/Public/Css/transfusion-backend.css @@ -6,6 +6,10 @@ padding: 0.75rem; } +.module-transfusion-connector .t3-grid-table td { + vertical-align: top; +} + .module-transfusion-connector .t3-grid-table th.transfusion-original { color:var(--bs-secondary-text-emphasis); background:var(--bs-secondary-border-subtle); @@ -82,12 +86,59 @@ background:var(--bs-danger-border-subtle); } +.module-transfusion-connector .t3-grid-table .header-wrapper { + display: flex; + flex-direction: row; + justify-content: space-between; +} + .module-transfusion-connector .t3-grid-table .t3-page-ce { - margin: 0.75rem; + margin: 0.5rem; } .module-transfusion-connector .t3-grid-table .t3-page-ce-element { margin-bottom: 0; + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.module-transfusion-connector .t3-grid-table .t3-page-ce-element .t3-page-ce-header { + padding: 0.5em; + min-height: 44px; + width: 100%; +} + +.module-transfusion-connector .t3-grid-table .header-wrapper .btn-transfusion-toggle-all-files { + margin-top: 0.5em; + text-align: right; + display: none; +} + +.module-transfusion-connector .t3-grid-table .header-wrapper .btn-transfusion-toggle-all-files-show { + display: inline-flex; +} + +.module-transfusion-connector .t3-grid-table .t3-page-ce-wrapper .btn-transfusion-toggle-files { + margin-top: 0.5em; + text-align: right; +} + +.module-transfusion-connector .t3-grid-table .header-wrapper .btn-transfusion-toggle-all-files .icon-actions-chevron-up, +.module-transfusion-connector .t3-grid-table .t3-page-ce-wrapper .btn-transfusion-toggle-files .icon-actions-chevron-up { + display: none; +} + +.module-transfusion-connector .t3-grid-table .header-wrapper .btn-transfusion-toggle-all-files .icon-actions-chevron-down, +.module-transfusion-connector .t3-grid-table .header-wrapper .btn-transfusion-toggle-all-files-active .icon-actions-chevron-up, +.module-transfusion-connector .t3-grid-table .t3-page-ce-wrapper .btn-transfusion-toggle-files .icon-actions-chevron-down, +.module-transfusion-connector .t3-grid-table .t3-page-ce-wrapper .btn-transfusion-toggle-files-active .icon-actions-chevron-up { + display: block; +} + +.module-transfusion-connector .t3-grid-table .header-wrapper .btn-transfusion-toggle-all-files-active .icon-actions-chevron-down, +.module-transfusion-connector .t3-grid-table .t3-page-ce-wrapper .btn-transfusion-toggle-files-active .icon-actions-chevron-down { + display: none; } .module-transfusion-connector .t3-grid-table .t3-page-ce-wrapper .t3-page-ce-header-left { @@ -116,7 +167,15 @@ .module-transfusion-connector .t3-grid-table .transfusion-confirmed .t3-page-ce-header-right .btn-transfusion-new, .module-transfusion-connector .t3-grid-table .transfusion-obvious .t3-page-ce-header-right .btn-transfusion-new, .module-transfusion-connector .t3-grid-table .transfusion-possible .t3-page-ce-header-right .btn-transfusion-new, -.module-transfusion-connector .t3-grid-table .transfusion-broken .t3-page-ce-header-right .btn-transfusion-new { +.module-transfusion-connector .t3-grid-table .transfusion-broken .t3-page-ce-header-right .btn-transfusion-new, +.module-transfusion-connector .t3-grid-table .file-row { display: none; } +.module-transfusion-connector .t3-grid-table .file-row td { + padding-left: 3em; +} + +.module-transfusion-connector .t3-grid-table .file-row-active { + display: table-row; +} diff --git a/Resources/Public/JavaScript/Backend/transfusion-connector.js b/Resources/Public/JavaScript/Backend/transfusion-connector.js index e2b5cbd..2f5b944 100644 --- a/Resources/Public/JavaScript/Backend/transfusion-connector.js +++ b/Resources/Public/JavaScript/Backend/transfusion-connector.js @@ -144,6 +144,65 @@ class TransfusionConnectorActions { for (var i = 0; i < removeButtons.length; i++) { removeButtons[i].addEventListener("click", removeAllConnections, false); } + var toggleAttachedFiles = function(event) { + event.preventDefault(); + var toggleId = this.dataset.toggleid; + var table = this.closest('table'); + var toggleAllButton = table.getElementsByClassName('btn-transfusion-toggle-all-files'); + var toggleRows = table.getElementsByClassName('file-row-' + toggleId); + for (var i = 0; i < toggleRows.length; i++) { + if (toggleRows[i].classList.contains('file-row-active')) { + toggleRows[i].classList.remove('file-row-active'); + } else { + toggleRows[i].classList.add('file-row-active'); + } + } + var activeRows = table.getElementsByClassName('file-row-active'); + if (activeRows.length) { + toggleAllButton[0].classList.add('btn-transfusion-toggle-all-files-active'); + } else { + toggleAllButton[0].classList.remove('btn-transfusion-toggle-all-files-active'); + } + if (this.classList.contains('btn-transfusion-toggle-files-active')) { + this.classList.remove('btn-transfusion-toggle-files-active'); + } else { + this.classList.add('btn-transfusion-toggle-files-active'); + } + } + + var toggleAllAttachedFiles = function(event) { + event.preventDefault(); + var table = this.closest('table'); + var toggleRows = table.getElementsByClassName('file-row'); + var toggleFilesButtons = document.getElementsByClassName("btn-transfusion-toggle-files"); + if (this.classList.contains('btn-transfusion-toggle-all-files-active')) { + this.classList.remove('btn-transfusion-toggle-all-files-active'); + for (var i = 0; i < toggleFilesButtons.length; i++) { + toggleFilesButtons[i].classList.remove('btn-transfusion-toggle-files-active'); + } + for (var i = 0; i < toggleRows.length; i++) { + toggleRows[i].classList.remove('file-row-active'); + } + } else { + this.classList.add('btn-transfusion-toggle-all-files-active'); + for (var i = 0; i < toggleFilesButtons.length; i++) { + toggleFilesButtons[i].classList.add('btn-transfusion-toggle-files-active'); + } + for (var i = 0; i < toggleRows.length; i++) { + toggleRows[i].classList.add('file-row-active'); + } + } + } + + var toggleAllFilesButton = document.getElementsByClassName("btn-transfusion-toggle-all-files"); + toggleAllFilesButton[0].addEventListener("click", toggleAllAttachedFiles, false); + + var toggleFilesButtons = document.getElementsByClassName("btn-transfusion-toggle-files"); + + for (var i = 0; i < toggleFilesButtons.length; i++) { + toggleAllFilesButton[0].classList.add('btn-transfusion-toggle-all-files-show'); + toggleFilesButtons[i].addEventListener("click", toggleAttachedFiles, false); + } var checkMarkedForRemovalOrDeletion = function(event) { event.preventDefault();