Files
VITEC-website/packages/evo_megamenu_json/README.md
T
orascheandClaude Opus 5.5 73e4298b75 Insights spotlight: news from folders 11 + 442, source editable in the menu
- Megamenu entries with the catalog or spotlight layout get two editor
  fields, "Data source folders" (source_pages) and "Data source
  categories" (source_categories); the extension stores them, the site
  package's listener reads them from the entry row.
- ProvideInsightsSpotlight reads its news from those folders (empty =
  11 + 442; the newer posts live in 442, the query only read 11) and,
  when set, only from those categories (Insights: Blog Post + Press
  Release). Newest datetime first, three cards.
- Pages carrying the menu are tagged with the news and event tables, so
  saving such a record refreshes the menu without a cache flush.
- VITEC field descriptions via a TCA override; spec v1.31, README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 10:59:56 +01:00

191 lines
7.7 KiB
Markdown

# EVO Megamenu JSON
An editable megamenu for headless TYPO3. One content element holds the whole
menu; the extension publishes it as JSON, the front end renders it.
Project-neutral by design — nothing in here knows which site it runs on.
## What the editor gets
A plugin called **Megamenu**. Inside it:
| Level | Holds |
|---|---|
| **Entry** | one item in the main bar: label, target page, panel layout |
| **Column** | a heading (optionally a link) and its items |
| **Item** | label, link, teaser line, badge, thumbnail, “page not ready” flag |
| **Teaser card** | kicker, headline, text, link, image — for editorial panels |
| **Featured** | one highlighted block per entry, edited on the entry itself |
Five panel layouts per entry: `columns` for a curated structure menu,
`teasers` for a small link column next to cards (news, stories),
`pagetree` for a structure menu built live from the page tree,
`catalog` for a data-driven panel whose content comes from the site
package, and `spotlight` for a visual panel with a left-rail nav and live
content cards (see below).
## Installation
```bash
composer require evomedien/evo-megamenu-json
vendor/bin/typo3 extension:setup
vendor/bin/typo3 database:updateschema "*.add,*.change"
```
In the site configuration, add the set **EVO Megamenu (JSON)** and set:
| Setting | Meaning |
|---|---|
| `megamenu.contentUid` | uid of the Megamenu element to publish on every page |
| `megamenu.storagePid` | alternative: folder whose first Megamenu element is used |
Leave both uid and pid at 0 and the menu is only rendered where the element
sits — useful while building it.
## Payload
```json
"megaMenu": {
"settings": {
"stage": 3, "openOn": "hover", "closeDelay": 140, "columnsPerRow": 4,
"panelWidth": "container", "pendingBehaviour": "fallback",
"showCounts": true, "showViewAll": true, "viewAllLabel": "View all %s"
},
"entries": [
{
"title": "Products",
"link": "/products",
"layout": "columns",
"columns": [
{
"title": "IP Video Streaming",
"link": "/products/ip-video-streaming",
"items": [
{ "title": "Appliances", "link": "/products/ip-video-streaming/appliances",
"pending": true, "teaser": "MGW Diamond, Ace, Pico",
"image": { "url": "/fileadmin/...", "alternative": "", "title": "", "width": 600, "height": 400 } }
]
}
],
"featured": { "kicker": "Datasheet", "title": "MGW Diamond-H", "text": "…", "link": "/product/…", "image": { } }
}
]
}
```
`settings` travels with the menu on purpose: the front end reads hover
behaviour, close delay, column count and labels from the payload instead of
hard-coding them, so an editor can change them without a deploy.
### Content stages
`stage` decides how much detail is emitted — 1 structure only, 2 adds images,
teaser lines and cards, 3 adds the featured block. Later stages only **add**
keys, so a front end written for stage 1 keeps working when the stage is
raised.
### `pending`
An item whose target page does not exist yet carries `"pending": true`.
`settings.pendingBehaviour` says what to do with it: `fallback` (link to the
column heading instead), `mute` (show, not clickable) or `hide`. This keeps
a menu shippable while its deeper pages are still being built.
### Layout `catalog`
For panels built from data rather than by hand — a product catalog with
categories, groups and items, a search bar, whatever the site needs. The
extension stays project-neutral: it dispatches
`Evomedien\EvoMegamenuJson\Event\BuildCatalogEvent` for every catalog entry
and emits whatever a listener sets via `setCatalog()` verbatim as
`catalog` on the entry (`null` without a listener). The entry's teaser cards
are emitted as `teasers` as usual and serve as the panel's featured tiles;
its columns are ignored.
```php
#[AsEventListener(identifier: 'site/megamenu-catalog')]
final class ProvideCatalog
{
public function __invoke(BuildCatalogEvent $event): void
{
$event->setCatalog(['categories' => [/* … */]]);
}
}
```
`getEntry()` hands the listener the raw entry row (to tell several catalog
entries apart), `getStage()` the content stage.
**Data source fields** (catalog and spotlight entries): *Data source
folders* (`source_pages`, comma list of page uids) and *Data source
categories* (`source_categories`, sys_category MM with
`tablenames = tx_evomegamenujson_entry`, `fieldname = source_categories`).
The extension only stores them; the listener reads them from the entry row
and decides what they mean (empty = its own default).
### Layout `pagetree`
A structure panel that can never age against the site: the columns mirror
the live subtree of the page the entry links to - one column per child
page, its children as the items. Hidden or nav-hidden pages leave the menu
with the next cache flush. Curated columns are ignored; teasers and the
featured slot stay editorial. From stage 2 a child page with media gets its
first image as `image` on the column - attach images in the page
properties and the panel turns visual by itself. From stage 2 the items
carry `image` (first page media or `null`) and, when set, the page
`abstract` as `teaser`.
The entry field *Page tree display* picks the presentation and travels as
`display`: `columns` (default, columns side by side) or `rail` (the columns
as a list on the left, the hovered column's items as image cards on the
right) plus `cardSize` (`regular` | `compact`) for `rail`. A front end that
ignores `display` keeps rendering columns.
### Layout `spotlight`
A visual panel ("rossvideo style"): `nav` is a flat left rail built live
from the linked page's children - each item with `title`, `link` and, from
stage 2, the page `abstract` as `teaser` plus the first page media as
`image`, so the front end can swap the visual area on hover. Next to it the
extension emits `spotlight`, filled by the site package: it dispatches
`Evomedien\EvoMegamenuJson\Event\BuildSpotlightEvent` per spotlight entry
and emits whatever a listener sets via `setSpotlight()` verbatim
(`null` without a listener). Curated columns are ignored.
The VITEC site package ships `ProvideInsightsSpotlight`, which supplies
```json
"spotlight": {
"news": [ {"title", "date", "link", "teaser?", "image?"} ],
"events": [ {"title", "start", "end", "venue", "booth", "city",
"country", "attendanceMode", "link", "teaser?", "image?"} ]
}
```
- `news`: the three latest news records (type 0 - the Solr convention)
from the entry's *Data source folders* (empty = 11 + 442) and, when set,
in one of its *Data source categories*; `link` =
`/news/article/<path_segment>` per the NewsDetail route enhancer, image
from `fal_media` as processed 640px webp. Pages carrying the menu are
tagged with the news and event tables, so saving such a record refreshes
the menu.
- `events`: the next two events (`hideonwebsite` = 0, upcoming by
eventstart/eventend), `link` = the record's `eventurl` or the events
page, image processed the same way.
## Notes
* Every link is a resolved URL — page, record, external or file, run through
typolink at render time.
* Translations are overlaid per record, so a menu can be localised entry by
entry.
* The renderer never throws: a broken menu returns an empty value rather than
taking the page payload down.
* Caching: every page carrying the menu is tagged with the menu tables and
`tt_content_<uid>` of the menu element, so saving any menu record refreshes
all of them. Panels built from the page tree (`pagetree`, `catalog`,
`spotlight`) pick up page changes with the next cache flush.
* Without `friendsoftypo3/headless` the element has no JSON envelope to render
into — the extension is built for headless installations.