Product text import from agency XLSX workbooks
VITEC Import module: Products tab is now a searchable/sortable product overview. "Edit Product" opens an XLSX upload with per-field source mapping (component + cell), old/new preview and checkbox apply via DataHandler; the mapping and manual matches are persisted and preselect the next workbook. Category workbooks are detected and rejected. - new: ProductXlsxReader (PhpSpreadsheet), ProductTextImportController, Products/ProductTexts templates, 4 module routes - related products: per-pair card text in new side table tx_vitec_product_related_text (survives MM rewrites), emitted as `cardtext` in the product JSON; missing MM relations added add-only - card copy read from Body Copy (D) with fallback to CTA/Card Copy (E) - the workbooks fill either depending on row type - product detail page <title> now uses seotitle with title fallback (provider made singleton and fed from the JSON renderer) - per-user recent-search badges; last loaded workbook stored per product (tx_vitec_product_workbook), Edit Product reopens on it - composer: add phpoffice/phpspreadsheet ^5.9 - diagnostics: migrations/check_workbook.php
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
use Evomedien\Vitec\Controller\Backend\ImportController;
|
||||
use Evomedien\Vitec\Controller\Backend\ProductTextImportController;
|
||||
use Evomedien\Vitec\Controller\Backend\WordPressImportController;
|
||||
use Evomedien\Vitec\Controller\OgImageController;
|
||||
|
||||
@@ -34,6 +35,20 @@ return [
|
||||
'target' => ImportController::class . '::seoUploadAction',
|
||||
'methods' => ['POST'],
|
||||
],
|
||||
'products' => [
|
||||
'target' => ProductTextImportController::class . '::productsAction',
|
||||
],
|
||||
'product_edit' => [
|
||||
'target' => ProductTextImportController::class . '::productEditAction',
|
||||
],
|
||||
'product_preview' => [
|
||||
'target' => ProductTextImportController::class . '::productPreviewAction',
|
||||
'methods' => ['POST'],
|
||||
],
|
||||
'product_apply' => [
|
||||
'target' => ProductTextImportController::class . '::productApplyAction',
|
||||
'methods' => ['POST'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'web_vitecwpimport' => [
|
||||
|
||||
@@ -25,5 +25,14 @@ return [
|
||||
'typo3/cms-frontend/site',
|
||||
],
|
||||
],
|
||||
'vitec/download-file' => [
|
||||
'target' => \Evomedien\Vitec\Middleware\DownloadFileMiddleware::class,
|
||||
'after' => [
|
||||
'typo3/cms-core/normalized-params-attribute',
|
||||
],
|
||||
'before' => [
|
||||
'typo3/cms-frontend/site',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -252,3 +252,29 @@ tt_content {
|
||||
# =============================================================================
|
||||
page.10.fields.jsonLd = USER
|
||||
page.10.fields.jsonLd.userFunc = Evomedien\Vitec\UserFunc\PageJsonLdRenderer->render
|
||||
|
||||
############################################################
|
||||
# Frontend resolution for the record links from the link
|
||||
# browser (page.tsconfig TCEMAIN.linkHandler):
|
||||
# download -> forced download endpoint (DownloadFileMiddleware)
|
||||
# product -> detail view, same /product/<slug> convention as
|
||||
# the `link` field in the product JSON (page 10)
|
||||
# A hidden or deleted target makes the typolink fail -> null.
|
||||
############################################################
|
||||
|
||||
config.recordLinks {
|
||||
download {
|
||||
forceLink = 1
|
||||
typolink {
|
||||
parameter.cObject = TEXT
|
||||
parameter.cObject.dataWrap = /download/file/{field:uid}
|
||||
}
|
||||
}
|
||||
product {
|
||||
forceLink = 1
|
||||
typolink {
|
||||
parameter.cObject = TEXT
|
||||
parameter.cObject.dataWrap = /product/{field:slug}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ return [
|
||||
],
|
||||
],
|
||||
'types' => [
|
||||
'1' => ['showitem' => 'title, subtitle, slug, teaser, description, applications, highlights, contentelement, contentelementcta, downloads, showdatapath,
|
||||
'1' => ['showitem' => 'title, subtitle, slug, teaser, description, description2, applications, capabilities, highlights, contentelement, contentelementcta, downloads, portfolio, showdatapath, textrelatedproducts, relatedprodukt,
|
||||
--div--;SEO, seotitle, urltitle, seometa, keywords, structureddata,
|
||||
--div--;Images and Videos, productimage, ogimage, video, videofile,
|
||||
--div--;Images and Videos, heroimage, productimage, ogimage, video, videofile,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories, categories,
|
||||
--div--;Visibility, hideonapp, hideonwebsite, hideondatasheets, hideonproducts, shortcut, shortcutpid,
|
||||
--div--;Misc, legacy, supportproduct, subproduct, relatedprodukt,
|
||||
--div--;Misc, legacy, supportproduct, subproduct,
|
||||
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, hidden, starttime, endtime'],
|
||||
],
|
||||
'columns' => [
|
||||
@@ -556,6 +556,88 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
'description2' => [
|
||||
'exclude' => true,
|
||||
'label' => '2nd Description',
|
||||
'config' => [
|
||||
'type' => 'text',
|
||||
'enableRichtext' => true,
|
||||
'eval' => 'trim',
|
||||
'default' => ''
|
||||
],
|
||||
'defaultExtras' => 'richtext:rte_transform[mode=ts_css]'
|
||||
],
|
||||
|
||||
'capabilities' => [
|
||||
'exclude' => true,
|
||||
'label' => 'Capabilities',
|
||||
'config' => [
|
||||
'type' => 'text',
|
||||
'enableRichtext' => true,
|
||||
'eval' => 'trim',
|
||||
'default' => ''
|
||||
],
|
||||
'defaultExtras' => 'richtext:rte_transform[mode=ts_css]'
|
||||
],
|
||||
|
||||
'portfolio' => [
|
||||
'exclude' => true,
|
||||
'label' => 'Portfolio',
|
||||
'description' => 'Link to the product portfolio (page, file or external URL)',
|
||||
'config' => [
|
||||
'type' => 'link',
|
||||
'allowedTypes' => ['page', 'url', 'file', 'record'],
|
||||
'size' => 50,
|
||||
],
|
||||
],
|
||||
|
||||
'textrelatedproducts' => [
|
||||
'exclude' => true,
|
||||
'label' => 'Text Related Products',
|
||||
'config' => [
|
||||
'type' => 'text',
|
||||
'enableRichtext' => true,
|
||||
'eval' => 'trim',
|
||||
'default' => ''
|
||||
],
|
||||
'defaultExtras' => 'richtext:rte_transform[mode=ts_css]'
|
||||
],
|
||||
|
||||
'heroimage' => [
|
||||
'exclude' => true,
|
||||
'label' => 'Hero Image(s)',
|
||||
'config' => [
|
||||
'type' => 'inline',
|
||||
'foreign_table' => 'sys_file_reference',
|
||||
'foreign_field' => 'uid_foreign',
|
||||
'foreign_sortby' => 'sorting_foreign',
|
||||
'foreign_table_field' => 'tablenames',
|
||||
'foreign_match_fields' => [
|
||||
'fieldname' => 'heroimage',
|
||||
],
|
||||
'appearance' => [
|
||||
'collapseAll' => true,
|
||||
'levelLinksPosition' => 'top',
|
||||
'showSynchronizationLink' => true,
|
||||
'showPossibleLocalizationRecords' => true,
|
||||
'showAllLocalizationLink' => true,
|
||||
],
|
||||
'behaviour' => [
|
||||
'allowLanguageSynchronization' => true,
|
||||
],
|
||||
'filter' => [
|
||||
[
|
||||
'userFunc' => \TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter::class . '->filterInlineChildren',
|
||||
'parameters' => [
|
||||
'allowedFileExtensions' => 'jpg,jpeg,png,gif,webp',
|
||||
],
|
||||
],
|
||||
],
|
||||
'maxitems' => 10,
|
||||
'minitems' => 0,
|
||||
],
|
||||
],
|
||||
|
||||
'contentelement' => [
|
||||
'exclude' => true,
|
||||
'label' => 'Select Content Element for Key Features Section',
|
||||
|
||||
@@ -127,3 +127,28 @@ mod.web_layout.tt_content.preview {
|
||||
# Hinweis: Content-Blocks-Previews werden automatisch aus
|
||||
# packages/vitec/ContentBlocks/ContentElements/<n>/templates/backend-preview.html geladen.
|
||||
# Keine separate Registrierung nötig.
|
||||
|
||||
############################################################
|
||||
# Link browser: record links to VITEC domain models.
|
||||
# Stored as t3://record?identifier=download|product&uid=N -
|
||||
# frontend resolution lives in setup.typoscript (config.recordLinks).
|
||||
############################################################
|
||||
|
||||
TCEMAIN.linkHandler {
|
||||
download {
|
||||
handler = TYPO3\CMS\Backend\LinkHandler\RecordLinkHandler
|
||||
label = Download
|
||||
configuration {
|
||||
table = tx_vitec_domain_model_download
|
||||
}
|
||||
displayAfter = file
|
||||
}
|
||||
product {
|
||||
handler = TYPO3\CMS\Backend\LinkHandler\RecordLinkHandler
|
||||
label = Product
|
||||
configuration {
|
||||
table = tx_vitec_domain_model_product
|
||||
}
|
||||
displayAfter = download
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user