- Extract the complete import logic (label-scan reading, page
find-or-create, slot filling, content-idempotent image attach) from
ImportSubmarketWorkbooksCommand into the shared service
SubmarketWorkbookImporter; the CLI command and the new controller are
thin shells around importFile(), so both entry points cannot drift.
CLI regression verified: identical dry-run report for the reference
workbook (12 elements, page 443)
- New "Sub-Markets" tab in the VITEC Import module
(SubmarketImportController + Import/Submarkets.html): upload multiple
filled workbooks into the SAME inbox the CLI uses
(migrations/submarkets_xlsx_in/), per-file checkboxes, dry-run and
apply buttons, result cards with the familiar report and a direct
link into the page module; backend dry-run verified against the CLI
- Submitted filenames are whitelisted against the actual directory
listing (no path traversal); uploads restricted to sanitized .xlsx
basenames
- Routes submarkets/submarket_upload/submarket_process in Modules.php,
Sub-Markets tab link in the sibling module views, ok/danger badge
colors in backend-import.css
- Docs section 5y (incl. operations note: apply in small batches in the
module, mass runs via CLI - image downloads run inside the web
request)
thumbnail of the actual image (hero background, intro image, insights
cover), key copy in the summary line, full details expanded; card and
intro-paragraph previews are wrapped in the same mechanism
- New SubmarketPluginPreview for vitec_usecaselist / vitec_productfeature /
vitec_productlist: instead of bare standard boxes they now list the
selected story titles (flagging stories that still lack a quote), the
featured product and the hand-picked products in order
- Container-style collapse for whole page-module COLUMNS: a chevron at the
right of every column header folds a section down to its title row,
state kept per page and colPos in localStorage - the slot view of a
sub-market page folds to six slim bands
- Previews sit under the page module's pointer-events lock and its
click-to-edit layer: pointer events are re-enabled inside the collapse
markup and the toggle runs on pointerdown in the capture phase
- Two more v14 removals fixed on the way, both latent in the OLDER preview
classes too (Usecaseshow, Modelcard would have crashed the page module):
GridColumnItem::getRecord() now returns a Domain\Record object, and
StandaloneView is gone - previews normalize the record via a shared
helper and render through the ViewFactory
- vitec_usecaselist: layout + record selection like marketlist
- new plugin vitec_solutionlist (spec 7.13.3, key "solutions")
- tx_vitec_domain_model_usecase: detail_page -> resolved detailUrl
(also gives story cards in vitec_modelcard a link for the first time)
- "Show Toolbar" checkbox on product/market/solution/usecase lists
- spec bumped to v1.9
BREAKING: vitec_productlist and vitec_usecaselist now emit an object
instead of a bare array. Consumers must read products.products and
usecases.usecases. Also found: productlist had a configurable layout
that was never serialised; it is emitted now, but keeps its own 0-3
vocabulary instead of grid/list/carousel.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
New "VITEC Import" module under Web: one import page per domain model
(v1: Market, Solution, Product - registry-driven, adding a model is one
config entry). Workflow: upload a CSV (delimiter and encoding are
auto-detected, including German-Excel semicolon/Windows-1252), map CSV
columns to DB fields, persist the mapping per model together with the
identity field used for matching (new table tx_vitec_import_mapping,
no TCA - pure tool configuration), review a unified list of CSV rows
matched against the DB records (new / update with differing fields /
unchanged / db-only), then apply the checked rows through DataHandler.
Each importable row carries an editable JSON payload textarea - what
is written is the textarea content, not the raw CSV, so editors can
fix values right in the review step. The parsed CSV travels through
the form as a hidden JSON field: no session state, no temp files.
Importable fields are derived from TCA at runtime (scalar types only;
files, categories and other relations are excluded - a flat CSV
cannot carry them). Payloads are whitelisted against that field list
on apply; new records require a storage pid (prefilled from existing
records). BE user permissions apply via DataHandler.
The module ships its own CSS (backend-import.css, loaded only by
this module) using the frontend button palette from _vitec.scss:
orange #f47937 for primary actions, navy #26358c for secondary
actions and structure. The stray <h2>Hi</h2> debug leftover in the
shared backend layout is removed (also affects the OG Image module).
Deliberately out of v1: import log with three-way compare (protection
against overwriting manual edits), images/relations, multiple saved
mappings per model.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
New "VITEC Import" module under Web: one import page per domain model
(v1: Market, Solution, Product - registry-driven, adding a model is one
config entry). Workflow: upload a CSV (delimiter and encoding are
auto-detected, including German-Excel semicolon/Windows-1252), map CSV
columns to DB fields, persist the mapping per model together with the
identity field used for matching (new table tx_vitec_import_mapping,
no TCA - pure tool configuration), review a unified list of CSV rows
matched against the DB records (new / update with differing fields /
unchanged / db-only), then apply the checked rows through DataHandler.
Each importable row carries an editable JSON payload textarea - what
is written is the textarea content, not the raw CSV, so editors can
fix values right in the review step. The parsed CSV travels through
the form as a hidden JSON field: no session state, no temp files.
Importable fields are derived from TCA at runtime (scalar types only;
files, categories and other relations are excluded - a flat CSV
cannot carry them). Payloads are whitelisted against that field list
on apply; new records require a storage pid (prefilled from existing
records). BE user permissions apply via DataHandler.
Deliberately out of v1: import log with three-way compare (protection
against overwriting manual edits), images/relations, multiple saved
mappings per model.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Resolves a cascade of TYPO3 v14 breaking changes that left every VITEC
plugin's JSON output silently empty:
1. `list_type` column dropped — all renderer page-discovery queries now
filter by `CType = 'vitec_X'`.
2. `#[AsAllowedCallable]` attribute added to every public render() —
without it v14 throws AllowedCallableException, which headless
silently filters via its "Oops, an error occurred!" guard.
3. `$GLOBALS['TSFE']->id` is null inside JSON cObj context — page id
now read from the `frontend.page.information` request attribute
(TSFE fallback kept for legacy entry points).
4. page.tsconfig wizard items migrated to `CType = vitec_X` directly
(legacy `CType=list, list_type=...` no longer exists in v14).
5. ContainerChildrenProcessor + ContentElementResolver dispatch the
PLUGIN_RENDERERS map by CType (primary) with list_type fallback.
Beyond the bug fix this commit also contains:
- Datasheets renderer rewritten to "products with newest datasheet"
semantics (filtered via Download.hideondatasheets).
- New vitec/card content block — multi-purpose card with backend
preview and layout/background/aspect/alignment/border/shadow options.
- New vitec_container CType (b13 single-column container, FlexForm
cssClass propagated into the JSON envelope).
- ContentElementResolver service for contentelement/contentelementcta
link resolution; ContainerChildrenProcessor for nested plugin
resolution inside b13 containers.
- Vitecset setup.typoscript: ContentElement import moved to top so
lib.contentElement is defined before VITEC's tt_content blocks.
- Cleanup: 98 .bak.<timestamp> debugging backups removed; *.bak.* and
/public/_assets_install/ added to .gitignore.
Resolves a cascade of TYPO3 v14 breaking changes that left every VITEC
plugin's JSON output silently empty:
1. `list_type` column dropped — all renderer page-discovery queries now
filter by `CType = 'vitec_X'`.
2. `#[AsAllowedCallable]` attribute added to every public render() —
without it v14 throws AllowedCallableException, which headless
silently filters via its "Oops, an error occurred!" guard.
3. `$GLOBALS['TSFE']->id` is null inside JSON cObj context — page id
now read from the `frontend.page.information` request attribute
(TSFE fallback kept for legacy entry points).
4. page.tsconfig wizard items migrated to `CType = vitec_X` directly
(legacy `CType=list, list_type=...` no longer exists in v14).
5. ContainerChildrenProcessor + ContentElementResolver dispatch the
PLUGIN_RENDERERS map by CType (primary) with list_type fallback.
Beyond the bug fix this commit also contains:
- Datasheets renderer rewritten to "products with newest datasheet"
semantics (filtered via Download.hideondatasheets).
- New vitec/card content block — multi-purpose card with backend
preview and layout/background/aspect/alignment/border/shadow options.
- New vitec_container CType (b13 single-column container, FlexForm
cssClass propagated into the JSON envelope).
- ContentElementResolver service for contentelement/contentelementcta
link resolution; ContainerChildrenProcessor for nested plugin
resolution inside b13 containers.
- Vitecset setup.typoscript: ContentElement import moved to top so
lib.contentElement is defined before VITEC's tt_content blocks.
- Cleanup: 98 .bak.<timestamp> debugging backups removed; *.bak.* and
/public/_assets_install/ added to .gitignore.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New Classes/Service/ContentElementResolver.php: parses TYPO3 typolink
(t3://record?identifier=tt_content&uid=N, t3://page?uid=P#N, plain numeric)
to a normalised tt_content envelope ({id,type,colPos,sorting,appearance,
data}), recursively resolving any nested VITEC list-plugin children.
- ProductListJsonRenderer / ProductShowJsonRenderer: contentelement and
contentelementcta now emit the resolved object instead of the raw
typolink string (breaking change at those two keys).
- Product model: new field videofile (FAL, single video upload in tab
Images and Videos, mp4/webm/ogv/mov/m4v); new bool field showdatapath
(toggle at end of General tab, controls the "Datapath is now Vitec"
graphic in the frontend). ext_tables.sql, TCA, model property +
getter/setter, and both renderers updated accordingly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>