From bb7c03235d8993101d5b011c706de1a9f55b4eb2 Mon Sep 17 00:00:00 2001 From: o-rasche Date: Thu, 9 Jul 2026 10:01:56 +0200 Subject: [PATCH] Checkpoint: headless JSON architecture documented + cleanup (Stufe 1+2) Restore point before Stufe 3 (central resolver-service refactoring). Includes this session's work: - Success Story (usecase) rebuild: new fields/tabs, UsecaseSerializer, thin List/Show renderers, MM relations, inline content elements. - vitec_columns content block (two-column layout with per-item content) incl. unified header section; special-cased JSON resolution. - Container per-column flex (items[].config align/justify) + gap on parent. - Unified header section across CEs/plugins/containers; header fields in JSON. - ISO-style architecture spec: Documentation/Headless-JSON-Architecture.md. - Cleanup: removed local scratch + verified .bak backups. - Fixes: B-6 (undefined thumbnail variable in Downloadcardcollection image resolver), B-7 (unsatisfiable legacy CType OR branch in Downloadcard/Datasheets). Rollback: git reset --hard snapshot-2026-07-09-pre-stufe3 Co-Authored-By: Claude Opus 4.8 --- composer.json | 1 + composer.lock | 926 ++++++++++-------- config/sites/vitec/config.yaml | 20 + fix-asset-perms.sh | 30 + .../StructuredDataGeneratorWizard.php | 0 .../Backend/StructuredDataController.php | 0 .../Classes/Controller/EventController.php | 39 + .../.msys00000000000000004cda359073ead130 | 0 .../.msys00000000000000004dd18ef4cfaf2af9 | 0 .../ContainerChildrenProcessor.php | 61 +- packages/vitec/Classes/Domain/Model/Event.php | 266 +++++ .../vitec/Classes/Domain/Model/Product.php | 0 .../Domain/Repository/EventRepository.php | 71 ++ .../LoadContainerCollapseAssets.php | 27 + .../ShowFrontendLayoutBanner.php | 0 .../Classes/Hook/SyncBackendLayoutHook.php | 0 .../.msys00000000000000002272de42bf87f8e5 | 0 .../.msys0000000000000000274fb505bf117200 | 0 .../.msys00000000000000002751b67b19a9c636 | 0 .../.msys00000000000000002752b73c4a27d4ba | 0 .../.msys00000000000000002753b7f777b58735 | 0 .../.msys00000000000000002753b7f978b2a67b | 0 .../.msys0000000000000000284b115dd4770044 | 0 .../Service/ContentElementResolver.php | 12 + .../Classes/Service/StructuredDataService.php | 142 +++ .../Classes/Service/UsecaseSerializer.php | 530 ++++++++++ .../UserFunc/DatasheetsJsonRenderer.php | 180 +++- .../UserFunc/DownloadcardJsonRenderer.php | 188 +++- .../DownloadcardcollectionJsonRenderer.php | 175 +++- .../UserFunc/EventlistJsonRenderer.php | 314 ++++++ .../UserFunc/MarketShowJsonRenderer.php | 0 .../Classes/UserFunc/NewsJsonRenderer.php | 753 ++++++++++++++ .../Classes/UserFunc/PageJsonLdRenderer.php | 185 ++++ .../UserFunc/ProductListJsonRenderer.php | 177 +++- .../UserFunc/ProductShowJsonRenderer.php | 169 +++- .../UserFunc/SolutionShowJsonRenderer.php | 0 .../UserFunc/UsecaseListJsonRenderer.php | 205 +--- .../UserFunc/UsecaseShowJsonRenderer.php | 233 +---- .../View/BackendLayoutDataProvider.php | 0 .../Classes/View/VitecBackendLayoutView.php | 0 .../Configuration/Backend/AjaxRoutes.php | 0 .../Configuration/FlexForms/CardsCarousel.xml | 96 ++ .../Configuration/FlexForms/Container.xml | 0 .../Configuration/FlexForms/Downloadcard.xml | 0 .../Configuration/FlexForms/Eventlist.xml | 48 + packages/vitec/Configuration/Icons.php | 4 + .../vitec/Configuration/JavaScriptModules.php | 0 .../Configuration/Sets/Vitecset/config.yaml | 0 .../Sets/Vitecset/setup.typoscript | 51 +- .../Configuration/TCA/Overrides/pages.php | 0 .../TCA/Overrides/tt_content.php | 6 + .../tt_content_vitec_cards_carousel.php | 63 ++ .../tt_content_vitec_cols_25_25_25_25.php | 8 +- .../tt_content_vitec_cols_33_33_33.php | 7 +- .../Overrides/tt_content_vitec_cols_33_66.php | 6 +- .../Overrides/tt_content_vitec_cols_50_50.php | 6 +- .../Overrides/tt_content_vitec_cols_66_33.php | 6 +- .../Overrides/tt_content_vitec_container.php | 3 +- .../TCA/Overrides/tt_content_vitec_shared.php | 81 ++ .../TCA/tx_vitec_domain_model_event.php | 290 ++++++ .../TCA/tx_vitec_domain_model_product.php | 0 .../TCA/tx_vitec_domain_model_usecase.php | 526 +++++----- .../Headless/vitec_containers.typoscript | 64 +- .../Headless/vitec_menus.typoscript | 0 .../TypoScript/Headless/vitec_news.typoscript | 30 + packages/vitec/Configuration/page.tsconfig | 15 + .../ContentBlocks/Basics/ButtonStyle.yaml | 0 .../Basics/SecondaryButtonStyle.yaml | 0 .../ContentElements/card/assets/icon.svg | 0 .../ContentElements/card/config.yaml | 25 +- .../ContentElements/card/language/labels.xlf | 0 .../card/templates/backend-preview.html | 2 +- .../card/templates/frontend.html | 0 .../ContentElements/columns/assets/icon.svg | 5 + .../ContentElements/columns/config.yaml | 91 ++ .../columns/language/labels.xlf | 45 + .../columns/templates/backend-preview.html | 19 + .../columns/templates/frontend.html | 3 + .../ContentElements/cta-banner/config.yaml | 23 +- .../cta-banner/language/labels.xlf | 4 +- .../cta-banner/templates/backend-preview.html | 10 +- .../ContentElements/faq/assets/icon.svg | 8 + .../ContentElements/faq/config.yaml | 56 ++ .../ContentElements/faq/language/labels.xlf | 33 + .../faq/templates/backend-preview.html | 66 ++ .../faq/templates/frontend.html | 3 + .../ContentElements/hero-section/config.yaml | 31 +- .../hero-section/language/labels.xlf | 0 .../templates/backend-preview.html | 6 +- .../intro-paragraph/assets/icon.svg | 0 .../intro-paragraph/config.yaml | 31 +- .../intro-paragraph/language/labels.xlf | 0 .../templates/backend-preview.html | 4 +- .../intro-paragraph/templates/frontend.html | 0 .../ContentElements/video/assets/icon.svg | 0 .../ContentElements/video/config.yaml | 31 +- .../ContentElements/video/language/labels.xlf | 0 .../video/templates/backend-preview.html | 4 +- .../video/templates/frontend.html | 0 .../Headless-JSON-Architecture.md | 619 ++++++++++++ .../Private/Language/locallang_buttons.xlf | 0 .../Private/Language/locallang_containers.xlf | 67 ++ .../Private/Language/locallang_pages.xlf | 0 .../Downloadcard/Backendpreview.html | 8 +- .../Backendpreview.html | 6 +- .../Public/Css/backend-container-collapse.css | 22 + .../Resources/Public/Css/backend-preview.css | 0 .../Icons/tx_vitec_domain_model_event.svg | 11 + .../Public/Icons/vitec-cards-carousel.svg | 13 + .../Public/Icons/vitec-cols-25-25-25-25.svg | 0 .../Public/Icons/vitec-cols-33-33-33.svg | 0 .../Public/Icons/vitec-cols-33-66.svg | 0 .../Public/Icons/vitec-cols-50-50.svg | 0 .../Public/Icons/vitec-cols-66-33.svg | 0 .../Public/Icons/vitec-container.svg | 0 .../Public/Icons/vitec-plugin-datasheets.svg | 7 + .../Public/Icons/vitec-plugin-eventlist.svg | 9 + .../Public/Javascript/container-collapse.js | 131 +++ .../Javascript/structured-data-generator.js | 0 packages/vitec/ext_localconf.php | 10 + packages/vitec/ext_tables.sql | 110 ++- public/.htaccess | 13 +- public/_frontend/.htaccess | 17 +- .../assets/VitecDebugToggle-9pp4AW9x.js | 1 - .../assets/VitecDebugToggle-BzU_nymF.js | 1 - .../assets/VitecDebugToggle-C76AUijU.js | 1 + .../assets/VitecDebugToggle-C8gYxgVq.js | 1 - .../assets/VitecDebugToggle-D50ebvSn.js | 1 - .../assets/fa-brands-400-BK5CuonO.woff2 | Bin 0 -> 114412 bytes .../assets/fa-regular-400-WLfxSHV3.woff2 | Bin 0 -> 19480 bytes .../assets/fa-solid-900-Iz_TytpP.woff2 | Bin 0 -> 119156 bytes .../assets/fa-v4compatibility-CMhGCN2W.woff2 | Bin 0 -> 4204 bytes public/_frontend/assets/header-BCPgsUEc.js | 1 - public/_frontend/assets/header-BwD3yTr8.js | 1 + public/_frontend/assets/header-CMkDHNN8.js | 1 - public/_frontend/assets/header-CbcGCvAq.js | 1 - public/_frontend/assets/header-DV30IKp8.js | 1 - public/_frontend/assets/index-7LYai_r-.js | 148 +++ public/_frontend/assets/index-BI31wk8i.js | 121 --- public/_frontend/assets/index-BXbyImyv.js | 121 --- public/_frontend/assets/index-C2f_wFri.css | 1 - public/_frontend/assets/index-CQZZ8YAR.css | 1 + public/_frontend/assets/index-Cq4vmvLV.js | 121 --- public/_frontend/assets/index-DSSM3bkw.css | 1 - public/_frontend/assets/index-jouuqNaB.js | 121 --- public/_frontend/assets/index-lpUAu6vv.css | 1 - ....min-Df29-9GY.js => jszip.min-B_jfdBDa.js} | 2 +- public/_frontend/assets/jszip.min-CXx7QQuN.js | 2 - public/_frontend/assets/jszip.min-DwEIuiR-.js | 2 - public/_frontend/assets/jszip.min-PsHYDUlW.js | 2 - public/_frontend/assets/text-BJeSE9y2.js | 1 - public/_frontend/assets/text-C_qxRHF2.js | 1 + public/_frontend/assets/text-DC_eQsul.js | 1 - public/_frontend/assets/text-Dp3AIh-4.js | 1 - public/_frontend/assets/text-Dq9lSgUc.js | 1 - public/_frontend/assets/textpic-BPDk9WiS.js | 1 - public/_frontend/assets/textpic-B_cm494c.js | 1 + public/_frontend/assets/textpic-C5BEsMbL.js | 1 - public/_frontend/assets/textpic-C_Bm3Pra.js | 1 - public/_frontend/assets/textpic-MhQPwqZV.js | 1 - .../assets/useControlled-OB0I4oAK.js | 1 + .../_frontend/assets/vitec_card-BeOiYQ4P.js | 1 - .../_frontend/assets/vitec_card-ChowkB3a.js | 1 - .../_frontend/assets/vitec_card-D8OSg1v2.js | 1 - .../_frontend/assets/vitec_card-DvvsWZfb.js | 1 - .../_frontend/assets/vitec_card-O7eqyfXI.js | 1 + .../assets/vitec_cards_carousel-DEMyg8kG.js | 1 + .../_frontend/assets/vitec_cols-2cWKAEap.js | 1 - .../_frontend/assets/vitec_cols-BLma67dc.js | 1 + .../_frontend/assets/vitec_cols-BVGaK0W-.js | 1 - .../_frontend/assets/vitec_cols-D2y4u0OF.js | 1 - .../_frontend/assets/vitec_cols-PU_VyQ7B.js | 1 - .../assets/vitec_container-B2PT_nmh.js | 1 - .../assets/vitec_container-CekQ-Tqd.js | 1 + .../assets/vitec_container-CjsIqmJl.js | 1 - .../assets/vitec_container-D_UF3jTW.js | 1 - .../assets/vitec_container-DxJb8k2z.js | 1 - .../assets/vitec_ctabanner-9hTz9dda.js | 1 - .../assets/vitec_ctabanner-BSc8V7mB.js | 1 + .../assets/vitec_ctabanner-BVGHlOTR.js | 1 - .../assets/vitec_ctabanner-CR41er8v.js | 1 - .../assets/vitec_ctabanner-z2lMbSUf.js | 1 - .../assets/vitec_datasheets-BiCTxfiq.js | 1 - .../assets/vitec_datasheets-Bu643D_W.js | 1 + .../assets/vitec_datasheets-CGEIbvsG.js | 1 - .../assets/vitec_datasheets-CLQYzRk1.js | 1 - .../assets/vitec_datasheets-Chy9IC_0.js | 1 - ...-BW1eXCSB.js => vitec_divider--SH2uqZD.js} | 2 +- .../assets/vitec_divider-CRGjdIHI.js | 1 - .../assets/vitec_divider-DFrVEpj4.js | 1 - .../assets/vitec_divider-DdhJi7h4.js | 1 - .../assets/vitec_downloadcard-BW8Vi_bS.js | 1 - .../assets/vitec_downloadcard-DEEmKBX9.js | 1 - ...LmJY.js => vitec_downloadcard-DZEXBeIZ.js} | 2 +- .../assets/vitec_downloadcard-VJxl82jk.js | 1 - .../vitec_downloadcardcollection-7D90DISQ.js | 1 + .../vitec_downloadcardcollection-Bw2XmxMX.js | 1 - .../vitec_downloadcardcollection-CPiNsMSZ.js | 1 - .../vitec_downloadcardcollection-OugWP7GR.js | 1 - .../vitec_downloadcardcollection-htwkZy4M.js | 1 - .../assets/vitec_eventlist-Do7dy7ug.js | 1 + public/_frontend/assets/vitec_faq-Bii0IQAm.js | 1 + .../assets/vitec_herosection-BP18eN1V.js | 1 - .../assets/vitec_herosection-CEdPd8Wl.js | 1 + .../assets/vitec_herosection-CfBguiN2.js | 1 - .../assets/vitec_herosection-DE8AnNdt.js | 1 - .../assets/vitec_herosection-dC77VTJ6.js | 1 - .../assets/vitec_introparagraph-BDH05wxR.js | 1 + .../assets/vitec_introparagraph-CofMtcTJ.js | 1 - .../assets/vitec_introparagraph-DBYpkACd.js | 1 - .../assets/vitec_introparagraph-DwJBlymb.js | 1 - .../assets/vitec_introparagraph-TGdmmr1P.js | 1 - .../assets/vitec_marketshow-BsWkUOPg.js | 1 - .../assets/vitec_marketshow-DdayTTQJ.js | 1 - .../assets/vitec_marketshow-DgggxTO_.js | 1 - ...sBoPN9.js => vitec_marketshow-euGpFALW.js} | 2 +- .../assets/vitec_productlist-83Xx5YeO.js | 1 - .../assets/vitec_productlist-BBvL1vVG.js | 1 + .../assets/vitec_productlist-Blnqx60b.js | 1 - .../assets/vitec_productlist-DlfIGFmO.js | 1 - .../assets/vitec_productlist-dVtXtUJt.js | 1 - .../assets/vitec_productshow-BFboxFcg.js | 1 - .../assets/vitec_productshow-CFG_m23a.js | 1 + .../assets/vitec_productshow-CV7IOthg.js | 1 - .../assets/vitec_productshow-Cf1HHiJg.js | 1 - .../assets/vitec_productshow-rBnXkhEE.js | 1 - .../assets/vitec_usecaseshow-B8AiH3X6.js | 1 + .../assets/vitec_usecaseshow-BJLsYJVo.js | 1 - .../assets/vitec_usecaseshow-CclIdchx.js | 1 - .../assets/vitec_usecaseshow-DoFLUQZ8.js | 1 - .../assets/vitec_usecaseshow-DuYn_ml6.js | 1 - ...eo-8BP8QnbS.js => vitec_video-1ZivpgZw.js} | 2 +- .../_frontend/assets/vitec_video-BdZpN8Ss.js | 1 - .../_frontend/assets/vitec_video-CvNYBDRQ.js | 1 - .../_frontend/assets/vitec_video-nSTDKcwT.js | 1 - public/_frontend/index.html | 7 +- public/collateral-fallback.php | 140 +++ 237 files changed, 6698 insertions(+), 1749 deletions(-) create mode 100644 fix-asset-perms.sh mode change 100755 => 100644 packages/vitec/Classes/Backend/FormEngine/StructuredDataGeneratorWizard.php mode change 100755 => 100644 packages/vitec/Classes/Controller/Backend/StructuredDataController.php create mode 100644 packages/vitec/Classes/Controller/EventController.php mode change 100755 => 100644 packages/vitec/Classes/DataProcessing/.msys00000000000000004cda359073ead130 mode change 100755 => 100644 packages/vitec/Classes/DataProcessing/.msys00000000000000004dd18ef4cfaf2af9 mode change 100755 => 100644 packages/vitec/Classes/DataProcessing/ContainerChildrenProcessor.php create mode 100644 packages/vitec/Classes/Domain/Model/Event.php mode change 100755 => 100644 packages/vitec/Classes/Domain/Model/Product.php create mode 100644 packages/vitec/Classes/Domain/Repository/EventRepository.php create mode 100644 packages/vitec/Classes/EventListener/LoadContainerCollapseAssets.php mode change 100755 => 100644 packages/vitec/Classes/EventListener/ShowFrontendLayoutBanner.php mode change 100755 => 100644 packages/vitec/Classes/Hook/SyncBackendLayoutHook.php mode change 100755 => 100644 packages/vitec/Classes/Service/.msys00000000000000002272de42bf87f8e5 mode change 100755 => 100644 packages/vitec/Classes/Service/.msys0000000000000000274fb505bf117200 mode change 100755 => 100644 packages/vitec/Classes/Service/.msys00000000000000002751b67b19a9c636 mode change 100755 => 100644 packages/vitec/Classes/Service/.msys00000000000000002752b73c4a27d4ba mode change 100755 => 100644 packages/vitec/Classes/Service/.msys00000000000000002753b7f777b58735 mode change 100755 => 100644 packages/vitec/Classes/Service/.msys00000000000000002753b7f978b2a67b mode change 100755 => 100644 packages/vitec/Classes/Service/.msys0000000000000000284b115dd4770044 mode change 100755 => 100644 packages/vitec/Classes/Service/ContentElementResolver.php mode change 100755 => 100644 packages/vitec/Classes/Service/StructuredDataService.php create mode 100644 packages/vitec/Classes/Service/UsecaseSerializer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/DatasheetsJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/DownloadcardJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/DownloadcardcollectionJsonRenderer.php create mode 100644 packages/vitec/Classes/UserFunc/EventlistJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/MarketShowJsonRenderer.php create mode 100644 packages/vitec/Classes/UserFunc/NewsJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/PageJsonLdRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/ProductShowJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/SolutionShowJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/UsecaseListJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/UserFunc/UsecaseShowJsonRenderer.php mode change 100755 => 100644 packages/vitec/Classes/View/BackendLayoutDataProvider.php mode change 100755 => 100644 packages/vitec/Classes/View/VitecBackendLayoutView.php mode change 100755 => 100644 packages/vitec/Configuration/Backend/AjaxRoutes.php create mode 100644 packages/vitec/Configuration/FlexForms/CardsCarousel.xml mode change 100755 => 100644 packages/vitec/Configuration/FlexForms/Container.xml mode change 100755 => 100644 packages/vitec/Configuration/FlexForms/Downloadcard.xml create mode 100644 packages/vitec/Configuration/FlexForms/Eventlist.xml mode change 100755 => 100644 packages/vitec/Configuration/Icons.php mode change 100755 => 100644 packages/vitec/Configuration/JavaScriptModules.php mode change 100755 => 100644 packages/vitec/Configuration/Sets/Vitecset/config.yaml mode change 100755 => 100644 packages/vitec/Configuration/Sets/Vitecset/setup.typoscript mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/pages.php create mode 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cards_carousel.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_25_25_25_25.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_33_33.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_66.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_50_50.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_66_33.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_container.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_shared.php create mode 100644 packages/vitec/Configuration/TCA/tx_vitec_domain_model_event.php mode change 100755 => 100644 packages/vitec/Configuration/TCA/tx_vitec_domain_model_product.php mode change 100755 => 100644 packages/vitec/Configuration/TypoScript/Headless/vitec_containers.typoscript mode change 100755 => 100644 packages/vitec/Configuration/TypoScript/Headless/vitec_menus.typoscript create mode 100644 packages/vitec/Configuration/TypoScript/Headless/vitec_news.typoscript mode change 100755 => 100644 packages/vitec/Configuration/page.tsconfig mode change 100755 => 100644 packages/vitec/ContentBlocks/Basics/ButtonStyle.yaml mode change 100755 => 100644 packages/vitec/ContentBlocks/Basics/SecondaryButtonStyle.yaml mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/card/assets/icon.svg mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/card/config.yaml mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/card/language/labels.xlf mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/card/templates/backend-preview.html mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/card/templates/frontend.html create mode 100644 packages/vitec/ContentBlocks/ContentElements/columns/assets/icon.svg create mode 100644 packages/vitec/ContentBlocks/ContentElements/columns/config.yaml create mode 100644 packages/vitec/ContentBlocks/ContentElements/columns/language/labels.xlf create mode 100644 packages/vitec/ContentBlocks/ContentElements/columns/templates/backend-preview.html create mode 100644 packages/vitec/ContentBlocks/ContentElements/columns/templates/frontend.html mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/cta-banner/config.yaml create mode 100644 packages/vitec/ContentBlocks/ContentElements/faq/assets/icon.svg create mode 100644 packages/vitec/ContentBlocks/ContentElements/faq/config.yaml create mode 100644 packages/vitec/ContentBlocks/ContentElements/faq/language/labels.xlf create mode 100644 packages/vitec/ContentBlocks/ContentElements/faq/templates/backend-preview.html create mode 100644 packages/vitec/ContentBlocks/ContentElements/faq/templates/frontend.html mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/hero-section/config.yaml mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/hero-section/language/labels.xlf mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/intro-paragraph/assets/icon.svg mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/intro-paragraph/config.yaml mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/intro-paragraph/language/labels.xlf mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/backend-preview.html mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/frontend.html mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/video/assets/icon.svg mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/video/config.yaml mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/video/language/labels.xlf mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/video/templates/backend-preview.html mode change 100755 => 100644 packages/vitec/ContentBlocks/ContentElements/video/templates/frontend.html create mode 100644 packages/vitec/Documentation/Headless-JSON-Architecture.md mode change 100755 => 100644 packages/vitec/Resources/Private/Language/locallang_buttons.xlf mode change 100755 => 100644 packages/vitec/Resources/Private/Language/locallang_containers.xlf mode change 100755 => 100644 packages/vitec/Resources/Private/Language/locallang_pages.xlf mode change 100755 => 100644 packages/vitec/Resources/Private/Templates/Downloadcard/Backendpreview.html mode change 100755 => 100644 packages/vitec/Resources/Private/Templates/Downloadcardcollection/Backendpreview.html create mode 100644 packages/vitec/Resources/Public/Css/backend-container-collapse.css mode change 100755 => 100644 packages/vitec/Resources/Public/Css/backend-preview.css create mode 100644 packages/vitec/Resources/Public/Icons/tx_vitec_domain_model_event.svg create mode 100644 packages/vitec/Resources/Public/Icons/vitec-cards-carousel.svg mode change 100755 => 100644 packages/vitec/Resources/Public/Icons/vitec-cols-25-25-25-25.svg mode change 100755 => 100644 packages/vitec/Resources/Public/Icons/vitec-cols-33-33-33.svg mode change 100755 => 100644 packages/vitec/Resources/Public/Icons/vitec-cols-33-66.svg mode change 100755 => 100644 packages/vitec/Resources/Public/Icons/vitec-cols-50-50.svg mode change 100755 => 100644 packages/vitec/Resources/Public/Icons/vitec-cols-66-33.svg mode change 100755 => 100644 packages/vitec/Resources/Public/Icons/vitec-container.svg create mode 100644 packages/vitec/Resources/Public/Icons/vitec-plugin-datasheets.svg create mode 100644 packages/vitec/Resources/Public/Icons/vitec-plugin-eventlist.svg create mode 100644 packages/vitec/Resources/Public/Javascript/container-collapse.js mode change 100755 => 100644 packages/vitec/Resources/Public/Javascript/structured-data-generator.js mode change 100755 => 100644 packages/vitec/ext_localconf.php mode change 100755 => 100644 packages/vitec/ext_tables.sql delete mode 100644 public/_frontend/assets/VitecDebugToggle-9pp4AW9x.js delete mode 100644 public/_frontend/assets/VitecDebugToggle-BzU_nymF.js create mode 100644 public/_frontend/assets/VitecDebugToggle-C76AUijU.js delete mode 100644 public/_frontend/assets/VitecDebugToggle-C8gYxgVq.js delete mode 100644 public/_frontend/assets/VitecDebugToggle-D50ebvSn.js create mode 100644 public/_frontend/assets/fa-brands-400-BK5CuonO.woff2 create mode 100644 public/_frontend/assets/fa-regular-400-WLfxSHV3.woff2 create mode 100644 public/_frontend/assets/fa-solid-900-Iz_TytpP.woff2 create mode 100644 public/_frontend/assets/fa-v4compatibility-CMhGCN2W.woff2 delete mode 100644 public/_frontend/assets/header-BCPgsUEc.js create mode 100644 public/_frontend/assets/header-BwD3yTr8.js delete mode 100644 public/_frontend/assets/header-CMkDHNN8.js delete mode 100644 public/_frontend/assets/header-CbcGCvAq.js delete mode 100644 public/_frontend/assets/header-DV30IKp8.js create mode 100644 public/_frontend/assets/index-7LYai_r-.js delete mode 100644 public/_frontend/assets/index-BI31wk8i.js delete mode 100644 public/_frontend/assets/index-BXbyImyv.js delete mode 100644 public/_frontend/assets/index-C2f_wFri.css create mode 100644 public/_frontend/assets/index-CQZZ8YAR.css delete mode 100644 public/_frontend/assets/index-Cq4vmvLV.js delete mode 100644 public/_frontend/assets/index-DSSM3bkw.css delete mode 100644 public/_frontend/assets/index-jouuqNaB.js delete mode 100644 public/_frontend/assets/index-lpUAu6vv.css rename public/_frontend/assets/{jszip.min-Df29-9GY.js => jszip.min-B_jfdBDa.js} (93%) delete mode 100644 public/_frontend/assets/jszip.min-CXx7QQuN.js delete mode 100644 public/_frontend/assets/jszip.min-DwEIuiR-.js delete mode 100644 public/_frontend/assets/jszip.min-PsHYDUlW.js delete mode 100644 public/_frontend/assets/text-BJeSE9y2.js create mode 100644 public/_frontend/assets/text-C_qxRHF2.js delete mode 100644 public/_frontend/assets/text-DC_eQsul.js delete mode 100644 public/_frontend/assets/text-Dp3AIh-4.js delete mode 100644 public/_frontend/assets/text-Dq9lSgUc.js delete mode 100644 public/_frontend/assets/textpic-BPDk9WiS.js create mode 100644 public/_frontend/assets/textpic-B_cm494c.js delete mode 100644 public/_frontend/assets/textpic-C5BEsMbL.js delete mode 100644 public/_frontend/assets/textpic-C_Bm3Pra.js delete mode 100644 public/_frontend/assets/textpic-MhQPwqZV.js create mode 100644 public/_frontend/assets/useControlled-OB0I4oAK.js delete mode 100644 public/_frontend/assets/vitec_card-BeOiYQ4P.js delete mode 100644 public/_frontend/assets/vitec_card-ChowkB3a.js delete mode 100644 public/_frontend/assets/vitec_card-D8OSg1v2.js delete mode 100644 public/_frontend/assets/vitec_card-DvvsWZfb.js create mode 100644 public/_frontend/assets/vitec_card-O7eqyfXI.js create mode 100644 public/_frontend/assets/vitec_cards_carousel-DEMyg8kG.js delete mode 100644 public/_frontend/assets/vitec_cols-2cWKAEap.js create mode 100644 public/_frontend/assets/vitec_cols-BLma67dc.js delete mode 100644 public/_frontend/assets/vitec_cols-BVGaK0W-.js delete mode 100644 public/_frontend/assets/vitec_cols-D2y4u0OF.js delete mode 100644 public/_frontend/assets/vitec_cols-PU_VyQ7B.js delete mode 100644 public/_frontend/assets/vitec_container-B2PT_nmh.js create mode 100644 public/_frontend/assets/vitec_container-CekQ-Tqd.js delete mode 100644 public/_frontend/assets/vitec_container-CjsIqmJl.js delete mode 100644 public/_frontend/assets/vitec_container-D_UF3jTW.js delete mode 100644 public/_frontend/assets/vitec_container-DxJb8k2z.js delete mode 100644 public/_frontend/assets/vitec_ctabanner-9hTz9dda.js create mode 100644 public/_frontend/assets/vitec_ctabanner-BSc8V7mB.js delete mode 100644 public/_frontend/assets/vitec_ctabanner-BVGHlOTR.js delete mode 100644 public/_frontend/assets/vitec_ctabanner-CR41er8v.js delete mode 100644 public/_frontend/assets/vitec_ctabanner-z2lMbSUf.js delete mode 100644 public/_frontend/assets/vitec_datasheets-BiCTxfiq.js create mode 100644 public/_frontend/assets/vitec_datasheets-Bu643D_W.js delete mode 100644 public/_frontend/assets/vitec_datasheets-CGEIbvsG.js delete mode 100644 public/_frontend/assets/vitec_datasheets-CLQYzRk1.js delete mode 100644 public/_frontend/assets/vitec_datasheets-Chy9IC_0.js rename public/_frontend/assets/{vitec_divider-BW1eXCSB.js => vitec_divider--SH2uqZD.js} (81%) delete mode 100644 public/_frontend/assets/vitec_divider-CRGjdIHI.js delete mode 100644 public/_frontend/assets/vitec_divider-DFrVEpj4.js delete mode 100644 public/_frontend/assets/vitec_divider-DdhJi7h4.js delete mode 100644 public/_frontend/assets/vitec_downloadcard-BW8Vi_bS.js delete mode 100644 public/_frontend/assets/vitec_downloadcard-DEEmKBX9.js rename public/_frontend/assets/{vitec_downloadcard-B1bJLmJY.js => vitec_downloadcard-DZEXBeIZ.js} (67%) delete mode 100644 public/_frontend/assets/vitec_downloadcard-VJxl82jk.js create mode 100644 public/_frontend/assets/vitec_downloadcardcollection-7D90DISQ.js delete mode 100644 public/_frontend/assets/vitec_downloadcardcollection-Bw2XmxMX.js delete mode 100644 public/_frontend/assets/vitec_downloadcardcollection-CPiNsMSZ.js delete mode 100644 public/_frontend/assets/vitec_downloadcardcollection-OugWP7GR.js delete mode 100644 public/_frontend/assets/vitec_downloadcardcollection-htwkZy4M.js create mode 100644 public/_frontend/assets/vitec_eventlist-Do7dy7ug.js create mode 100644 public/_frontend/assets/vitec_faq-Bii0IQAm.js delete mode 100644 public/_frontend/assets/vitec_herosection-BP18eN1V.js create mode 100644 public/_frontend/assets/vitec_herosection-CEdPd8Wl.js delete mode 100644 public/_frontend/assets/vitec_herosection-CfBguiN2.js delete mode 100644 public/_frontend/assets/vitec_herosection-DE8AnNdt.js delete mode 100644 public/_frontend/assets/vitec_herosection-dC77VTJ6.js create mode 100644 public/_frontend/assets/vitec_introparagraph-BDH05wxR.js delete mode 100644 public/_frontend/assets/vitec_introparagraph-CofMtcTJ.js delete mode 100644 public/_frontend/assets/vitec_introparagraph-DBYpkACd.js delete mode 100644 public/_frontend/assets/vitec_introparagraph-DwJBlymb.js delete mode 100644 public/_frontend/assets/vitec_introparagraph-TGdmmr1P.js delete mode 100644 public/_frontend/assets/vitec_marketshow-BsWkUOPg.js delete mode 100644 public/_frontend/assets/vitec_marketshow-DdayTTQJ.js delete mode 100644 public/_frontend/assets/vitec_marketshow-DgggxTO_.js rename public/_frontend/assets/{vitec_marketshow-BRsBoPN9.js => vitec_marketshow-euGpFALW.js} (50%) delete mode 100644 public/_frontend/assets/vitec_productlist-83Xx5YeO.js create mode 100644 public/_frontend/assets/vitec_productlist-BBvL1vVG.js delete mode 100644 public/_frontend/assets/vitec_productlist-Blnqx60b.js delete mode 100644 public/_frontend/assets/vitec_productlist-DlfIGFmO.js delete mode 100644 public/_frontend/assets/vitec_productlist-dVtXtUJt.js delete mode 100644 public/_frontend/assets/vitec_productshow-BFboxFcg.js create mode 100644 public/_frontend/assets/vitec_productshow-CFG_m23a.js delete mode 100644 public/_frontend/assets/vitec_productshow-CV7IOthg.js delete mode 100644 public/_frontend/assets/vitec_productshow-Cf1HHiJg.js delete mode 100644 public/_frontend/assets/vitec_productshow-rBnXkhEE.js create mode 100644 public/_frontend/assets/vitec_usecaseshow-B8AiH3X6.js delete mode 100644 public/_frontend/assets/vitec_usecaseshow-BJLsYJVo.js delete mode 100644 public/_frontend/assets/vitec_usecaseshow-CclIdchx.js delete mode 100644 public/_frontend/assets/vitec_usecaseshow-DoFLUQZ8.js delete mode 100644 public/_frontend/assets/vitec_usecaseshow-DuYn_ml6.js rename public/_frontend/assets/{vitec_video-8BP8QnbS.js => vitec_video-1ZivpgZw.js} (57%) delete mode 100644 public/_frontend/assets/vitec_video-BdZpN8Ss.js delete mode 100644 public/_frontend/assets/vitec_video-CvNYBDRQ.js delete mode 100644 public/_frontend/assets/vitec_video-nSTDKcwT.js create mode 100644 public/collateral-fallback.php diff --git a/composer.json b/composer.json index 2651f9a..d2c3cac 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,7 @@ "evomedien/vitec": "^1.0.1", "friendsoftypo3/content-blocks": "^2.4", "friendsoftypo3/headless": "^5.0@rc", + "georgringer/news": "^14.0", "netzbewegung/nb-headless-content-blocks": "^0.0.23", "typo3/cms-backend": "^14.3", "typo3/cms-belog": "^14.3", diff --git a/composer.lock b/composer.lock index e454b71..6f3a6e5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1b855a4234befa546bf9280aa9536303", + "content-hash": "894f07b60885efbdf0a5979a6879e631", "packages": [ { "name": "b13/container", @@ -364,16 +364,16 @@ }, { "name": "composer/composer", - "version": "2.10.1", + "version": "2.10.2", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "4120703b9bda8795075047b40361d7ec4d2abe49" + "reference": "8d4439f572a97670a9edc039eb3b093cc976b4bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/4120703b9bda8795075047b40361d7ec4d2abe49", - "reference": "4120703b9bda8795075047b40361d7ec4d2abe49", + "url": "https://api.github.com/repos/composer/composer/zipball/8d4439f572a97670a9edc039eb3b093cc976b4bc", + "reference": "8d4439f572a97670a9edc039eb3b093cc976b4bc", "shasum": "" }, "require": { @@ -461,7 +461,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.10.1" + "source": "https://github.com/composer/composer/tree/2.10.2" }, "funding": [ { @@ -473,20 +473,20 @@ "type": "github" } ], - "time": "2026-06-04T08:25:59+00:00" + "time": "2026-07-01T09:24:45+00:00" }, { "name": "composer/metadata-minifier", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/composer/metadata-minifier.git", - "reference": "c549d23829536f0d0e984aaabbf02af91f443207" + "reference": "8e86142e3ade750b837d55e55f0cdc786d8da006" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", - "reference": "c549d23829536f0d0e984aaabbf02af91f443207", + "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/8e86142e3ade750b837d55e55f0cdc786d8da006", + "reference": "8e86142e3ade750b837d55e55f0cdc786d8da006", "shasum": "" }, "require": { @@ -494,8 +494,8 @@ }, "require-dev": { "composer/composer": "^2", - "phpstan/phpstan": "^0.12.55", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^1", + "symfony/phpunit-bridge": "^4.2 || ^5 || ^6 || ^7" }, "type": "library", "extra": { @@ -526,7 +526,7 @@ ], "support": { "issues": "https://github.com/composer/metadata-minifier/issues", - "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" + "source": "https://github.com/composer/metadata-minifier/tree/1.0.1" }, "funding": [ { @@ -536,38 +536,35 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2021-04-07T13:37:33+00:00" + "time": "2026-06-30T11:34:59+00:00" }, { "name": "composer/pcre", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed", + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, "conflict": { - "phpstan/phpstan": "<1.11.10" + "phpstan/phpstan": "<2.2.2" }, "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^9" }, "type": "library", "extra": { @@ -605,7 +602,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" + "source": "https://github.com/composer/pcre/tree/3.4.0" }, "funding": [ { @@ -615,13 +612,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-11-12T16:29:46+00:00" + "time": "2026-06-07T11:47:49+00:00" }, { "name": "composer/semver", @@ -1345,16 +1338,16 @@ }, { "name": "firebase/php-jwt", - "version": "v7.0.5", + "version": "v7.1.0", "source": { "type": "git", "url": "https://github.com/googleapis/php-jwt.git", - "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" + "reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", - "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/b374a5d1a4f1f67fadc2165cdb284645945e2fc0", + "reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0", "shasum": "" }, "require": { @@ -1363,6 +1356,7 @@ "require-dev": { "guzzlehttp/guzzle": "^7.4", "phpfastcache/phpfastcache": "^9.2", + "phpseclib/phpseclib": "~3.0", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", @@ -1371,7 +1365,8 @@ }, "suggest": { "ext-sodium": "Support EdDSA (Ed25519) signatures", - "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present", + "phpseclib/phpseclib": "Support PS256 (RSASSA-PSS) signatures" }, "type": "library", "autoload": { @@ -1396,29 +1391,29 @@ } ], "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", + "homepage": "https://github.com/googleapis/php-jwt", "keywords": [ "jwt", "php" ], "support": { "issues": "https://github.com/googleapis/php-jwt/issues", - "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" + "source": "https://github.com/googleapis/php-jwt/tree/v7.1.0" }, - "time": "2026-04-01T20:38:03+00:00" + "time": "2026-06-11T17:54:14+00:00" }, { "name": "friendsoftypo3/content-blocks", - "version": "2.4.5", + "version": "2.4.7", "source": { "type": "git", "url": "https://github.com/FriendsOfTYPO3/content-blocks.git", - "reference": "6e82652bc653b98aabd4fc60211286c40c8abe75" + "reference": "9f2b13b5f605cd6576b9a1dec10b559c59af3c66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfTYPO3/content-blocks/zipball/6e82652bc653b98aabd4fc60211286c40c8abe75", - "reference": "6e82652bc653b98aabd4fc60211286c40c8abe75", + "url": "https://api.github.com/repos/FriendsOfTYPO3/content-blocks/zipball/9f2b13b5f605cd6576b9a1dec10b559c59af3c66", + "reference": "9f2b13b5f605cd6576b9a1dec10b559c59af3c66", "shasum": "" }, "require": { @@ -1465,7 +1460,7 @@ "symfony/var-exporter": "" } }, - "version": "2.4.5", + "version": "2.4.7", "web-dir": ".Build/public", "extension-key": "content_blocks" } @@ -1494,7 +1489,7 @@ "issues": "https://github.com/FriendsOfTYPO3/content-blocks/issues", "source": "https://github.com/FriendsOfTYPO3/content-blocks" }, - "time": "2026-06-04T16:27:24+00:00" + "time": "2026-06-25T15:33:34+00:00" }, { "name": "friendsoftypo3/headless", @@ -1585,27 +1580,132 @@ "time": "2026-05-08T15:09:37+00:00" }, { - "name": "guzzlehttp/guzzle", - "version": "7.11.0", + "name": "georgringer/news", + "version": "14.0.3", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "c987f8ce84b8434fa430795eca0f3430663da72b" + "url": "https://github.com/georgringer/news.git", + "reference": "cec1cd776a32e5cec527575b97ca7b044ceac19c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/c987f8ce84b8434fa430795eca0f3430663da72b", - "reference": "c987f8ce84b8434fa430795eca0f3430663da72b", + "url": "https://api.github.com/repos/georgringer/news/zipball/cec1cd776a32e5cec527575b97ca7b044ceac19c", + "reference": "cec1cd776a32e5cec527575b97ca7b044ceac19c", + "shasum": "" + }, + "require": { + "php": ">= 8.2 < 8.6", + "symfony/console": "^5.4 || ^6.4 || ^7.0", + "typo3/cms-backend": "^13.4.20 || ^14.0", + "typo3/cms-core": "^13.4.20 || ^14.0", + "typo3/cms-extbase": "^13.4.20 || ^14.0", + "typo3/cms-fluid": "^13.4.20 || ^14.0", + "typo3/cms-frontend": "^13.4.20 || ^14.0", + "typo3/cms-install": "^13.4.20 || ^14.0" + }, + "conflict": { + "sebastian/recursion-context": "6.0.0 || 6.0.1 || 6.0.2" + }, + "replace": { + "typo3-ter/news": "self.version" + }, + "require-dev": { + "a9f/typo3-fractor": "@dev", + "friendsofphp/php-cs-fixer": "^3.89.2", + "phpstan/phpdoc-parser": "^1.33.0", + "phpunit/phpunit": "^10.5.58", + "ssch/typo3-rector": "^3.7", + "typo3/cms-seo": "^13.4.20 || ^14.0", + "typo3/coding-standards": "^0.8.0", + "typo3/testing-framework": "^8.3.1", + "webmozart/assert": "^1.12.1" + }, + "suggest": { + "georgringer/news-tagsuggest": "On the fly creation of tag records within a news record", + "georgringer/numbered-pagination": "Improved pagination API", + "reelworx/rx-shariff": "GDPR compliant social sharing", + "typo3/cms-scheduler": "XML and ICS import", + "typo3/cms-seo": "Sitemaps" + }, + "type": "typo3-cms-extension", + "extra": { + "typo3/cms": { + "app-dir": ".Build", + "web-dir": ".Build/Web", + "extension-key": "news" + } + }, + "autoload": { + "psr-4": { + "GeorgRinger\\News\\": "Classes" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Georg Ringer", + "homepage": "https://ringer.it", + "role": "Developer" + } + ], + "description": "News system - Versatile news system based on Extbase & Fluid and using the latest technologies provided by TYPO3 CMS.", + "homepage": "https://extensions.typo3.org/extension/news", + "keywords": [ + "article", + "extension", + "news", + "typo3" + ], + "support": { + "docs": "https://docs.typo3.org/p/georgringer/news/main/en-us/", + "issues": "https://github.com/georgringer/news/issues", + "source": "https://github.com/georgringer/news" + }, + "funding": [ + { + "url": "https://paypal.me/GeorgRinger/10", + "type": "custom" + }, + { + "url": "https://www.amazon.de/hz/wishlist/ls/8F573K08TSDG", + "type": "custom" + }, + { + "url": "https://github.com/georgringer", + "type": "github" + }, + { + "url": "https://www.patreon.com/georgringer", + "type": "patreon" + } + ], + "time": "2026-05-18T20:53:26+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.13.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "bcd989ad36c92d42a3715379af91f2defee5b8dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/bcd989ad36c92d42a3715379af91f2defee5b8dd", + "reference": "bcd989ad36c92d42a3715379af91f2defee5b8dd", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^2.5", - "guzzlehttp/psr7": "^2.11", + "guzzlehttp/psr7": "^2.12.3", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/polyfill-php80": "^1.24" + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-client-implementation": "1.0" @@ -1613,8 +1713,8 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "guzzle/client-integration-tests": "3.0.2", - "guzzlehttp/test-server": "^0.4", + "guzzle/client-integration-tests": "3.0.3", + "guzzlehttp/test-server": "^0.6", "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" @@ -1694,7 +1794,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.11.0" + "source": "https://github.com/guzzle/guzzle/tree/7.13.2" }, "funding": [ { @@ -1710,7 +1810,7 @@ "type": "tidelift" } ], - "time": "2026-06-02T12:40:51+00:00" + "time": "2026-07-05T19:00:11+00:00" }, { "name": "guzzlehttp/promises", @@ -1798,16 +1898,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.11.0", + "version": "2.12.3", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f" + "reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/bbb5e61349fa5cb822b3e87842b951088b76b81f", - "reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7ec62dc3f44aa218487dbed81a9bf9bc647be55d", + "reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d", "shasum": "" }, "require": { @@ -1816,7 +1916,7 @@ "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/polyfill-php80": "^1.24" + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-factory-implementation": "1.0", @@ -1897,7 +1997,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.11.0" + "source": "https://github.com/guzzle/psr7/tree/2.12.3" }, "funding": [ { @@ -1913,20 +2013,20 @@ "type": "tidelift" } ], - "time": "2026-06-02T12:30:48+00:00" + "time": "2026-06-23T15:21:08+00:00" }, { "name": "justinrainbow/json-schema", - "version": "6.8.2", + "version": "6.10.0", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "2c89ebb95ca9cedc9347f780333f7b25792dcb76" + "reference": "8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/2c89ebb95ca9cedc9347f780333f7b25792dcb76", - "reference": "2c89ebb95ca9cedc9347f780333f7b25792dcb76", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33", + "reference": "8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33", "shasum": "" }, "require": { @@ -1986,9 +2086,9 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/6.8.2" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.10.0" }, - "time": "2026-05-05T05:39:01+00:00" + "time": "2026-06-16T20:50:26+00:00" }, { "name": "lolli42/finediff", @@ -2130,16 +2230,16 @@ }, { "name": "masterminds/html5", - "version": "2.10.0", + "version": "2.10.1", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "fcf91eb64359852f00d921887b219479b4f21251" + "reference": "fd5018f6815fff903946d0564977b44ce8010e29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", - "reference": "fcf91eb64359852f00d921887b219479b4f21251", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fd5018f6815fff903946d0564977b44ce8010e29", + "reference": "fd5018f6815fff903946d0564977b44ce8010e29", "shasum": "" }, "require": { @@ -2147,7 +2247,7 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9 || ^10" }, "type": "library", "extra": { @@ -2191,9 +2291,9 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" + "source": "https://github.com/Masterminds/html5-php/tree/2.10.1" }, - "time": "2025-07-25T09:04:22+00:00" + "time": "2026-06-23T18:43:15+00:00" }, { "name": "netzbewegung/nb-headless-content-blocks", @@ -2266,20 +2366,19 @@ }, { "name": "nikic/php-parser", - "version": "v5.7.0", + "version": "v5.8.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f", + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" @@ -2318,9 +2417,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0" }, - "time": "2025-12-06T11:56:16+00:00" + "time": "2026-07-04T14:30:18+00:00" }, { "name": "opis/json-schema", @@ -2690,16 +2789,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.2", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", "shasum": "" }, "require": { @@ -2731,9 +2830,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.3" }, - "time": "2026-01-25T14:56:51+00:00" + "time": "2026-07-08T07:01:06+00:00" }, { "name": "psr/cache", @@ -3377,16 +3476,16 @@ }, { "name": "seld/jsonlint", - "version": "1.11.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2" + "reference": "9a90eb5d32d5a500296bf43f946d60246444d5f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2", - "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9a90eb5d32d5a500296bf43f946d60246444d5f7", + "reference": "9a90eb5d32d5a500296bf43f946d60246444d5f7", "shasum": "" }, "require": { @@ -3425,7 +3524,7 @@ ], "support": { "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0" + "source": "https://github.com/Seldaek/jsonlint/tree/1.12.1" }, "funding": [ { @@ -3437,7 +3536,7 @@ "type": "tidelift" } ], - "time": "2024-07-11T14:55:45+00:00" + "time": "2026-06-12T11:32:29+00:00" }, { "name": "seld/phar-utils", @@ -3550,16 +3649,16 @@ }, { "name": "symfony/cache", - "version": "v8.0.13", + "version": "v8.0.14", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "75f92239836ce08bce4d19f2734737dae4276fe9" + "reference": "76ec84217eb39e4787d03928bba86a25cc859f76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/75f92239836ce08bce4d19f2734737dae4276fe9", - "reference": "75f92239836ce08bce4d19f2734737dae4276fe9", + "url": "https://api.github.com/repos/symfony/cache/zipball/76ec84217eb39e4787d03928bba86a25cc859f76", + "reference": "76ec84217eb39e4787d03928bba86a25cc859f76", "shasum": "" }, "require": { @@ -3625,7 +3724,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v8.0.13" + "source": "https://github.com/symfony/cache/tree/v8.0.14" }, "funding": [ { @@ -3645,20 +3744,20 @@ "type": "tidelift" } ], - "time": "2026-05-24T08:44:11+00:00" + "time": "2026-06-17T15:00:27+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "225e8a254166bd3442e370c6f50145465db63831" + "reference": "9789738bc19af1106dc54d6afba9a0b467516cf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/225e8a254166bd3442e370c6f50145465db63831", - "reference": "225e8a254166bd3442e370c6f50145465db63831", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/9789738bc19af1106dc54d6afba9a0b467516cf2", + "reference": "9789738bc19af1106dc54d6afba9a0b467516cf2", "shasum": "" }, "require": { @@ -3705,7 +3804,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.7.1" }, "funding": [ { @@ -3725,7 +3824,7 @@ "type": "tidelift" } ], - "time": "2026-05-05T15:33:14+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/clock", @@ -3806,16 +3905,16 @@ }, { "name": "symfony/config", - "version": "v7.4.10", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57" + "reference": "7b665e443381ea7c4db03eb03b4bf79ea2b020eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57", - "reference": "d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57", + "url": "https://api.github.com/repos/symfony/config/zipball/7b665e443381ea7c4db03eb03b4bf79ea2b020eb", + "reference": "7b665e443381ea7c4db03eb03b4bf79ea2b020eb", "shasum": "" }, "require": { @@ -3861,7 +3960,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.4.10" + "source": "https://github.com/symfony/config/tree/v7.4.14" }, "funding": [ { @@ -3881,20 +3980,20 @@ "type": "tidelift" } ], - "time": "2026-05-03T14:20:49+00:00" + "time": "2026-06-09T07:51:57+00:00" }, { "name": "symfony/console", - "version": "v7.4.13", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217" + "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/85095d2573eaefaf35e40b9513a9bf09f72cd217", - "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217", + "url": "https://api.github.com/repos/symfony/console/zipball/92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87", + "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87", "shasum": "" }, "require": { @@ -3959,7 +4058,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.13" + "source": "https://github.com/symfony/console/tree/v7.4.14" }, "funding": [ { @@ -3979,20 +4078,20 @@ "type": "tidelift" } ], - "time": "2026-05-24T08:56:14+00:00" + "time": "2026-06-16T11:50:14+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.4.13", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f299e20ce983be6c0744952533c6dfeaaa1448e2" + "reference": "2c8c64a33e2e6911579e1ff79a8e06c27d48d402" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f299e20ce983be6c0744952533c6dfeaaa1448e2", - "reference": "f299e20ce983be6c0744952533c6dfeaaa1448e2", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2c8c64a33e2e6911579e1ff79a8e06c27d48d402", + "reference": "2c8c64a33e2e6911579e1ff79a8e06c27d48d402", "shasum": "" }, "require": { @@ -4043,7 +4142,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.4.13" + "source": "https://github.com/symfony/dependency-injection/tree/v7.4.14" }, "funding": [ { @@ -4063,20 +4162,20 @@ "type": "tidelift" } ], - "time": "2026-05-20T14:07:29+00:00" + "time": "2026-06-24T07:41:05+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", - "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", "shasum": "" }, "require": { @@ -4114,7 +4213,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" }, "funding": [ { @@ -4134,20 +4233,20 @@ "type": "tidelift" } ], - "time": "2026-04-13T15:52:40+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/doctrine-messenger", - "version": "v7.4.6", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-messenger.git", - "reference": "a429cd95983eaea2371ea279bed3b8a93b9ecdd3" + "reference": "c29901ea81dff6557ae3c78c0bad1d559500c2d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/a429cd95983eaea2371ea279bed3b8a93b9ecdd3", - "reference": "a429cd95983eaea2371ea279bed3b8a93b9ecdd3", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/c29901ea81dff6557ae3c78c0bad1d559500c2d8", + "reference": "c29901ea81dff6557ae3c78c0bad1d559500c2d8", "shasum": "" }, "require": { @@ -4190,7 +4289,7 @@ "description": "Symfony Doctrine Messenger Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-messenger/tree/v7.4.6" + "source": "https://github.com/symfony/doctrine-messenger/tree/v7.4.14" }, "funding": [ { @@ -4210,20 +4309,20 @@ "type": "tidelift" } ], - "time": "2026-02-18T09:40:04+00:00" + "time": "2026-06-11T07:31:44+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v8.0.9", + "version": "v8.0.14", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f" + "reference": "3973836dd335445d0c622ffe98e418eed304d95b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0c3c1a17604c4dbbec4b93fe162c538482096e1f", - "reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3973836dd335445d0c622ffe98e418eed304d95b", + "reference": "3973836dd335445d0c622ffe98e418eed304d95b", "shasum": "" }, "require": { @@ -4275,7 +4374,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.9" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.14" }, "funding": [ { @@ -4295,20 +4394,20 @@ "type": "tidelift" } ], - "time": "2026-04-18T13:51:42+00:00" + "time": "2026-06-06T11:11:34+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32" + "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32", - "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c7de7a00ffb67842132da02ea92988a39ccd9f4e", + "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e", "shasum": "" }, "require": { @@ -4355,7 +4454,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.1" }, "funding": [ { @@ -4375,20 +4474,20 @@ "type": "tidelift" } ], - "time": "2026-01-05T13:30:16+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/expression-language", - "version": "v7.4.8", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "87ff95687748f4af65e4d5a6e917d448ec52aa83" + "reference": "bd5763f92959201816ecc31defdf352d2ea473be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/87ff95687748f4af65e4d5a6e917d448ec52aa83", - "reference": "87ff95687748f4af65e4d5a6e917d448ec52aa83", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/bd5763f92959201816ecc31defdf352d2ea473be", + "reference": "bd5763f92959201816ecc31defdf352d2ea473be", "shasum": "" }, "require": { @@ -4423,7 +4522,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v7.4.8" + "source": "https://github.com/symfony/expression-language/tree/v7.4.14" }, "funding": [ { @@ -4443,7 +4542,7 @@ "type": "tidelift" } ], - "time": "2026-03-24T13:12:05+00:00" + "time": "2026-06-08T20:24:16+00:00" }, { "name": "symfony/filesystem", @@ -4517,16 +4616,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.8", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "e0be088d22278583a82da281886e8c3592fbf149" + "reference": "13b38720174286f55d1761152b575a8d1436fc25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", - "reference": "e0be088d22278583a82da281886e8c3592fbf149", + "url": "https://api.github.com/repos/symfony/finder/zipball/13b38720174286f55d1761152b575a8d1436fc25", + "reference": "13b38720174286f55d1761152b575a8d1436fc25", "shasum": "" }, "require": { @@ -4561,7 +4660,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.8" + "source": "https://github.com/symfony/finder/tree/v7.4.14" }, "funding": [ { @@ -4581,20 +4680,20 @@ "type": "tidelift" } ], - "time": "2026-03-24T13:12:05+00:00" + "time": "2026-06-27T08:31:18+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.13", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "bc354f47c62301e990b7874fa662326368508e2c" + "reference": "06db5ae1552177bf8572f8908839f12e3c06aed3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bc354f47c62301e990b7874fa662326368508e2c", - "reference": "bc354f47c62301e990b7874fa662326368508e2c", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/06db5ae1552177bf8572f8908839f12e3c06aed3", + "reference": "06db5ae1552177bf8572f8908839f12e3c06aed3", "shasum": "" }, "require": { @@ -4643,7 +4742,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.13" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.14" }, "funding": [ { @@ -4663,20 +4762,20 @@ "type": "tidelift" } ], - "time": "2026-05-24T11:20:33+00:00" + "time": "2026-06-11T07:31:44+00:00" }, { "name": "symfony/mailer", - "version": "v7.4.12", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "5cefb712a25f320579615ba9e1942abaeade7dff" + "reference": "f88ce03ae73e3edb5c176ce1f337709996e88495" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/5cefb712a25f320579615ba9e1942abaeade7dff", - "reference": "5cefb712a25f320579615ba9e1942abaeade7dff", + "url": "https://api.github.com/repos/symfony/mailer/zipball/f88ce03ae73e3edb5c176ce1f337709996e88495", + "reference": "f88ce03ae73e3edb5c176ce1f337709996e88495", "shasum": "" }, "require": { @@ -4727,7 +4826,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.4.12" + "source": "https://github.com/symfony/mailer/tree/v7.4.14" }, "funding": [ { @@ -4747,20 +4846,20 @@ "type": "tidelift" } ], - "time": "2026-05-20T07:20:23+00:00" + "time": "2026-06-13T08:51:35+00:00" }, { "name": "symfony/messenger", - "version": "v7.4.12", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "906387986caecc10b2ad2e85f715d834e5133a04" + "reference": "1ebe448527c77d9efaf2d3205b23707ebaaa28c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/906387986caecc10b2ad2e85f715d834e5133a04", - "reference": "906387986caecc10b2ad2e85f715d834e5133a04", + "url": "https://api.github.com/repos/symfony/messenger/zipball/1ebe448527c77d9efaf2d3205b23707ebaaa28c4", + "reference": "1ebe448527c77d9efaf2d3205b23707ebaaa28c4", "shasum": "" }, "require": { @@ -4821,7 +4920,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.4.12" + "source": "https://github.com/symfony/messenger/tree/v7.4.14" }, "funding": [ { @@ -4841,7 +4940,7 @@ "type": "tidelift" } ], - "time": "2026-05-19T07:02:47+00:00" + "time": "2026-06-08T20:24:16+00:00" }, { "name": "symfony/mime", @@ -5342,16 +5441,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.38.1", + "version": "v1.38.2", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92" + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92", - "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "shasum": "" }, "require": { @@ -5403,7 +5502,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" }, "funding": [ { @@ -5423,7 +5522,7 @@ "type": "tidelift" } ], - "time": "2026-05-26T12:51:13+00:00" + "time": "2026-05-27T06:59:30+00:00" }, { "name": "symfony/polyfill-php73", @@ -5671,16 +5770,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.38.1", + "version": "v1.38.2", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "8339098cae28673c15cce00d80734af0453054e2" + "reference": "796a26abb75ce49f3a84433cd81bf1009d73d5f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/8339098cae28673c15cce00d80734af0453054e2", - "reference": "8339098cae28673c15cce00d80734af0453054e2", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/796a26abb75ce49f3a84433cd81bf1009d73d5f8", + "reference": "796a26abb75ce49f3a84433cd81bf1009d73d5f8", "shasum": "" }, "require": { @@ -5727,7 +5826,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.38.2" }, "funding": [ { @@ -5747,7 +5846,7 @@ "type": "tidelift" } ], - "time": "2026-05-26T12:51:13+00:00" + "time": "2026-05-27T06:51:48+00:00" }, { "name": "symfony/polyfill-php84", @@ -6150,16 +6249,16 @@ }, { "name": "symfony/rate-limiter", - "version": "v7.4.13", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/rate-limiter.git", - "reference": "8b162768544e5a8895c52161d63c999aca91f4a9" + "reference": "5c0af3fdc93e6115d9b806a6ea73e7de040e711d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/rate-limiter/zipball/8b162768544e5a8895c52161d63c999aca91f4a9", - "reference": "8b162768544e5a8895c52161d63c999aca91f4a9", + "url": "https://api.github.com/repos/symfony/rate-limiter/zipball/5c0af3fdc93e6115d9b806a6ea73e7de040e711d", + "reference": "5c0af3fdc93e6115d9b806a6ea73e7de040e711d", "shasum": "" }, "require": { @@ -6200,7 +6299,7 @@ "rate-limiter" ], "support": { - "source": "https://github.com/symfony/rate-limiter/tree/v7.4.13" + "source": "https://github.com/symfony/rate-limiter/tree/v7.4.14" }, "funding": [ { @@ -6220,7 +6319,7 @@ "type": "tidelift" } ], - "time": "2026-05-23T16:05:06+00:00" + "time": "2026-06-08T20:24:16+00:00" }, { "name": "symfony/routing", @@ -6309,16 +6408,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a" + "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a", - "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0", + "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0", "shasum": "" }, "require": { @@ -6372,7 +6471,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.1" }, "funding": [ { @@ -6392,7 +6491,7 @@ "type": "tidelift" } ], - "time": "2026-03-28T09:44:51+00:00" + "time": "2026-06-16T09:55:08+00:00" }, { "name": "symfony/string", @@ -6486,16 +6585,16 @@ }, { "name": "symfony/translation", - "version": "v7.4.10", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "ada7578c30dd5feaa8259cff3e885069ea81ddde" + "reference": "a1af4dacb24eb7ef4f1ca71b94da8ddbce572281" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/ada7578c30dd5feaa8259cff3e885069ea81ddde", - "reference": "ada7578c30dd5feaa8259cff3e885069ea81ddde", + "url": "https://api.github.com/repos/symfony/translation/zipball/a1af4dacb24eb7ef4f1ca71b94da8ddbce572281", + "reference": "a1af4dacb24eb7ef4f1ca71b94da8ddbce572281", "shasum": "" }, "require": { @@ -6562,7 +6661,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.4.10" + "source": "https://github.com/symfony/translation/tree/v7.4.14" }, "funding": [ { @@ -6582,20 +6681,20 @@ "type": "tidelift" } ], - "time": "2026-05-06T11:19:24+00:00" + "time": "2026-06-06T09:33:19+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" + "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", - "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/ccb206b98faccc511ebae8e5fad50f2dc0b30621", + "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621", "shasum": "" }, "require": { @@ -6644,7 +6743,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.1" }, "funding": [ { @@ -6664,7 +6763,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T13:30:16+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/type-info", @@ -6828,16 +6927,16 @@ }, { "name": "symfony/validator", - "version": "v7.4.10", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "c76458623af9a3fe3b2e5b09b36453f334c2a361" + "reference": "306d904336166d001751759351d40d5e82312596" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/c76458623af9a3fe3b2e5b09b36453f334c2a361", - "reference": "c76458623af9a3fe3b2e5b09b36453f334c2a361", + "url": "https://api.github.com/repos/symfony/validator/zipball/306d904336166d001751759351d40d5e82312596", + "reference": "306d904336166d001751759351d40d5e82312596", "shasum": "" }, "require": { @@ -6908,7 +7007,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v7.4.10" + "source": "https://github.com/symfony/validator/tree/v7.4.14" }, "funding": [ { @@ -6928,20 +7027,20 @@ "type": "tidelift" } ], - "time": "2026-05-05T15:30:56+00:00" + "time": "2026-06-27T06:16:12+00:00" }, { "name": "symfony/var-exporter", - "version": "v8.0.9", + "version": "v8.0.14", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "24cf67be4dd0926e4413635418682f4fff831412" + "reference": "5185b7a7ea87a177be5fb16e8dc7756bea9b6eee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/24cf67be4dd0926e4413635418682f4fff831412", - "reference": "24cf67be4dd0926e4413635418682f4fff831412", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5185b7a7ea87a177be5fb16e8dc7756bea9b6eee", + "reference": "5185b7a7ea87a177be5fb16e8dc7756bea9b6eee", "shasum": "" }, "require": { @@ -6988,7 +7087,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v8.0.9" + "source": "https://github.com/symfony/var-exporter/tree/v8.0.14" }, "funding": [ { @@ -7008,20 +7107,20 @@ "type": "tidelift" } ], - "time": "2026-04-18T13:51:42+00:00" + "time": "2026-06-27T08:56:37+00:00" }, { "name": "symfony/yaml", - "version": "v7.4.13", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "a7ec3b1156faf8815db7683ec7c1e7338e6f977c" + "reference": "f8f328665ace2370d1e10645b807ba1646dc7dcc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a7ec3b1156faf8815db7683ec7c1e7338e6f977c", - "reference": "a7ec3b1156faf8815db7683ec7c1e7338e6f977c", + "url": "https://api.github.com/repos/symfony/yaml/zipball/f8f328665ace2370d1e10645b807ba1646dc7dcc", + "reference": "f8f328665ace2370d1e10645b807ba1646dc7dcc", "shasum": "" }, "require": { @@ -7064,7 +7163,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.13" + "source": "https://github.com/symfony/yaml/tree/v7.4.14" }, "funding": [ { @@ -7084,7 +7183,7 @@ "type": "tidelift" } ], - "time": "2026-05-25T06:06:12+00:00" + "time": "2026-06-08T20:24:16+00:00" }, { "name": "typo3/class-alias-loader", @@ -7151,23 +7250,23 @@ }, { "name": "typo3/cms-backend", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/backend.git", - "reference": "e3a61d3f083e10e8125f281b5c758103cfd015c4" + "reference": "f842410118ea059292dc697e3c085e5b12ea41f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/backend/zipball/e3a61d3f083e10e8125f281b5c758103cfd015c4", - "reference": "e3a61d3f083e10e8125f281b5c758103cfd015c4", + "url": "https://api.github.com/repos/TYPO3-CMS/backend/zipball/f842410118ea059292dc697e3c085e5b12ea41f0", + "reference": "f842410118ea059292dc697e3c085e5b12ea41f0", "shasum": "" }, "require": { "ext-intl": "*", "ext-libxml": "*", "psr/event-dispatcher": "^1.0", - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -7240,24 +7339,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-belog", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/belog.git", - "reference": "5c0585ae27c0712b38f36225e1c564f47b7d293d" + "reference": "e5f33784c536e43929104e378d872cafbb5c3afd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/belog/zipball/5c0585ae27c0712b38f36225e1c564f47b7d293d", - "reference": "5c0585ae27c0712b38f36225e1c564f47b7d293d", + "url": "https://api.github.com/repos/TYPO3-CMS/belog/zipball/e5f33784c536e43929104e378d872cafbb5c3afd", + "reference": "e5f33784c536e43929104e378d872cafbb5c3afd", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -7307,24 +7406,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-beuser", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/beuser.git", - "reference": "7269663f07577c1a17674207c8aff5858adf9a20" + "reference": "124498b0bcf090e1cde666f9f6f80d34322bdd1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/beuser/zipball/7269663f07577c1a17674207c8aff5858adf9a20", - "reference": "7269663f07577c1a17674207c8aff5858adf9a20", + "url": "https://api.github.com/repos/TYPO3-CMS/beuser/zipball/124498b0bcf090e1cde666f9f6f80d34322bdd1e", + "reference": "124498b0bcf090e1cde666f9f6f80d34322bdd1e", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -7374,7 +7473,7 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-cli", @@ -7483,22 +7582,23 @@ }, { "name": "typo3/cms-core", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/core.git", - "reference": "e323e061321a6a8441d2b552dfe59af4de478d2c" + "reference": "e59ef7a3348e439bf103140e01614f1bc403d373" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/core/zipball/e323e061321a6a8441d2b552dfe59af4de478d2c", - "reference": "e323e061321a6a8441d2b552dfe59af4de478d2c", + "url": "https://api.github.com/repos/TYPO3-CMS/core/zipball/e59ef7a3348e439bf103140e01614f1bc403d373", + "reference": "e59ef7a3348e439bf103140e01614f1bc403d373", "shasum": "" }, "require": { "bacon/bacon-qr-code": "^3.1.1", "christian-riesen/base32": "^1.6", "composer-runtime-api": "^2.1", + "composer/class-map-generator": "^1.7.2", "composer/semver": "^3.4", "doctrine/dbal": "~4.4.3", "doctrine/lexer": "^3.0.1", @@ -7537,7 +7637,7 @@ "symfony/expression-language": "^7.4.8", "symfony/filesystem": "^7.4.8", "symfony/finder": "^7.4.8", - "symfony/http-foundation": "^7.4.8", + "symfony/http-foundation": "^7.4.13", "symfony/mailer": "^7.4.12", "symfony/messenger": "^7.4.8", "symfony/mime": "^7.4.12", @@ -7545,14 +7645,14 @@ "symfony/polyfill-php83": "^1.36.0", "symfony/process": "^7.4.8", "symfony/rate-limiter": "^7.4.8", - "symfony/routing": "^7.4.12", + "symfony/routing": "^7.4.13", "symfony/translation": "^7.4.8", "symfony/uid": "^7.4.8", "symfony/yaml": "^7.4.12", "typo3/class-alias-loader": "^2.0.1", "typo3/cms-cli": "^3.1.3", "typo3/cms-composer-installers": "^5.0.2", - "typo3/html-sanitizer": "^2.2.0", + "typo3/html-sanitizer": "^2.3.2", "typo3fluid/fluid": "^5.3.1" }, "conflict": { @@ -7637,28 +7737,28 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-dashboard", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/dashboard.git", - "reference": "195f573f0c44c239de385fb712969ea7455c7d7b" + "reference": "0dfdb48e21dfd7e48785b775aa0265c981ca43b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/dashboard/zipball/195f573f0c44c239de385fb712969ea7455c7d7b", - "reference": "195f573f0c44c239de385fb712969ea7455c7d7b", + "url": "https://api.github.com/repos/TYPO3-CMS/dashboard/zipball/0dfdb48e21dfd7e48785b775aa0265c981ca43b1", + "reference": "0dfdb48e21dfd7e48785b775aa0265c981ca43b1", "shasum": "" }, "require": { - "typo3/cms-backend": "14.3.2", - "typo3/cms-core": "14.3.2", - "typo3/cms-extbase": "14.3.2", - "typo3/cms-fluid": "14.3.2", - "typo3/cms-frontend": "14.3.2" + "typo3/cms-backend": "14.3.4", + "typo3/cms-core": "14.3.4", + "typo3/cms-extbase": "14.3.4", + "typo3/cms-fluid": "14.3.4", + "typo3/cms-frontend": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -7709,20 +7809,20 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-extbase", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/extbase.git", - "reference": "c178b1246599c6619452b5ecbad980bc1a9cd9a1" + "reference": "3d41793cdb2dcae4a3490f859af6a999e5cc5627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/extbase/zipball/c178b1246599c6619452b5ecbad980bc1a9cd9a1", - "reference": "c178b1246599c6619452b5ecbad980bc1a9cd9a1", + "url": "https://api.github.com/repos/TYPO3-CMS/extbase/zipball/3d41793cdb2dcae4a3490f859af6a999e5cc5627", + "reference": "3d41793cdb2dcae4a3490f859af6a999e5cc5627", "shasum": "" }, "require": { @@ -7734,7 +7834,7 @@ "symfony/property-access": "^7.4.8", "symfony/property-info": "^7.4.8", "symfony/validator": "^7.4.8", - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -7795,25 +7895,25 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-extensionmanager", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/extensionmanager.git", - "reference": "613d92bb63eeaa6611fa8b426fa50282386d7614" + "reference": "a3f272a35cc3938324f5b9fc7a8131ed5f731851" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/extensionmanager/zipball/613d92bb63eeaa6611fa8b426fa50282386d7614", - "reference": "613d92bb63eeaa6611fa8b426fa50282386d7614", + "url": "https://api.github.com/repos/TYPO3-CMS/extensionmanager/zipball/a3f272a35cc3938324f5b9fc7a8131ed5f731851", + "reference": "a3f272a35cc3938324f5b9fc7a8131ed5f731851", "shasum": "" }, "require": { "ext-libxml": "*", - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -7865,24 +7965,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-felogin", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/felogin.git", - "reference": "c44e401f138491c494018390ccae58aa9c7d48b9" + "reference": "d45a4987e58186b3806829ca0e715b148ea6b721" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/felogin/zipball/c44e401f138491c494018390ccae58aa9c7d48b9", - "reference": "c44e401f138491c494018390ccae58aa9c7d48b9", + "url": "https://api.github.com/repos/TYPO3-CMS/felogin/zipball/d45a4987e58186b3806829ca0e715b148ea6b721", + "reference": "d45a4987e58186b3806829ca0e715b148ea6b721", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -7932,24 +8032,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-filelist", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/filelist.git", - "reference": "e4f20c9aa130a2d23e3de5bc904877ca07b071a0" + "reference": "8bc262bbd3577a5535317941e141b0975803a4ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/filelist/zipball/e4f20c9aa130a2d23e3de5bc904877ca07b071a0", - "reference": "e4f20c9aa130a2d23e3de5bc904877ca07b071a0", + "url": "https://api.github.com/repos/TYPO3-CMS/filelist/zipball/8bc262bbd3577a5535317941e141b0975803a4ca", + "reference": "8bc262bbd3577a5535317941e141b0975803a4ca", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8001,27 +8101,27 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-fluid", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/fluid.git", - "reference": "c2366cf6e7dfdf80d098f7b7f75ac0e7ac1e0b95" + "reference": "8f50a943ac2a22532379591c97b570119c8e4bae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/fluid/zipball/c2366cf6e7dfdf80d098f7b7f75ac0e7ac1e0b95", - "reference": "c2366cf6e7dfdf80d098f7b7f75ac0e7ac1e0b95", + "url": "https://api.github.com/repos/TYPO3-CMS/fluid/zipball/8f50a943ac2a22532379591c97b570119c8e4bae", + "reference": "8f50a943ac2a22532379591c97b570119c8e4bae", "shasum": "" }, "require": { "symfony/dependency-injection": "^7.4.8", "symfony/finder": "^7.4.8", - "typo3/cms-core": "14.3.2", - "typo3/cms-extbase": "14.3.2", + "typo3/cms-core": "14.3.4", + "typo3/cms-extbase": "14.3.4", "typo3fluid/fluid": "^5.3.1" }, "conflict": { @@ -8075,26 +8175,26 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-fluid-styled-content", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/fluid_styled_content.git", - "reference": "a3c108e57adec1fa71c8d29420eb0205bf090185" + "reference": "b08e119753ab90e15f015135cdfd65d47bbdbbf6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/fluid_styled_content/zipball/a3c108e57adec1fa71c8d29420eb0205bf090185", - "reference": "a3c108e57adec1fa71c8d29420eb0205bf090185", + "url": "https://api.github.com/repos/TYPO3-CMS/fluid_styled_content/zipball/b08e119753ab90e15f015135cdfd65d47bbdbbf6", + "reference": "b08e119753ab90e15f015135cdfd65d47bbdbbf6", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2", - "typo3/cms-fluid": "14.3.2", - "typo3/cms-frontend": "14.3.2" + "typo3/cms-core": "14.3.4", + "typo3/cms-fluid": "14.3.4", + "typo3/cms-frontend": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8144,27 +8244,27 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-form", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/form.git", - "reference": "5d4d429f6870582b6debfee339fbf39891ed81f8" + "reference": "3307aae5867a885cd239226c9dda2791ad711f56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/form/zipball/5d4d429f6870582b6debfee339fbf39891ed81f8", - "reference": "5d4d429f6870582b6debfee339fbf39891ed81f8", + "url": "https://api.github.com/repos/TYPO3-CMS/form/zipball/3307aae5867a885cd239226c9dda2791ad711f56", + "reference": "3307aae5867a885cd239226c9dda2791ad711f56", "shasum": "" }, "require": { "psr/http-message": "^1.1 || ^2.0", "symfony/expression-language": "^7.4.8", - "typo3/cms-core": "14.3.2", - "typo3/cms-frontend": "14.3.2" + "typo3/cms-core": "14.3.4", + "typo3/cms-frontend": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8219,25 +8319,25 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-frontend", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/frontend.git", - "reference": "9a623a68e880bbf5ef468b4c1206648271dfe58a" + "reference": "bd865d76c5b63a5c0b1f0325b32292e975ad7c38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/frontend/zipball/9a623a68e880bbf5ef468b4c1206648271dfe58a", - "reference": "9a623a68e880bbf5ef468b4c1206648271dfe58a", + "url": "https://api.github.com/repos/TYPO3-CMS/frontend/zipball/bd865d76c5b63a5c0b1f0325b32292e975ad7c38", + "reference": "bd865d76c5b63a5c0b1f0325b32292e975ad7c38", "shasum": "" }, "require": { "ext-libxml": "*", - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8297,24 +8397,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-impexp", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/impexp.git", - "reference": "9bbc42bc05358bf03dc1931a2ea9ecdfaf03c19e" + "reference": "b7644c24e3cb118a91be1eafa8810eb33cd94ddf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/impexp/zipball/9bbc42bc05358bf03dc1931a2ea9ecdfaf03c19e", - "reference": "9bbc42bc05358bf03dc1931a2ea9ecdfaf03c19e", + "url": "https://api.github.com/repos/TYPO3-CMS/impexp/zipball/b7644c24e3cb118a91be1eafa8810eb33cd94ddf", + "reference": "b7644c24e3cb118a91be1eafa8810eb33cd94ddf", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8364,24 +8464,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-info", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/info.git", - "reference": "d89a05aa69b2ee7a1ee1c8a0292122e40faba5bd" + "reference": "b530430877339b2a16c30ba7b78b8c88454dd7a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/info/zipball/d89a05aa69b2ee7a1ee1c8a0292122e40faba5bd", - "reference": "d89a05aa69b2ee7a1ee1c8a0292122e40faba5bd", + "url": "https://api.github.com/repos/TYPO3-CMS/info/zipball/b530430877339b2a16c30ba7b78b8c88454dd7a1", + "reference": "b530430877339b2a16c30ba7b78b8c88454dd7a1", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8434,20 +8534,20 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-install", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/install.git", - "reference": "033b815b778af0a6bd1a55fd8a8755dc7f42d9e4" + "reference": "a4c5bd2e9a598d5d45975312ae097df2a33ef05d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/install/zipball/033b815b778af0a6bd1a55fd8a8755dc7f42d9e4", - "reference": "033b815b778af0a6bd1a55fd8a8755dc7f42d9e4", + "url": "https://api.github.com/repos/TYPO3-CMS/install/zipball/a4c5bd2e9a598d5d45975312ae097df2a33ef05d", + "reference": "a4c5bd2e9a598d5d45975312ae097df2a33ef05d", "shasum": "" }, "require": { @@ -8455,10 +8555,10 @@ "guzzlehttp/promises": "^2.0.3", "nikic/php-parser": "^5.4.0", "symfony/finder": "^7.4.8", - "symfony/http-foundation": "^7.4.8", - "typo3/cms-core": "14.3.2", - "typo3/cms-extbase": "14.3.2", - "typo3/cms-fluid": "14.3.2" + "symfony/http-foundation": "^7.4.13", + "typo3/cms-core": "14.3.4", + "typo3/cms-extbase": "14.3.4", + "typo3/cms-fluid": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8511,24 +8611,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-reactions", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/reactions.git", - "reference": "5e4215eabe684343da7ed2eeae472680cefc9c1d" + "reference": "700233067b941381d551fa8a0662c92977ba9ceb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/reactions/zipball/5e4215eabe684343da7ed2eeae472680cefc9c1d", - "reference": "5e4215eabe684343da7ed2eeae472680cefc9c1d", + "url": "https://api.github.com/repos/TYPO3-CMS/reactions/zipball/700233067b941381d551fa8a0662c92977ba9ceb", + "reference": "700233067b941381d551fa8a0662c92977ba9ceb", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8578,24 +8678,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-recycler", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/recycler.git", - "reference": "d17e66c3bf8819b4915a582efe510636553ccfaa" + "reference": "e34ad4cf0561f2e441248c52243457adef3a9bac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/recycler/zipball/d17e66c3bf8819b4915a582efe510636553ccfaa", - "reference": "d17e66c3bf8819b4915a582efe510636553ccfaa", + "url": "https://api.github.com/repos/TYPO3-CMS/recycler/zipball/e34ad4cf0561f2e441248c52243457adef3a9bac", + "reference": "e34ad4cf0561f2e441248c52243457adef3a9bac", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8648,24 +8748,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-rte-ckeditor", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/rte_ckeditor.git", - "reference": "f1c80b0e15dc9b5cee51ffc3578fcbd3293dd1b0" + "reference": "1e649567cec0c67a3acef5fc2a680f861c6ed146" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/rte_ckeditor/zipball/f1c80b0e15dc9b5cee51ffc3578fcbd3293dd1b0", - "reference": "f1c80b0e15dc9b5cee51ffc3578fcbd3293dd1b0", + "url": "https://api.github.com/repos/TYPO3-CMS/rte_ckeditor/zipball/1e649567cec0c67a3acef5fc2a680f861c6ed146", + "reference": "1e649567cec0c67a3acef5fc2a680f861c6ed146", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8715,24 +8815,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-scheduler", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/scheduler.git", - "reference": "398eb05a3590ee8d37fbfdfe8cb0967c0ca1e850" + "reference": "b5cb0dfbd2e52fc6903cc9e695d7536e55489321" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/scheduler/zipball/398eb05a3590ee8d37fbfdfe8cb0967c0ca1e850", - "reference": "398eb05a3590ee8d37fbfdfe8cb0967c0ca1e850", + "url": "https://api.github.com/repos/TYPO3-CMS/scheduler/zipball/b5cb0dfbd2e52fc6903cc9e695d7536e55489321", + "reference": "b5cb0dfbd2e52fc6903cc9e695d7536e55489321", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8779,26 +8879,26 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-seo", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/seo.git", - "reference": "db45e6c092197c32596a9b4e59123784cf442b42" + "reference": "ed5e9f465e1379adfcff0abedbfe1d68b96f6bdc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/seo/zipball/db45e6c092197c32596a9b4e59123784cf442b42", - "reference": "db45e6c092197c32596a9b4e59123784cf442b42", + "url": "https://api.github.com/repos/TYPO3-CMS/seo/zipball/ed5e9f465e1379adfcff0abedbfe1d68b96f6bdc", + "reference": "ed5e9f465e1379adfcff0abedbfe1d68b96f6bdc", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2", - "typo3/cms-extbase": "14.3.2", - "typo3/cms-frontend": "14.3.2" + "typo3/cms-core": "14.3.4", + "typo3/cms-extbase": "14.3.4", + "typo3/cms-frontend": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8851,24 +8951,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-sys-note", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/sys_note.git", - "reference": "e16ca23b306d844997dc97998cbb7c77d7624f9a" + "reference": "14543f7367fb92adbacc96a889ff602fe559a979" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/sys_note/zipball/e16ca23b306d844997dc97998cbb7c77d7624f9a", - "reference": "e16ca23b306d844997dc97998cbb7c77d7624f9a", + "url": "https://api.github.com/repos/TYPO3-CMS/sys_note/zipball/14543f7367fb92adbacc96a889ff602fe559a979", + "reference": "14543f7367fb92adbacc96a889ff602fe559a979", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8921,24 +9021,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-tstemplate", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/tstemplate.git", - "reference": "e3f09b0da26a57e25a07223253743f009b6c51ab" + "reference": "caa2a8e1a373a8ae5b8cba0ea8e8944bffce83f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/tstemplate/zipball/e3f09b0da26a57e25a07223253743f009b6c51ab", - "reference": "e3f09b0da26a57e25a07223253743f009b6c51ab", + "url": "https://api.github.com/repos/TYPO3-CMS/tstemplate/zipball/caa2a8e1a373a8ae5b8cba0ea8e8944bffce83f4", + "reference": "caa2a8e1a373a8ae5b8cba0ea8e8944bffce83f4", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -8988,24 +9088,24 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-viewpage", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/viewpage.git", - "reference": "b766123bdb09d627b5ad4bef09bf2aa401243927" + "reference": "519ebbb6b6da69b13bd2a7a3651c0ae1e8ece3ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/viewpage/zipball/b766123bdb09d627b5ad4bef09bf2aa401243927", - "reference": "b766123bdb09d627b5ad4bef09bf2aa401243927", + "url": "https://api.github.com/repos/TYPO3-CMS/viewpage/zipball/519ebbb6b6da69b13bd2a7a3651c0ae1e8ece3ee", + "reference": "519ebbb6b6da69b13bd2a7a3651c0ae1e8ece3ee", "shasum": "" }, "require": { - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -9055,25 +9155,25 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/cms-webhooks", - "version": "v14.3.2", + "version": "v14.3.4", "source": { "type": "git", "url": "https://github.com/TYPO3-CMS/webhooks.git", - "reference": "2abedd921aac6a228c94eec6d0d68f5bd3769dc0" + "reference": "e72dac3ec0378c4f5094987ffdc08ba07f68cb41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3-CMS/webhooks/zipball/2abedd921aac6a228c94eec6d0d68f5bd3769dc0", - "reference": "2abedd921aac6a228c94eec6d0d68f5bd3769dc0", + "url": "https://api.github.com/repos/TYPO3-CMS/webhooks/zipball/e72dac3ec0378c4f5094987ffdc08ba07f68cb41", + "reference": "e72dac3ec0378c4f5094987ffdc08ba07f68cb41", "shasum": "" }, "require": { "symfony/uid": "^7.4.8", - "typo3/cms-core": "14.3.2" + "typo3/cms-core": "14.3.4" }, "conflict": { "typo3/cms": "*" @@ -9123,20 +9223,20 @@ "type": "membership" } ], - "time": "2026-05-26T09:37:47+00:00" + "time": "2026-06-16T08:52:34+00:00" }, { "name": "typo3/html-sanitizer", - "version": "v2.3.1", + "version": "v2.3.2", "source": { "type": "git", "url": "https://github.com/TYPO3/html-sanitizer.git", - "reference": "988caa31b5fa0dbe17a8331bfa3245898a650d88" + "reference": "8b5d0be44ded457ca993ec9ca93d859941c63764" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TYPO3/html-sanitizer/zipball/988caa31b5fa0dbe17a8331bfa3245898a650d88", - "reference": "988caa31b5fa0dbe17a8331bfa3245898a650d88", + "url": "https://api.github.com/repos/TYPO3/html-sanitizer/zipball/8b5d0be44ded457ca993ec9ca93d859941c63764", + "reference": "8b5d0be44ded457ca993ec9ca93d859941c63764", "shasum": "" }, "require": { @@ -9172,9 +9272,9 @@ "description": "HTML sanitizer aiming to provide XSS-safe markup based on explicitly allowed tags, attributes and values.", "support": { "issues": "https://github.com/TYPO3/html-sanitizer/issues", - "source": "https://github.com/TYPO3/html-sanitizer/tree/v2.3.1" + "source": "https://github.com/TYPO3/html-sanitizer/tree/v2.3.2" }, - "time": "2026-04-30T11:50:45+00:00" + "time": "2026-06-08T15:19:36+00:00" }, { "name": "typo3fluid/fluid", @@ -9238,16 +9338,16 @@ }, { "name": "webmozart/assert", - "version": "2.4.0", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155" + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/9007ea6f45ecf352a9422b36644e4bfc039b9155", - "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70", + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70", "shasum": "" }, "require": { @@ -9298,9 +9398,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/2.4.0" + "source": "https://github.com/webmozarts/assert/tree/2.4.1" }, - "time": "2026-05-20T13:07:01+00:00" + "time": "2026-06-15T15:31:57+00:00" } ], "packages-dev": [], diff --git a/config/sites/vitec/config.yaml b/config/sites/vitec/config.yaml index 070e13f..9c99dfe 100644 --- a/config/sites/vitec/config.yaml +++ b/config/sites/vitec/config.yaml @@ -15,6 +15,11 @@ dependencies: - vitec/card - vitec/intro-paragraph - vitec/video + - vitec/faq + - georgringer/news + - georgringer/news-sitemap + - georgringer/news-recordlinks + - vitec/columns frontendBase: '' headless: 1 languages: @@ -49,4 +54,19 @@ routeEnhancers: tableName: tx_vitec_domain_model_product routeFieldName: slug routeValuePrefix: '' + NewsDetail: + type: Extbase + limitToPages: + - 21 + extension: News + plugin: Pi1 + routes: + - routePath: '/{news-title}' + _controller: 'News::detail' + _arguments: + news-title: news + defaultController: 'News::detail' + aspects: + news-title: + type: NewsTitle websiteTitle: '' diff --git a/fix-asset-perms.sh b/fix-asset-perms.sh new file mode 100644 index 0000000..03a17c2 --- /dev/null +++ b/fix-asset-perms.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# ============================================================================= +# VITEC — fix backend asset permissions after a deploy via the Windows sshfs mount +# ----------------------------------------------------------------------------- +# sshfs-win (WinFsp) writes newly deployed files with mode 770 (no other-read). +# The webserver runs as "other" (suexec) -> assets under Resources/Public and +# public/_assets return HTTP 403 (backend icons / CSS / JS missing). +# +# chmod OVER the Windows mount does NOT change the real server mode, so this +# has to run ON THE SERVER, via real SSH, as the site owner (vitecevo). +# +# Usage (from the live/ project root on the server): +# bash fix-asset-perms.sh +# ============================================================================= +set -u +cd "$(dirname "$0")" || exit 1 + +echo "[perms] Project root: $(pwd)" +echo "[perms] Setting files 644 / directories 755 under Resources/Public + _assets ..." +find public/_assets packages/vitec/Resources/Public -type f -exec chmod 644 {} \; 2>/dev/null +find public/_assets packages/vitec/Resources/Public -type d -exec chmod 755 {} \; 2>/dev/null + +echo "[perms] Flushing TYPO3 caches ..." +if [ -x vendor/bin/typo3 ]; then + vendor/bin/typo3 cache:flush +else + echo "[perms] (vendor/bin/typo3 not found — skip cache flush)" +fi + +echo "[perms] Done." diff --git a/packages/vitec/Classes/Backend/FormEngine/StructuredDataGeneratorWizard.php b/packages/vitec/Classes/Backend/FormEngine/StructuredDataGeneratorWizard.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Controller/Backend/StructuredDataController.php b/packages/vitec/Classes/Controller/Backend/StructuredDataController.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Controller/EventController.php b/packages/vitec/Classes/Controller/EventController.php new file mode 100644 index 0000000..fc3faae --- /dev/null +++ b/packages/vitec/Classes/Controller/EventController.php @@ -0,0 +1,39 @@ +eventRepository = $eventRepository; + } + + public function listAction(): ResponseInterface + { + $this->view->assign('events', $this->eventRepository->findUpcoming()); + return $this->htmlResponse(); + } +} diff --git a/packages/vitec/Classes/DataProcessing/.msys00000000000000004cda359073ead130 b/packages/vitec/Classes/DataProcessing/.msys00000000000000004cda359073ead130 old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/DataProcessing/.msys00000000000000004dd18ef4cfaf2af9 b/packages/vitec/Classes/DataProcessing/.msys00000000000000004dd18ef4cfaf2af9 old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/DataProcessing/ContainerChildrenProcessor.php b/packages/vitec/Classes/DataProcessing/ContainerChildrenProcessor.php old mode 100755 new mode 100644 index 380ab01..ee54d3f --- a/packages/vitec/Classes/DataProcessing/ContainerChildrenProcessor.php +++ b/packages/vitec/Classes/DataProcessing/ContainerChildrenProcessor.php @@ -12,6 +12,8 @@ use Evomedien\Vitec\UserFunc\SolutionShowJsonRenderer; use Evomedien\Vitec\UserFunc\DownloadcardJsonRenderer; use Evomedien\Vitec\UserFunc\DownloadcardcollectionJsonRenderer; use Evomedien\Vitec\UserFunc\DatasheetsJsonRenderer; +use Evomedien\Vitec\UserFunc\EventlistJsonRenderer; +use Evomedien\Vitec\UserFunc\NewsJsonRenderer; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -20,9 +22,13 @@ use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface; /** * Collect container children grouped by colPos and emit a lean, transport- - * ready structure. Each child is normalised to: - * { id, type, colPos, sorting, appearance, data } - * `data` only contains non-empty content-relevant fields. + * ready structure. Each column is normalised to: + * { config: { colPos, align, justify }, contentElements: [ { id, type, … } ] } + * `align`/`justify` are the PARENT container's per-column flex settings + * (tx_vitec_col{N}_align/justify) and therefore apply to ALL children of that + * column. Each child is normalised to { id, type, colPos, sorting, appearance, + * data }, where `data` only contains non-empty content-relevant fields — + * container-level fields (gap, col flex) are never leaked to children. * * VITEC list-plugins nested as container children (productlist, productshow, * usecaselist, usecaseshow) are resolved to the SAME JSON the top-level @@ -59,6 +65,30 @@ final class ContainerChildrenProcessor implements DataProcessorInterface 'uploads_description', 'uploads_type', ]; + /** + * Container-level fields — they belong on the parent container (grid gap + * and per-column flex) and must never appear in a child's `data`. + */ + private const CONTAINER_FIELDS = [ + 'tx_vitec_gap', + 'tx_vitec_col1_align', 'tx_vitec_col1_justify', + 'tx_vitec_col2_align', 'tx_vitec_col2_justify', + 'tx_vitec_col3_align', 'tx_vitec_col3_justify', + 'tx_vitec_col4_align', 'tx_vitec_col4_justify', + ]; + + /** + * Per container CType: colPos value => 1-based column number. Used to pick + * the parent's tx_vitec_col{N}_align/justify for each rendered column. + */ + private const COLPOS_TO_COLUMN = [ + 'vitec_cols_50_50' => [211 => 1, 212 => 2], + 'vitec_cols_33_66' => [251 => 1, 252 => 2], + 'vitec_cols_66_33' => [241 => 1, 242 => 2], + 'vitec_cols_33_33_33' => [221 => 1, 222 => 2, 223 => 3], + 'vitec_cols_25_25_25_25' => [231 => 1, 232 => 2, 233 => 3, 234 => 4], + ]; + /** Fields whose 0/empty value is still meaningful. */ private const KEEP_IF_ZERO = [ 'header_layout', @@ -80,6 +110,16 @@ final class ContainerChildrenProcessor implements DataProcessorInterface 'vitec_downloadcard' => [DownloadcardJsonRenderer::class, 'downloadcard'], 'vitec_downloadcardcollection' => [DownloadcardcollectionJsonRenderer::class, 'downloadcardcollection'], 'vitec_datasheets' => [DatasheetsJsonRenderer::class, 'datasheets'], + 'vitec_eventlist' => [EventlistJsonRenderer::class, 'eventlist'], + 'news_pi1' => [NewsJsonRenderer::class, 'news'], + 'news_newsliststicky' => [NewsJsonRenderer::class, 'news'], + 'news_newsselectedlist' => [NewsJsonRenderer::class, 'news'], + 'news_newsdetail' => [NewsJsonRenderer::class, 'news'], + 'news_newsdatemenu' => [NewsJsonRenderer::class, 'news'], + 'news_categorylist' => [NewsJsonRenderer::class, 'news'], + 'news_newssearchform' => [NewsJsonRenderer::class, 'news'], + 'news_newssearchresult' => [NewsJsonRenderer::class, 'news'], + 'news_taglist' => [NewsJsonRenderer::class, 'news'], ]; public function process( @@ -121,10 +161,20 @@ final class ContainerChildrenProcessor implements DataProcessorInterface } ksort($byColPos); + // Per-column flex settings come from the parent container record. + $parentCType = (string)($cObj->data['CType'] ?? ''); + $colMap = self::COLPOS_TO_COLUMN[$parentCType] ?? []; + $items = []; foreach ($byColPos as $colPos => $contentElements) { + $config = ['colPos' => $colPos]; + $columnNo = $colMap[$colPos] ?? null; + if ($columnNo !== null) { + $config['align'] = (string)($cObj->data['tx_vitec_col' . $columnNo . '_align'] ?? 'stretch'); + $config['justify'] = (string)($cObj->data['tx_vitec_col' . $columnNo . '_justify'] ?? 'flex-start'); + } $items[] = [ - 'config' => ['colPos' => $colPos], + 'config' => $config, 'contentElements' => $contentElements, ]; } @@ -147,6 +197,9 @@ final class ContainerChildrenProcessor implements DataProcessorInterface if (in_array($field, self::SYSTEM_FIELDS, true)) { continue; } + if (in_array($field, self::CONTAINER_FIELDS, true)) { + continue; + } if ($this->isEmpty($value) && !in_array($field, self::KEEP_IF_ZERO, true)) { continue; } diff --git a/packages/vitec/Classes/Domain/Model/Event.php b/packages/vitec/Classes/Domain/Model/Event.php new file mode 100644 index 0000000..c0ff97c --- /dev/null +++ b/packages/vitec/Classes/Domain/Model/Event.php @@ -0,0 +1,266 @@ + + * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy + */ + protected $categories; + + public function __construct() + { + $this->categories = new ObjectStorage(); + } + + public function getTitle(): string + { + return $this->title; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getSlug(): string + { + return $this->slug; + } + + public function setSlug(string $slug): void + { + $this->slug = $slug; + } + + public function getTeaser(): string + { + return $this->teaser; + } + + public function setTeaser(string $teaser): void + { + $this->teaser = $teaser; + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): void + { + $this->description = $description; + } + + public function getEventstart(): ?\DateTime + { + return $this->eventstart; + } + + public function setEventstart(?\DateTime $eventstart): void + { + $this->eventstart = $eventstart; + } + + public function getEventend(): ?\DateTime + { + return $this->eventend; + } + + public function setEventend(?\DateTime $eventend): void + { + $this->eventend = $eventend; + } + + public function getVenue(): string + { + return $this->venue; + } + + public function setVenue(string $venue): void + { + $this->venue = $venue; + } + + public function getBooth(): string + { + return $this->booth; + } + + public function setBooth(string $booth): void + { + $this->booth = $booth; + } + + public function getCity(): string + { + return $this->city; + } + + public function setCity(string $city): void + { + $this->city = $city; + } + + public function getCountry(): string + { + return $this->country; + } + + public function setCountry(string $country): void + { + $this->country = $country; + } + + public function getAttendancemode(): string + { + return $this->attendancemode; + } + + public function setAttendancemode(string $attendancemode): void + { + $this->attendancemode = $attendancemode; + } + + public function getEventstatus(): string + { + return $this->eventstatus; + } + + public function setEventstatus(string $eventstatus): void + { + $this->eventstatus = $eventstatus; + } + + public function getEventurl(): string + { + return $this->eventurl; + } + + public function setEventurl(string $eventurl): void + { + $this->eventurl = $eventurl; + } + + public function getMeetinglink(): string + { + return $this->meetinglink; + } + + public function setMeetinglink(string $meetinglink): void + { + $this->meetinglink = $meetinglink; + } + + public function getImage(): ?FileReference + { + return $this->image; + } + + public function setImage(?FileReference $image): void + { + $this->image = $image; + } + + public function getHideonwebsite(): bool + { + return $this->hideonwebsite; + } + + public function setHideonwebsite(bool $hideonwebsite): void + { + $this->hideonwebsite = $hideonwebsite; + } + + public function getHideonapp(): bool + { + return $this->hideonapp; + } + + public function setHideonapp(bool $hideonapp): void + { + $this->hideonapp = $hideonapp; + } + + public function addCategory(Category $category): void + { + $this->categories->attach($category); + } + + public function removeCategory(Category $categoryToRemove): void + { + $this->categories->detach($categoryToRemove); + } + + public function getCategories(): ObjectStorage + { + return $this->categories; + } + + public function setCategories(ObjectStorage $categories): void + { + $this->categories = $categories; + } +} diff --git a/packages/vitec/Classes/Domain/Model/Product.php b/packages/vitec/Classes/Domain/Model/Product.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Domain/Repository/EventRepository.php b/packages/vitec/Classes/Domain/Repository/EventRepository.php new file mode 100644 index 0000000..e768628 --- /dev/null +++ b/packages/vitec/Classes/Domain/Repository/EventRepository.php @@ -0,0 +1,71 @@ + QueryInterface::ORDER_ASCENDING, + ]; + + /** + * All upcoming (or currently running) events, soonest first. + * "Upcoming" = event end (or start, when no end is set) is today or later. + */ + public function findUpcoming(): QueryResultInterface + { + $todayMidnight = strtotime('today'); + + $query = $this->createQuery(); + $query->getQuerySettings()->setRespectStoragePage(false); + $query->matching( + $query->logicalAnd( + $query->equals('hideonwebsite', 0), + $query->logicalOr( + $query->greaterThanOrEqual('eventend', $todayMidnight), + $query->logicalAnd( + $query->equals('eventend', 0), + $query->greaterThanOrEqual('eventstart', $todayMidnight) + ) + ) + ) + ); + return $query->execute(); + } + + /** + * Past events, most recent first. + */ + public function findPast(): QueryResultInterface + { + $todayMidnight = strtotime('today'); + + $query = $this->createQuery(); + $query->getQuerySettings()->setRespectStoragePage(false); + $query->matching( + $query->logicalAnd( + $query->equals('hideonwebsite', 0), + $query->logicalOr( + $query->logicalAnd( + $query->greaterThan('eventend', 0), + $query->lessThan('eventend', $todayMidnight) + ), + $query->logicalAnd( + $query->equals('eventend', 0), + $query->greaterThan('eventstart', 0), + $query->lessThan('eventstart', $todayMidnight) + ) + ) + ) + ); + $query->setOrderings(['eventstart' => QueryInterface::ORDER_DESCENDING]); + return $query->execute(); + } +} diff --git a/packages/vitec/Classes/EventListener/LoadContainerCollapseAssets.php b/packages/vitec/Classes/EventListener/LoadContainerCollapseAssets.php new file mode 100644 index 0000000..9af2542 --- /dev/null +++ b/packages/vitec/Classes/EventListener/LoadContainerCollapseAssets.php @@ -0,0 +1,27 @@ +loadJavaScriptModule('@evomedien/vitec/container-collapse.js'); + $pageRenderer->addCssFile( + 'EXT:vitec/Resources/Public/Css/backend-container-collapse.css' + ); + } +} diff --git a/packages/vitec/Classes/EventListener/ShowFrontendLayoutBanner.php b/packages/vitec/Classes/EventListener/ShowFrontendLayoutBanner.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Hook/SyncBackendLayoutHook.php b/packages/vitec/Classes/Hook/SyncBackendLayoutHook.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/.msys00000000000000002272de42bf87f8e5 b/packages/vitec/Classes/Service/.msys00000000000000002272de42bf87f8e5 old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/.msys0000000000000000274fb505bf117200 b/packages/vitec/Classes/Service/.msys0000000000000000274fb505bf117200 old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/.msys00000000000000002751b67b19a9c636 b/packages/vitec/Classes/Service/.msys00000000000000002751b67b19a9c636 old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/.msys00000000000000002752b73c4a27d4ba b/packages/vitec/Classes/Service/.msys00000000000000002752b73c4a27d4ba old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/.msys00000000000000002753b7f777b58735 b/packages/vitec/Classes/Service/.msys00000000000000002753b7f777b58735 old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/.msys00000000000000002753b7f978b2a67b b/packages/vitec/Classes/Service/.msys00000000000000002753b7f978b2a67b old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/.msys0000000000000000284b115dd4770044 b/packages/vitec/Classes/Service/.msys0000000000000000284b115dd4770044 old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/Service/ContentElementResolver.php b/packages/vitec/Classes/Service/ContentElementResolver.php old mode 100755 new mode 100644 index 61c7b96..c2b9d24 --- a/packages/vitec/Classes/Service/ContentElementResolver.php +++ b/packages/vitec/Classes/Service/ContentElementResolver.php @@ -14,6 +14,8 @@ use Evomedien\Vitec\UserFunc\SolutionShowJsonRenderer; use Evomedien\Vitec\UserFunc\DownloadcardJsonRenderer; use Evomedien\Vitec\UserFunc\DownloadcardcollectionJsonRenderer; use Evomedien\Vitec\UserFunc\DatasheetsJsonRenderer; +use Evomedien\Vitec\UserFunc\EventlistJsonRenderer; +use Evomedien\Vitec\UserFunc\NewsJsonRenderer; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -73,6 +75,16 @@ final class ContentElementResolver 'vitec_downloadcard' => [DownloadcardJsonRenderer::class, 'downloadcard'], 'vitec_downloadcardcollection' => [DownloadcardcollectionJsonRenderer::class, 'downloadcardcollection'], 'vitec_datasheets' => [DatasheetsJsonRenderer::class, 'datasheets'], + 'vitec_eventlist' => [EventlistJsonRenderer::class, 'eventlist'], + 'news_pi1' => [NewsJsonRenderer::class, 'news'], + 'news_newsliststicky' => [NewsJsonRenderer::class, 'news'], + 'news_newsselectedlist' => [NewsJsonRenderer::class, 'news'], + 'news_newsdetail' => [NewsJsonRenderer::class, 'news'], + 'news_newsdatemenu' => [NewsJsonRenderer::class, 'news'], + 'news_categorylist' => [NewsJsonRenderer::class, 'news'], + 'news_newssearchform' => [NewsJsonRenderer::class, 'news'], + 'news_newssearchresult' => [NewsJsonRenderer::class, 'news'], + 'news_taglist' => [NewsJsonRenderer::class, 'news'], ]; /** diff --git a/packages/vitec/Classes/Service/StructuredDataService.php b/packages/vitec/Classes/Service/StructuredDataService.php old mode 100755 new mode 100644 index 9793c31..3f852cc --- a/packages/vitec/Classes/Service/StructuredDataService.php +++ b/packages/vitec/Classes/Service/StructuredDataService.php @@ -305,6 +305,148 @@ final class StructuredDataService return $video; } + /** + * schema.org FAQPage from a list of question/answer pairs. + * Answers may contain RTE HTML — tags are stripped for the JSON-LD text. + * + * @param list $items + */ + public function buildFaqPage(array $items, string $base): ?array + { + $mainEntity = []; + foreach ($items as $item) { + $question = trim((string)($item['question'] ?? '')); + $answer = trim(strip_tags((string)($item['answer'] ?? ''))); + if ($question === '' || $answer === '') { + continue; + } + $mainEntity[] = [ + '@type' => 'Question', + 'name' => $question, + 'acceptedAnswer' => [ + '@type' => 'Answer', + 'text' => $answer, + ], + ]; + } + + if ($mainEntity === []) { + return null; + } + + return [ + '@type' => 'FAQPage', + 'mainEntity' => $mainEntity, + ]; + } + + /** + * schema.org ExhibitionEvent (trade-show) node from a + * tx_vitec_domain_model_event row. + * + * Google rich-result requirements: name, startDate, location. + * Recommended extras handled here: endDate, description, image, url, + * eventStatus, eventAttendanceMode, organizer. + * + * @param array $e Event DB row + * @param list $imageUrls Absolute or root-relative logo URLs + */ + public function buildEvent(array $e, string $base, array $imageUrls, bool $hasOrganization): ?array + { + $name = trim((string)($e['title'] ?? '')); + $start = (int)($e['eventstart'] ?? 0); + if ($name === '' || $start === 0) { + return null; + } + + $event = [ + '@type' => 'ExhibitionEvent', + 'name' => $name, + 'startDate' => date('Y-m-d', $start), + ]; + + $end = (int)($e['eventend'] ?? 0); + if ($end > 0) { + $event['endDate'] = date('Y-m-d', $end); + } + + $description = trim(strip_tags((string)($e['description'] ?? ''))); + if ($description === '') { + $description = trim((string)($e['teaser'] ?? '')); + } + if ($description !== '') { + $event['description'] = $description; + } + + // Location: Place with venue + city/country, or VirtualLocation for online. + $mode = (string)($e['attendancemode'] ?? 'offline'); + $venue = trim((string)($e['venue'] ?? '')); + $city = trim((string)($e['city'] ?? '')); + $country = trim((string)($e['country'] ?? '')); + + if ($mode === 'online') { + $url = trim((string)($e['eventurl'] ?? '')); + if ($url !== '') { + $event['location'] = [ + '@type' => 'VirtualLocation', + 'url' => $this->absUrl($url, $base), + ]; + } + } else { + $address = array_filter([ + '@type' => 'PostalAddress', + 'addressLocality' => $city !== '' ? $city : null, + 'addressCountry' => $country !== '' ? $country : null, + ]); + $place = array_filter([ + '@type' => 'Place', + 'name' => $venue !== '' ? $venue : ($city !== '' ? $city : null), + 'address' => count($address) > 1 ? $address : null, + ]); + if (count($place) > 1) { + $event['location'] = $place; + } + } + + $statusMap = [ + 'scheduled' => 'https://schema.org/EventScheduled', + 'cancelled' => 'https://schema.org/EventCancelled', + 'postponed' => 'https://schema.org/EventPostponed', + 'rescheduled' => 'https://schema.org/EventRescheduled', + 'movedonline' => 'https://schema.org/EventMovedOnline', + ]; + $event['eventStatus'] = $statusMap[(string)($e['eventstatus'] ?? 'scheduled')] ?? $statusMap['scheduled']; + + $modeMap = [ + 'offline' => 'https://schema.org/OfflineEventAttendanceMode', + 'online' => 'https://schema.org/OnlineEventAttendanceMode', + 'mixed' => 'https://schema.org/MixedEventAttendanceMode', + ]; + $event['eventAttendanceMode'] = $modeMap[$mode] ?? $modeMap['offline']; + + $images = []; + foreach ($imageUrls as $imageUrl) { + $abs = $this->absUrl((string)$imageUrl, $base); + if ($abs !== '') { + $images[] = $abs; + } + } + if ($images !== []) { + $event['image'] = $images; + } + + $eventUrl = trim((string)($e['eventurl'] ?? '')); + if ($eventUrl !== '' && !str_starts_with($eventUrl, 't3://')) { + $event['url'] = $this->absUrl($eventUrl, $base); + } + + if ($hasOrganization) { + $event['organizer'] = ['@id' => $base . '/#organization']; + } + + return $event; + } + /** * Wrap one or more schema nodes into a single @graph document string. * diff --git a/packages/vitec/Classes/Service/UsecaseSerializer.php b/packages/vitec/Classes/Service/UsecaseSerializer.php new file mode 100644 index 0000000..b7c793b --- /dev/null +++ b/packages/vitec/Classes/Service/UsecaseSerializer.php @@ -0,0 +1,530 @@ + lean card data for the list plugin + * serializeDetail() -> full detail (hero, content elements, related, seo) + * + * Inline content elements are resolved flat; the VITEC Columns content block + * (vitec_columns) is resolved specially into { header…, layout, columns:{…} }. + * + * All relation/FAL resolution lives here so the List/Show UserFunc renderers + * stay thin. Every resolver is exception-safe and returns null/[] on failure. + */ +final class UsecaseSerializer +{ + private const TABLE = 'tx_vitec_domain_model_usecase'; + private const IMAGE_WIDTHS = [400, 800, 1200, 1600]; + private const COLUMNS_CTYPE = 'vitec_columns'; + + /** + * @param array $u + * @return array + */ + public function serializeListItem(array $u): array + { + $uid = (int)$u['uid']; + + return [ + 'uid' => $uid, + 'title' => (string)($u['title'] ?? ''), + 'slug' => (string)($u['slug'] ?? ''), + 'subtitle' => (string)($u['subtitle'] ?? ''), + 'teaser' => (string)($u['teaser'] ?? ''), + 'cardImage' => $this->image($uid, 'card_image'), + 'customerLogo' => $this->image($uid, 'customer_logo'), + 'market' => $this->market((int)($u['market'] ?? 0)), + 'categories' => $this->categories($uid), + 'featured' => (bool)($u['featured'] ?? false), + 'layoutVariant' => (string)($u['layout_variant'] ?? 'standard'), + 'backgroundVariant' => (string)($u['background_variant'] ?? 'none'), + ]; + } + + /** + * @param array $u + * @return array + */ + public function serializeDetail(array $u): array + { + $uid = (int)$u['uid']; + $base = $this->serializeListItem($u); + + return array_merge($base, [ + 'hero' => [ + 'bgImage' => $this->image($uid, 'hero_bgimage'), + 'smallImage' => $this->image($uid, 'hero_small_image'), + 'video' => $this->video($uid, 'hero_video'), + 'overlayColor' => (string)($u['hero_overlay_color'] ?? ''), + 'overlayOpacity' => (float)($u['hero_overlay_opacity'] ?? 0), + 'layout' => (string)($u['hero_layout'] ?? 'fullscreen'), + 'textTheme' => (string)($u['text_theme'] ?? 'light'), + ], + 'contentElements' => $this->contentElements($uid), + 'related' => [ + 'show' => (bool)($u['show_related'] ?? true), + 'market' => $base['market'], + 'solutions' => $this->relationMulti('tx_vitec_usecase_solution_mm', 'tx_vitec_domain_model_solution', $uid), + 'products' => $this->relationMulti('tx_vitec_usecase_product_mm', 'tx_vitec_domain_model_product', $uid), + 'categories' => $base['categories'], + ], + 'seo' => $this->seo($u), + 'appearance' => [ + 'layoutVariant' => (string)($u['layout_variant'] ?? 'standard'), + 'backgroundVariant' => (string)($u['background_variant'] ?? 'none'), + 'accentColor' => (string)($u['accent_color'] ?? ''), + 'featured' => (bool)($u['featured'] ?? false), + 'heroLayout' => (string)($u['hero_layout'] ?? 'fullscreen'), + 'textTheme' => (string)($u['text_theme'] ?? 'light'), + ], + ]); + } + + // ---------------------------------------------------------------- images + + /** + * FAL image (with srcset). $table defaults to the usecase table but can be + * a content-block collection table (for Columns items). + * + * @return array|null + */ + public function image(int $recordUid, string $fieldName, ?string $table = null): ?array + { + try { + $table = $table ?? self::TABLE; + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_file_reference'); + $ref = $qb + ->select('sfr.uid', 'sfr.title', 'sfr.description', 'sfr.alternative', 'sfr.crop') + ->from('sys_file_reference', 'sfr') + ->where( + $qb->expr()->eq('sfr.tablenames', $qb->createNamedParameter($table, ParameterType::STRING)), + $qb->expr()->eq('sfr.fieldname', $qb->createNamedParameter($fieldName, ParameterType::STRING)), + $qb->expr()->eq('sfr.uid_foreign', $qb->createNamedParameter($recordUid, ParameterType::INTEGER)), + $qb->expr()->eq('sfr.deleted', 0), + $qb->expr()->eq('sfr.hidden', 0) + ) + ->orderBy('sfr.sorting_foreign') + ->setMaxResults(1) + ->executeQuery() + ->fetchAssociative(); + + if (!$ref) { + return null; + } + + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); + $imageService = GeneralUtility::makeInstance(ImageService::class); + $fileReference = $resourceFactory->getFileReferenceObject((int)$ref['uid']); + + $srcset = []; + foreach (self::IMAGE_WIDTHS as $width) { + $variant = $imageService->applyProcessingInstructions( + $fileReference, + ['width' => $width, 'crop' => $ref['crop'] ?? null] + ); + $srcset[] = [ + 'url' => $imageService->getImageUri($variant), + 'width' => $width, + 'descriptor' => $width . 'w', + ]; + } + + $default = $imageService->applyProcessingInstructions( + $fileReference, + ['width' => 800, 'crop' => $ref['crop'] ?? null] + ); + + return [ + 'uid' => (int)$ref['uid'], + 'url' => $imageService->getImageUri($default), + 'title' => (string)($ref['title'] ?? ''), + 'alternative' => (string)($ref['alternative'] ?? ''), + 'description' => (string)($ref['description'] ?? ''), + 'srcset' => $srcset, + 'properties' => [ + 'width' => $fileReference->getProperty('width'), + 'height' => $fileReference->getProperty('height'), + 'mimeType' => $fileReference->getProperty('mime_type'), + ], + ]; + } catch (\Throwable $e) { + return null; + } + } + + /** + * FAL video (public URL only). $table as in image(). + * + * @return array|null + */ + public function video(int $recordUid, string $fieldName, ?string $table = null): ?array + { + try { + $table = $table ?? self::TABLE; + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_file_reference'); + $ref = $qb + ->select('uid', 'title', 'description') + ->from('sys_file_reference') + ->where( + $qb->expr()->eq('tablenames', $qb->createNamedParameter($table, ParameterType::STRING)), + $qb->expr()->eq('fieldname', $qb->createNamedParameter($fieldName, ParameterType::STRING)), + $qb->expr()->eq('uid_foreign', $qb->createNamedParameter($recordUid, ParameterType::INTEGER)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) + ) + ->orderBy('sorting_foreign') + ->setMaxResults(1) + ->executeQuery() + ->fetchAssociative(); + + if (!$ref) { + return null; + } + + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); + $fileReference = $resourceFactory->getFileReferenceObject((int)$ref['uid']); + + return [ + 'uid' => (int)$ref['uid'], + 'url' => $fileReference->getPublicUrl(), + 'title' => (string)($ref['title'] ?? ''), + 'mimeType' => $fileReference->getProperty('mime_type'), + ]; + } catch (\Throwable $e) { + return null; + } + } + + // ------------------------------------------------------------- relations + + /** + * Single market (foreign_table, no MM) -> title/slug. + * + * @return array|null + */ + public function market(int $marketUid): ?array + { + if ($marketUid <= 0) { + return null; + } + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_vitec_domain_model_market'); + $row = $qb + ->select('uid', 'title', 'subtitle', 'teaser') + ->from('tx_vitec_domain_model_market') + ->where( + $qb->expr()->eq('uid', $qb->createNamedParameter($marketUid, ParameterType::INTEGER)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) + ) + ->executeQuery() + ->fetchAssociative(); + + if (!$row) { + return null; + } + + return [ + 'uid' => (int)$row['uid'], + 'title' => (string)($row['title'] ?? ''), + 'subtitle' => (string)($row['subtitle'] ?? ''), + 'teaser' => (string)($row['teaser'] ?? ''), + ]; + } catch (\Throwable $e) { + return null; + } + } + + /** + * n:n relation resolved through an MM table -> [{uid,title}, …]. + * + * @return array> + */ + public function relationMulti(string $mmTable, string $foreignTable, int $usecaseUid): array + { + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable($foreignTable); + $rows = $qb + ->select('f.uid', 'f.title') + ->from($foreignTable, 'f') + ->join('f', $mmTable, 'mm', 'mm.uid_foreign = f.uid') + ->where( + $qb->expr()->eq('mm.uid_local', $qb->createNamedParameter($usecaseUid, ParameterType::INTEGER)), + $qb->expr()->eq('f.deleted', 0), + $qb->expr()->eq('f.hidden', 0) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + return array_map(static fn ($r) => [ + 'uid' => (int)$r['uid'], + 'title' => (string)($r['title'] ?? ''), + ], $rows); + } catch (\Throwable $e) { + return []; + } + } + + /** + * System categories (sys_category MM) -> [{uid,title,description}, …]. + * + * @return array> + */ + public function categories(int $usecaseUid): array + { + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + $rows = $qb + ->select('c.uid', 'c.title', 'c.description') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid AND mm.tablenames = ' . + $qb->createNamedParameter(self::TABLE, ParameterType::STRING) . + ' AND mm.fieldname = ' . + $qb->createNamedParameter('categories', ParameterType::STRING) + ) + ->where( + $qb->expr()->eq('mm.uid_foreign', $qb->createNamedParameter($usecaseUid, ParameterType::INTEGER)), + $qb->expr()->eq('c.deleted', 0), + $qb->expr()->eq('c.hidden', 0) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + return array_map(static fn ($c) => [ + 'uid' => (int)$c['uid'], + 'title' => (string)($c['title'] ?? ''), + 'description' => (string)($c['description'] ?? ''), + ], $rows); + } catch (\Throwable $e) { + return []; + } + } + + // ------------------------------------------------------- content elements + + /** + * Inline content elements (tt_content owned via tx_vitec_usecase_content). + * Flat CEs are normalised; a VITEC Columns element is resolved specially. + * + * @return array> + */ + public function contentElements(int $usecaseUid): array + { + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tt_content'); + $rows = $qb + ->select('*') + ->from('tt_content') + ->where( + $qb->expr()->eq('tx_vitec_usecase_content', $qb->createNamedParameter($usecaseUid, ParameterType::INTEGER)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) + ) + ->orderBy('sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + $out = []; + foreach ($rows as $row) { + $resolved = $this->resolveInlineElement($row); + if ($resolved !== null) { + $out[] = $resolved; + } + } + return $out; + } catch (\Throwable $e) { + return []; + } + } + + /** + * @param array $row + * @return array|null + */ + private function resolveInlineElement(array $row): ?array + { + if ((string)($row['CType'] ?? '') === self::COLUMNS_CTYPE) { + return $this->resolveColumnsElement($row); + } + return ContentElementResolver::normaliseRecord($row); + } + + /** + * VITEC Columns content block -> { header…, layout, columns:{left,right} }. + * Items live in a content-blocks collection table (discovered from TCA) and + * carry a `column` (left/right) plus a typed payload. + * + * @param array $row + * @return array + */ + private function resolveColumnsElement(array $row): array + { + $uid = (int)$row['uid']; + + $left = []; + $right = []; + + $table = $this->collectionTable('vitec_items') ?? $this->collectionTable('items'); + if ($table !== null) { + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); + $items = $qb + ->select('*') + ->from($table) + ->where( + $qb->expr()->eq('foreign_table_parent_uid', $qb->createNamedParameter($uid, ParameterType::INTEGER)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) + ) + ->orderBy('sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($items as $it) { + $column = (string)($it['vitec_column'] ?? $it['column'] ?? 'left'); + $resolved = $this->resolveColumnItem($it, $table); + if ($column === 'right') { + $right[] = $resolved; + } else { + $left[] = $resolved; + } + } + } catch (\Throwable $e) { + // collection table not ready / query failed -> empty columns + } + } + + return [ + 'id' => $uid, + 'type' => self::COLUMNS_CTYPE, + 'colPos' => (int)($row['colPos'] ?? 0), + 'sorting' => (int)($row['sorting'] ?? 0), + 'header' => (string)($row['header'] ?? ''), + 'subheader' => (string)($row['subheader'] ?? ''), + 'headerLayout' => (int)($row['header_layout'] ?? 0), + 'headerPosition' => (string)($row['header_position'] ?? ''), + 'headerLink' => (string)($row['header_link'] ?? ''), + 'layout' => (string)($row['vitec_layout'] ?? $row['layout'] ?? 'cols_50_50'), + 'columns' => [ + 'left' => $left, + 'right' => $right, + ], + ]; + } + + /** + * @param array $it + * @return array + */ + private function resolveColumnItem(array $it, string $table): array + { + $uid = (int)$it['uid']; + $get = static fn (string $k): string => (string)($it['vitec_' . $k] ?? $it[$k] ?? ''); + + $imageField = array_key_exists('vitec_image', $it) ? 'vitec_image' : 'image'; + $videoField = array_key_exists('vitec_video', $it) ? 'vitec_video' : 'video'; + + return [ + 'type' => $get('item_type') !== '' ? $get('item_type') : 'text', + 'headline' => $get('headline'), + 'text' => $get('text'), + 'image' => $this->image($uid, $imageField, $table), + 'video' => $this->video($uid, $videoField, $table), + 'link' => $get('link'), + 'linkLabel' => $get('link_label'), + ]; + } + + /** + * Resolve a content-blocks collection field's storage table from TCA. + */ + private function collectionTable(string $field): ?string + { + $t = $GLOBALS['TCA']['tt_content']['columns'][$field]['config']['foreign_table'] ?? null; + return (is_string($t) && $t !== '') ? $t : null; + } + + // ------------------------------------------------------------------- seo + + /** + * SEO bundle with fallback resolution (title/teaser/card/hero images). + * + * @param array $u + * @return array + */ + public function seo(array $u): array + { + $uid = (int)$u['uid']; + + $title = $this->firstNonEmpty([(string)($u['seo_title'] ?? ''), (string)($u['title'] ?? '')]); + $desc = $this->firstNonEmpty([(string)($u['seo_description'] ?? ''), (string)($u['teaser'] ?? '')]); + + $ogTitle = $this->firstNonEmpty([(string)($u['og_title'] ?? ''), $title]); + $ogDesc = $this->firstNonEmpty([(string)($u['og_description'] ?? ''), $desc]); + $ogImage = $this->image($uid, 'og_image') + ?? $this->image($uid, 'card_image') + ?? $this->image($uid, 'hero_bgimage'); + + $twTitle = $this->firstNonEmpty([(string)($u['twitter_title'] ?? ''), $ogTitle]); + $twDesc = $this->firstNonEmpty([(string)($u['twitter_description'] ?? ''), $ogDesc]); + $twImage = $this->image($uid, 'twitter_image') ?? $ogImage; + + return [ + 'title' => $title, + 'description' => $desc, + 'canonical' => (string)($u['canonical_link'] ?? ''), + 'robots' => [ + 'noIndex' => (bool)($u['no_index'] ?? false), + 'noFollow' => (bool)($u['no_follow'] ?? false), + ], + 'openGraph' => [ + 'title' => $ogTitle, + 'description' => $ogDesc, + 'image' => $ogImage, + ], + 'twitter' => [ + 'title' => $twTitle, + 'description' => $twDesc, + 'image' => $twImage, + ], + ]; + } + + /** + * @param array $candidates + */ + private function firstNonEmpty(array $candidates): string + { + foreach ($candidates as $c) { + $c = trim($c); + if ($c !== '') { + return $c; + } + } + return ''; + } +} diff --git a/packages/vitec/Classes/UserFunc/DatasheetsJsonRenderer.php b/packages/vitec/Classes/UserFunc/DatasheetsJsonRenderer.php old mode 100755 new mode 100644 index d82c17b..cbd3a75 --- a/packages/vitec/Classes/UserFunc/DatasheetsJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/DatasheetsJsonRenderer.php @@ -7,6 +7,7 @@ namespace Evomedien\Vitec\UserFunc; use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use Doctrine\DBAL\ParameterType; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Service\FlexFormService; @@ -49,13 +50,7 @@ class DatasheetsJsonRenderer ->from('tt_content') ->where( $qb->expr()->eq('pid', $qb->createNamedParameter($pageId, ParameterType::INTEGER)), - $qb->expr()->or( - $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_datasheets', ParameterType::STRING)), - $qb->expr()->and( - $qb->expr()->eq('CType', $qb->createNamedParameter('list', ParameterType::STRING)), - $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_datasheets', ParameterType::STRING)) - ) - ), + $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_datasheets', ParameterType::STRING)), $qb->expr()->eq('deleted', 0), $qb->expr()->eq('hidden', 0) ) @@ -118,6 +113,7 @@ class DatasheetsJsonRenderer $response['debug'] = [ 'productCount' => count($itemsOut), 'settings' => $settings, + 'fallbackFiles' => $this->collectFallbackFilesFromItems($itemsOut), ]; } @@ -259,6 +255,7 @@ class DatasheetsJsonRenderer private function serializeDatasheet(array $download): array { $uid = (int)$download['uid']; + $filetype = $this->getDownloadFileType($uid); return [ 'uid' => $uid, 'title' => (string)($download['title'] ?? ''), @@ -266,10 +263,48 @@ class DatasheetsJsonRenderer 'teaser' => (string)($download['teaser'] ?? ''), 'description' => (string)($download['description'] ?? ''), 'tstamp' => (int)($download['tstamp'] ?? 0), - 'file' => $this->getDownloadFile($uid), + 'filetype' => $filetype, + 'file' => $this->getDownloadFile($uid, (string)($download['fileprefix'] ?? ''), $filetype), ]; } + private function getDownloadFileType(int $downloadUid): string + { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + $categories = $qb + ->select('c.filetype') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid AND mm.tablenames = ' . + $qb->createNamedParameter('tx_vitec_domain_model_download', ParameterType::STRING) . + ' AND mm.fieldname = ' . + $qb->createNamedParameter('categories', ParameterType::STRING) + ) + ->where( + $qb->expr()->eq('mm.uid_foreign', $qb->createNamedParameter($downloadUid, ParameterType::INTEGER)), + $qb->expr()->eq('c.deleted', 0), + $qb->expr()->eq('c.hidden', 0), + $qb->expr()->eq('c.parent', $qb->createNamedParameter(4, ParameterType::INTEGER)) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($categories as $category) { + $filetype = trim((string)($category['filetype'] ?? '')); + if ($filetype !== '') { + return $filetype; + } + } + + return ''; + } + /** * @return array|null */ @@ -356,7 +391,7 @@ class DatasheetsJsonRenderer /** * @return array|null */ - private function getDownloadFile(int $downloadUid): ?array + private function getDownloadFile(int $downloadUid, string $fileprefix = '', string $filetype = ''): ?array { $qb = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('sys_file_reference'); @@ -378,7 +413,7 @@ class DatasheetsJsonRenderer ->fetchAssociative(); if (!$row) { - return null; + return $this->resolveFileByConvention($fileprefix, $filetype); } return [ @@ -392,4 +427,129 @@ class DatasheetsJsonRenderer 'description' => (string)($row['description'] ?? ''), ]; } + + /** + * Resolve file from naming convention: + * [fileprefix]__[filetype]__[number]-[letter].ext + * and pick highest number + highest letter. + * + * @return array|null + */ + private function resolveFileByConvention(string $fileprefix, string $filetype): ?array + { + $fileprefix = trim($fileprefix); + $filetype = trim($filetype); + if ($fileprefix === '' || $filetype === '') { + return null; + } + + $baseDir = Environment::getPublicPath() . '/fileadmin/downloads/Collateral'; + if (!is_dir($baseDir) || !is_readable($baseDir)) { + return null; + } + + $escapedPrefix = preg_quote($fileprefix, '/'); + $escapedType = preg_quote($filetype, '/'); + $pattern = '/^' . $escapedPrefix . '__' . $escapedType . '__(\\d+)-([A-Za-z]+)\\.([A-Za-z0-9]+)$/'; + + $bestFile = null; + $bestNumber = -1; + $bestLetterRank = -1; + + $entries = scandir($baseDir); + if ($entries === false) { + return null; + } + + foreach ($entries as $entry) { + if (!is_string($entry) || $entry === '.' || $entry === '..') { + continue; + } + + if (!preg_match($pattern, $entry, $matches)) { + continue; + } + + $number = (int)$matches[1]; + $letter = strtoupper($matches[2]); + $letterRank = $this->letterSequenceToRank($letter); + + if ($number > $bestNumber || ($number === $bestNumber && $letterRank > $bestLetterRank)) { + $bestNumber = $number; + $bestLetterRank = $letterRank; + $bestFile = $entry; + } + } + + if ($bestFile === null) { + return null; + } + + $fullPath = $baseDir . '/' . $bestFile; + if (!is_file($fullPath) || !is_readable($fullPath)) { + return null; + } + + $extension = strtolower(pathinfo($bestFile, PATHINFO_EXTENSION)); + $mimeType = function_exists('mime_content_type') ? (string)(mime_content_type($fullPath) ?: '') : ''; + + return [ + 'uid' => 0, + 'name' => $bestFile, + 'url' => '/fileadmin/downloads/Collateral/' . rawurlencode($bestFile), + 'size' => (int)(filesize($fullPath) ?: 0), + 'extension' => $extension, + 'mimeType' => $mimeType, + 'title' => '', + 'description' => '', + ]; + } + + private function letterSequenceToRank(string $letters): int + { + $rank = 0; + $letters = strtoupper($letters); + $length = strlen($letters); + + for ($i = 0; $i < $length; $i++) { + $char = ord($letters[$i]); + if ($char < 65 || $char > 90) { + continue; + } + + $rank = ($rank * 26) + ($char - 64); + } + + return $rank; + } + + /** + * @param array> $items + * @return array> + */ + private function collectFallbackFilesFromItems(array $items): array + { + $fallbackFiles = []; + + foreach ($items as $item) { + $datasheet = $item['datasheet'] ?? null; + if (!is_array($datasheet)) { + continue; + } + + $file = $datasheet['file'] ?? null; + if (!is_array($file) || (int)($file['uid'] ?? 1) !== 0) { + continue; + } + + $fallbackFiles[] = [ + 'datasheetUid' => (int)($datasheet['uid'] ?? 0), + 'name' => (string)($file['name'] ?? ''), + 'url' => (string)($file['url'] ?? ''), + 'source' => 'naming-convention-fallback', + ]; + } + + return $fallbackFiles; + } } diff --git a/packages/vitec/Classes/UserFunc/DownloadcardJsonRenderer.php b/packages/vitec/Classes/UserFunc/DownloadcardJsonRenderer.php old mode 100755 new mode 100644 index eff7c91..a24ba70 --- a/packages/vitec/Classes/UserFunc/DownloadcardJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/DownloadcardJsonRenderer.php @@ -7,6 +7,7 @@ namespace Evomedien\Vitec\UserFunc; use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use Doctrine\DBAL\ParameterType; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -44,20 +45,12 @@ class DownloadcardJsonRenderer $qb = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('tt_content'); - // After v14 migration the CType is the plugin signature; for legacy - // (unmigrated) records the CType is still "list" with list_type set. $rows = $qb ->select('*') ->from('tt_content') ->where( $qb->expr()->eq('pid', $qb->createNamedParameter($pageId, ParameterType::INTEGER)), - $qb->expr()->or( - $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_downloadcard', ParameterType::STRING)), - $qb->expr()->and( - $qb->expr()->eq('CType', $qb->createNamedParameter('list', ParameterType::STRING)), - $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_downloadcard', ParameterType::STRING)) - ) - ), + $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_downloadcard', ParameterType::STRING)), $qb->expr()->eq('deleted', 0), $qb->expr()->eq('hidden', 0) ) @@ -106,14 +99,17 @@ class DownloadcardJsonRenderer : ''; } + $serializedDownload = $this->serializeDownload($download); + $response = [ 'mode' => 'single', - 'download' => $this->serializeDownload($download), + 'download' => $serializedDownload, 'settings' => $settingsOut, ]; if ($debugMode) { $response['debug'] = [ 'pageId' => $pageId, 'downloadUid' => $downloadUid, 'settings' => $settings, + 'fallbackFiles' => $this->collectFallbackFilesFromDownloads([$serializedDownload]), ]; } return json_encode($response); @@ -123,11 +119,12 @@ class DownloadcardJsonRenderer if ($productUid > 0) { $downloads = $this->fetchDownloadsForProduct($productUid); $product = $this->fetchProductContext($productUid); + $serializedDownloads = array_map(fn($r) => $this->serializeDownload($r), $downloads); $response = [ 'mode' => 'product-downloads', 'product' => $product, - 'downloads' => array_map(fn($r) => $this->serializeDownload($r), $downloads), + 'downloads' => $serializedDownloads, 'settings' => $settingsOut, ]; if ($debugMode) { @@ -136,6 +133,7 @@ class DownloadcardJsonRenderer 'productUid' => $productUid, 'downloadCount' => count($downloads), 'settings' => $settings, + 'fallbackFiles' => $this->collectFallbackFilesFromDownloads($serializedDownloads), ]; } return json_encode($response); @@ -248,6 +246,8 @@ class DownloadcardJsonRenderer protected function serializeDownload(array $download): array { $uid = (int)$download['uid']; + $fileprefix = (string)($download['fileprefix'] ?? ''); + $filetype = $this->getDownloadFileType($uid); return [ 'uid' => $uid, @@ -258,22 +258,60 @@ class DownloadcardJsonRenderer 'keywords' => (string)($download['keywords'] ?? ''), 'icon' => (string)($download['icon'] ?? ''), 'filepath' => (string)($download['filepath'] ?? ''), - 'fileprefix' => (string)($download['fileprefix'] ?? ''), + 'fileprefix' => $fileprefix, + 'filetype' => $filetype, 'private_download' => (bool)($download['private_download'] ?? false), 'hideonapp' => (bool)($download['hideonapp'] ?? false), 'hideonwebsite' => (bool)($download['hideonwebsite'] ?? false), 'hideondatasheets' => (bool)($download['hideondatasheets'] ?? false), 'hideonproducts' => (bool)($download['hideonproducts'] ?? false), - 'file' => $this->getDownloadFile($uid), + 'file' => $this->getDownloadFile($uid, $fileprefix, $filetype), ]; } + private function getDownloadFileType(int $downloadUid): string + { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + $categories = $qb + ->select('c.filetype') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid AND mm.tablenames = ' . + $qb->createNamedParameter('tx_vitec_domain_model_download', ParameterType::STRING) . + ' AND mm.fieldname = ' . + $qb->createNamedParameter('categories', ParameterType::STRING) + ) + ->where( + $qb->expr()->eq('mm.uid_foreign', $qb->createNamedParameter($downloadUid, ParameterType::INTEGER)), + $qb->expr()->eq('c.deleted', 0), + $qb->expr()->eq('c.hidden', 0), + $qb->expr()->eq('c.parent', $qb->createNamedParameter(4, ParameterType::INTEGER)) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($categories as $category) { + $filetype = trim((string)($category['filetype'] ?? '')); + if ($filetype !== '') { + return $filetype; + } + } + + return ''; + } + /** * Resolve the FAL file reference (fieldname=file) for a download. * * @return array|null */ - protected function getDownloadFile(int $downloadUid): ?array + protected function getDownloadFile(int $downloadUid, string $fileprefix = '', string $filetype = ''): ?array { $qb = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('sys_file_reference'); @@ -295,7 +333,7 @@ class DownloadcardJsonRenderer ->fetchAssociative(); if (!$row) { - return null; + return $this->resolveFileByConvention($fileprefix, $filetype); } $thumbnailUrl = null; @@ -324,4 +362,124 @@ class DownloadcardJsonRenderer 'description' => (string)($row['description'] ?? ''), ]; } + + /** + * @return array|null + */ + private function resolveFileByConvention(string $fileprefix, string $filetype): ?array + { + $fileprefix = trim($fileprefix); + $filetype = trim($filetype); + if ($fileprefix === '' || $filetype === '') { + return null; + } + + $baseDir = Environment::getPublicPath() . '/fileadmin/downloads/Collateral'; + if (!is_dir($baseDir) || !is_readable($baseDir)) { + return null; + } + + $escapedPrefix = preg_quote($fileprefix, '/'); + $escapedType = preg_quote($filetype, '/'); + $pattern = '/^' . $escapedPrefix . '__' . $escapedType . '__(\\d+)-([A-Za-z]+)\\.([A-Za-z0-9]+)$/'; + + $bestFile = null; + $bestNumber = -1; + $bestLetterRank = -1; + + $entries = scandir($baseDir); + if ($entries === false) { + return null; + } + + foreach ($entries as $entry) { + if (!is_string($entry) || $entry === '.' || $entry === '..') { + continue; + } + + if (!preg_match($pattern, $entry, $matches)) { + continue; + } + + $number = (int)$matches[1]; + $letterRank = $this->letterSequenceToRank((string)$matches[2]); + + if ($number > $bestNumber || ($number === $bestNumber && $letterRank > $bestLetterRank)) { + $bestNumber = $number; + $bestLetterRank = $letterRank; + $bestFile = $entry; + } + } + + if ($bestFile === null) { + return null; + } + + $fullPath = $baseDir . '/' . $bestFile; + if (!is_file($fullPath) || !is_readable($fullPath)) { + return null; + } + + $extension = strtolower(pathinfo($bestFile, PATHINFO_EXTENSION)); + $mimeType = function_exists('mime_content_type') ? (string)(mime_content_type($fullPath) ?: '') : ''; + + return [ + 'uid' => 0, + 'name' => $bestFile, + 'url' => '/fileadmin/downloads/Collateral/' . rawurlencode($bestFile), + 'thumbnail' => null, + 'size' => (int)(filesize($fullPath) ?: 0), + 'extension' => $extension, + 'mimeType' => $mimeType, + 'title' => '', + 'description' => '', + ]; + } + + private function letterSequenceToRank(string $letters): int + { + $rank = 0; + $letters = strtoupper($letters); + $length = strlen($letters); + + for ($i = 0; $i < $length; $i++) { + $char = ord($letters[$i]); + if ($char < 65 || $char > 90) { + continue; + } + + $rank = ($rank * 26) + ($char - 64); + } + + return $rank; + } + + /** + * @param array> $downloads + * @return array> + */ + private function collectFallbackFilesFromDownloads(array $downloads): array + { + $fallbackFiles = []; + + foreach ($downloads as $download) { + $file = $download['file'] ?? null; + if (!is_array($file)) { + continue; + } + + if ((int)($file['uid'] ?? 1) !== 0) { + continue; + } + + $fallbackFiles[] = [ + 'downloadUid' => (int)($download['uid'] ?? 0), + 'name' => (string)($file['name'] ?? ''), + 'url' => (string)($file['url'] ?? ''), + 'source' => 'naming-convention-fallback', + ]; + } + + return $fallbackFiles; + } } diff --git a/packages/vitec/Classes/UserFunc/DownloadcardcollectionJsonRenderer.php b/packages/vitec/Classes/UserFunc/DownloadcardcollectionJsonRenderer.php old mode 100755 new mode 100644 index e742ff5..64219da --- a/packages/vitec/Classes/UserFunc/DownloadcardcollectionJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/DownloadcardcollectionJsonRenderer.php @@ -7,6 +7,7 @@ namespace Evomedien\Vitec\UserFunc; use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use Doctrine\DBAL\ParameterType; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Resource\ResourceFactory; @@ -96,13 +97,14 @@ class DownloadcardcollectionJsonRenderer // --- Downloads: comma-separated UID list from settings.download --- $downloadUids = $this->parseUidList($settings['download'] ?? ''); $downloads = $downloadUids === [] ? [] : $this->fetchDownloadsByUids($downloadUids); + $serializedDownloads = array_map(fn($r) => $this->serializeDownload($r), $downloads); // --- Header image (inline FAL on this tt_content element, fieldname=image) --- $image = $this->getCollectionImage($ttContentUid); $response = [ 'image' => $image, - 'downloads' => array_map(fn($r) => $this->serializeDownload($r), $downloads), + 'downloads' => $serializedDownloads, 'settings' => $settingsOut, ]; @@ -112,6 +114,7 @@ class DownloadcardcollectionJsonRenderer 'downloadUids' => $downloadUids, 'downloadCount' => count($downloads), 'settings' => $settings, + 'fallbackFiles' => $this->collectFallbackFilesFromDownloads($serializedDownloads), ]; } @@ -212,7 +215,6 @@ class DownloadcardcollectionJsonRenderer ); $srcset[] = [ 'url' => $imageService->getImageUri($variant), - 'thumbnail' => $thumbnailUrl, 'width' => $width, 'descriptor' => $width . 'w', ]; @@ -226,7 +228,6 @@ class DownloadcardcollectionJsonRenderer return [ 'uid' => (int)$fileRefData['uid'], 'url' => $imageService->getImageUri($default), - 'thumbnail' => $thumbnailUrl, 'title' => $fileRefData['title'] ?? '', 'alternative' => $fileRefData['alternative'] ?? '', 'description' => $fileRefData['description'] ?? '', @@ -249,6 +250,8 @@ class DownloadcardcollectionJsonRenderer protected function serializeDownload(array $download): array { $uid = (int)$download['uid']; + $fileprefix = (string)($download['fileprefix'] ?? ''); + $filetype = $this->getDownloadFileType($uid); return [ 'uid' => $uid, @@ -259,22 +262,60 @@ class DownloadcardcollectionJsonRenderer 'keywords' => (string)($download['keywords'] ?? ''), 'icon' => (string)($download['icon'] ?? ''), 'filepath' => (string)($download['filepath'] ?? ''), - 'fileprefix' => (string)($download['fileprefix'] ?? ''), + 'fileprefix' => $fileprefix, + 'filetype' => $filetype, 'private_download' => (bool)($download['private_download'] ?? false), 'hideonapp' => (bool)($download['hideonapp'] ?? false), 'hideonwebsite' => (bool)($download['hideonwebsite'] ?? false), 'hideondatasheets' => (bool)($download['hideondatasheets'] ?? false), 'hideonproducts' => (bool)($download['hideonproducts'] ?? false), - 'file' => $this->getDownloadFile($uid), + 'file' => $this->getDownloadFile($uid, $fileprefix, $filetype), ]; } + private function getDownloadFileType(int $downloadUid): string + { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + $categories = $qb + ->select('c.filetype') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid AND mm.tablenames = ' . + $qb->createNamedParameter('tx_vitec_domain_model_download', ParameterType::STRING) . + ' AND mm.fieldname = ' . + $qb->createNamedParameter('categories', ParameterType::STRING) + ) + ->where( + $qb->expr()->eq('mm.uid_foreign', $qb->createNamedParameter($downloadUid, ParameterType::INTEGER)), + $qb->expr()->eq('c.deleted', 0), + $qb->expr()->eq('c.hidden', 0), + $qb->expr()->eq('c.parent', $qb->createNamedParameter(4, ParameterType::INTEGER)) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($categories as $category) { + $filetype = trim((string)($category['filetype'] ?? '')); + if ($filetype !== '') { + return $filetype; + } + } + + return ''; + } + /** * Resolve the FAL file reference (fieldname=file) for a download. * * @return array|null */ - protected function getDownloadFile(int $downloadUid): ?array + protected function getDownloadFile(int $downloadUid, string $fileprefix = '', string $filetype = ''): ?array { $qb = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('sys_file_reference'); @@ -296,7 +337,7 @@ class DownloadcardcollectionJsonRenderer ->fetchAssociative(); if (!$row) { - return null; + return $this->resolveFileByConvention($fileprefix, $filetype); } @@ -325,4 +366,124 @@ class DownloadcardcollectionJsonRenderer 'description' => (string)($row['description'] ?? ''), ]; } + + /** + * @return array|null + */ + private function resolveFileByConvention(string $fileprefix, string $filetype): ?array + { + $fileprefix = trim($fileprefix); + $filetype = trim($filetype); + if ($fileprefix === '' || $filetype === '') { + return null; + } + + $baseDir = Environment::getPublicPath() . '/fileadmin/downloads/Collateral'; + if (!is_dir($baseDir) || !is_readable($baseDir)) { + return null; + } + + $escapedPrefix = preg_quote($fileprefix, '/'); + $escapedType = preg_quote($filetype, '/'); + $pattern = '/^' . $escapedPrefix . '__' . $escapedType . '__(\\d+)-([A-Za-z]+)\\.([A-Za-z0-9]+)$/'; + + $bestFile = null; + $bestNumber = -1; + $bestLetterRank = -1; + + $entries = scandir($baseDir); + if ($entries === false) { + return null; + } + + foreach ($entries as $entry) { + if (!is_string($entry) || $entry === '.' || $entry === '..') { + continue; + } + + if (!preg_match($pattern, $entry, $matches)) { + continue; + } + + $number = (int)$matches[1]; + $letterRank = $this->letterSequenceToRank((string)$matches[2]); + + if ($number > $bestNumber || ($number === $bestNumber && $letterRank > $bestLetterRank)) { + $bestNumber = $number; + $bestLetterRank = $letterRank; + $bestFile = $entry; + } + } + + if ($bestFile === null) { + return null; + } + + $fullPath = $baseDir . '/' . $bestFile; + if (!is_file($fullPath) || !is_readable($fullPath)) { + return null; + } + + $extension = strtolower(pathinfo($bestFile, PATHINFO_EXTENSION)); + $mimeType = function_exists('mime_content_type') ? (string)(mime_content_type($fullPath) ?: '') : ''; + + return [ + 'uid' => 0, + 'name' => $bestFile, + 'url' => '/fileadmin/downloads/Collateral/' . rawurlencode($bestFile), + 'thumbnail' => null, + 'size' => (int)(filesize($fullPath) ?: 0), + 'extension' => $extension, + 'mimeType' => $mimeType, + 'title' => '', + 'description' => '', + ]; + } + + private function letterSequenceToRank(string $letters): int + { + $rank = 0; + $letters = strtoupper($letters); + $length = strlen($letters); + + for ($i = 0; $i < $length; $i++) { + $char = ord($letters[$i]); + if ($char < 65 || $char > 90) { + continue; + } + + $rank = ($rank * 26) + ($char - 64); + } + + return $rank; + } + + /** + * @param array> $downloads + * @return array> + */ + private function collectFallbackFilesFromDownloads(array $downloads): array + { + $fallbackFiles = []; + + foreach ($downloads as $download) { + $file = $download['file'] ?? null; + if (!is_array($file)) { + continue; + } + + if ((int)($file['uid'] ?? 1) !== 0) { + continue; + } + + $fallbackFiles[] = [ + 'downloadUid' => (int)($download['uid'] ?? 0), + 'name' => (string)($file['name'] ?? ''), + 'url' => (string)($file['url'] ?? ''), + 'source' => 'naming-convention-fallback', + ]; + } + + return $fallbackFiles; + } } diff --git a/packages/vitec/Classes/UserFunc/EventlistJsonRenderer.php b/packages/vitec/Classes/UserFunc/EventlistJsonRenderer.php new file mode 100644 index 0000000..7fbe5ab --- /dev/null +++ b/packages/vitec/Classes/UserFunc/EventlistJsonRenderer.php @@ -0,0 +1,314 @@ +data or page discovery). + * `renderForRecord()` = one specific tt_content row; reused by + * ContainerChildrenProcessor / ContentElementResolver. Exception-safe. + */ +class EventlistJsonRenderer +{ + #[AsAllowedCallable] + public function render(string $content, array $conf): string + { + // 1) cObj data path + $row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null; + if ($row && (string)($row['CType'] ?? '') === 'vitec_eventlist') { + return $this->renderForRecord($row); + } + + // 2) Page discovery via v14 request attribute + $pageId = 0; + $request = $GLOBALS['TYPO3_REQUEST'] ?? null; + if ($request !== null) { + $pageInfo = $request->getAttribute('frontend.page.information'); + if ($pageInfo !== null) { + $pageId = (int)$pageInfo->getId(); + } + } + if ($pageId <= 0) { + $pageId = (int)($GLOBALS['TSFE']->id ?? 0); + } + if ($pageId <= 0) { + return ''; + } + + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tt_content'); + + $contentElements = $qb + ->select('*') + ->from('tt_content') + ->where( + $qb->expr()->eq('pid', $qb->createNamedParameter($pageId, ParameterType::INTEGER)), + $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_eventlist', ParameterType::STRING)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) + ) + ->executeQuery() + ->fetchAllAssociative(); + + if (empty($contentElements)) { + return ''; + } + + return $this->renderForRecord($contentElements[0]); + } + + /** + * @param array $contentElement + */ + public function renderForRecord(array $contentElement): string + { + try { + $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); + $flexFormData = $flexFormService->convertFlexFormContentToArray($contentElement['pi_flexform'] ?? ''); + $settings = $flexFormData['settings'] ?? []; + + $showPast = (bool)($settings['showpast'] ?? false); + $daysInAdvance = (int)($settings['daysinadvance'] ?? 0); + $limit = (int)($settings['limit'] ?? 0); + $debugMode = (bool)($settings['debug'] ?? false); + + $upcoming = $this->fetchEvents(true, $limit, $daysInAdvance); + + $response = [ + 'events' => array_map(fn($e) => $this->serializeEvent($e), $upcoming), + 'settings' => [ + 'showpast' => $showPast, + 'daysinadvance' => $daysInAdvance, + 'limit' => $limit, + ], + ]; + + if ($showPast) { + $past = $this->fetchEvents(false, $limit); + $response['pastEvents'] = array_map(fn($e) => $this->serializeEvent($e), $past); + } + + if ($debugMode) { + $response['debug'] = [ + 'upcomingCount' => count($upcoming), + 'settings' => $settings, + ]; + } + + return json_encode($response); + } catch (\Throwable $e) { + return ''; + } + } + + /** + * @return array> + */ + private function fetchEvents(bool $upcoming, int $limit, int $daysInAdvance = 0): array + { + $todayMidnight = strtotime('today'); + + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_vitec_domain_model_event'); + $expr = $qb->expr(); + + $qb + ->select('*') + ->from('tx_vitec_domain_model_event') + ->where( + $expr->eq('deleted', 0), + $expr->eq('hidden', 0), + $expr->eq('hideonwebsite', 0) + ); + + if ($upcoming) { + // running or future: end >= today, or (no end and start >= today) + $qb->andWhere( + $expr->or( + $expr->gte('eventend', $qb->createNamedParameter($todayMidnight, ParameterType::INTEGER)), + $expr->and( + $expr->eq('eventend', 0), + $expr->gte('eventstart', $qb->createNamedParameter($todayMidnight, ParameterType::INTEGER)) + ) + ) + ); + $qb->orderBy('eventstart', 'ASC'); + if ($daysInAdvance > 0) { + $qb->andWhere( + $expr->lt('eventstart', $qb->createNamedParameter($todayMidnight + ($daysInAdvance * 86400), ParameterType::INTEGER)) + ); + } + } else { + // past: (end > 0 and end < today) or (no end and 0 < start < today) + $qb->andWhere( + $expr->or( + $expr->and( + $expr->gt('eventend', 0), + $expr->lt('eventend', $qb->createNamedParameter($todayMidnight, ParameterType::INTEGER)) + ), + $expr->and( + $expr->eq('eventend', 0), + $expr->gt('eventstart', 0), + $expr->lt('eventstart', $qb->createNamedParameter($todayMidnight, ParameterType::INTEGER)) + ) + ) + ); + $qb->orderBy('eventstart', 'DESC'); + } + + if ($limit > 0) { + $qb->setMaxResults($limit); + } + + return $qb->executeQuery()->fetchAllAssociative(); + } + + /** + * @param array $event + * @return array + */ + protected function serializeEvent(array $event): array + { + $uid = (int)$event['uid']; + $start = (int)($event['eventstart'] ?? 0); + $end = (int)($event['eventend'] ?? 0); + + return [ + 'uid' => $uid, + 'title' => (string)($event['title'] ?? ''), + 'slug' => (string)($event['slug'] ?? ''), + 'teaser' => (string)($event['teaser'] ?? ''), + 'description' => (string)($event['description'] ?? ''), + 'eventstart' => $start > 0 ? date('Y-m-d', $start) : null, + 'eventend' => $end > 0 ? date('Y-m-d', $end) : null, + 'venue' => (string)($event['venue'] ?? ''), + 'booth' => (string)($event['booth'] ?? ''), + 'city' => (string)($event['city'] ?? ''), + 'country' => (string)($event['country'] ?? ''), + 'attendancemode' => (string)($event['attendancemode'] ?? 'offline'), + 'eventstatus' => (string)($event['eventstatus'] ?? 'scheduled'), + 'eventurl' => (string)($event['eventurl'] ?? ''), + 'meetinglink' => (string)($event['meetinglink'] ?? ''), + 'image' => $this->getEventImage($uid), + 'categories' => $this->getEventCategories($uid), + ]; + } + + /** + * @return array|null + */ + protected function getEventImage(int $eventUid): ?array + { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_file_reference'); + + $fileRefData = $qb + ->select('sfr.uid', 'sfr.title', 'sfr.description', 'sfr.alternative', 'sfr.crop') + ->from('sys_file_reference', 'sfr') + ->where( + $qb->expr()->eq('sfr.tablenames', $qb->createNamedParameter('tx_vitec_domain_model_event', ParameterType::STRING)), + $qb->expr()->eq('sfr.fieldname', $qb->createNamedParameter('image', ParameterType::STRING)), + $qb->expr()->eq('sfr.uid_foreign', $qb->createNamedParameter($eventUid, ParameterType::INTEGER)), + $qb->expr()->eq('sfr.deleted', 0), + $qb->expr()->eq('sfr.hidden', 0) + ) + ->orderBy('sfr.sorting_foreign') + ->setMaxResults(1) + ->executeQuery() + ->fetchAssociative(); + + if (!$fileRefData) { + return null; + } + + try { + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); + $imageService = GeneralUtility::makeInstance(ImageService::class); + $fileReference = $resourceFactory->getFileReferenceObject((int)$fileRefData['uid']); + + $srcset = []; + foreach ([400, 800] as $width) { + $variant = $imageService->applyProcessingInstructions( + $fileReference, + ['width' => $width, 'crop' => $fileRefData['crop'] ?? null] + ); + $srcset[] = [ + 'url' => $imageService->getImageUri($variant), + 'width' => $width, + 'descriptor' => $width . 'w', + ]; + } + + $default = $imageService->applyProcessingInstructions( + $fileReference, + ['width' => 400, 'crop' => $fileRefData['crop'] ?? null] + ); + + return [ + 'uid' => (int)$fileRefData['uid'], + 'url' => $imageService->getImageUri($default), + 'title' => $fileRefData['title'] ?? '', + 'alternative' => $fileRefData['alternative'] ?? '', + 'description' => $fileRefData['description'] ?? '', + 'srcset' => $srcset, + 'properties' => [ + 'width' => $fileReference->getProperty('width'), + 'height' => $fileReference->getProperty('height'), + 'mimeType' => $fileReference->getProperty('mime_type'), + ], + ]; + } catch (\Exception $e) { + return null; + } + } + + protected function getEventCategories(int $eventUid): array + { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + $categories = $qb + ->select('c.uid', 'c.title', 'c.description') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid AND mm.tablenames = ' . + $qb->createNamedParameter('tx_vitec_domain_model_event', ParameterType::STRING) . + ' AND mm.fieldname = ' . + $qb->createNamedParameter('categories', ParameterType::STRING) + ) + ->where( + $qb->expr()->eq('mm.uid_foreign', $qb->createNamedParameter($eventUid, ParameterType::INTEGER)), + $qb->expr()->eq('c.deleted', 0), + $qb->expr()->eq('c.hidden', 0) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + return array_map(static function ($cat) { + return [ + 'uid' => (int)$cat['uid'], + 'title' => (string)($cat['title'] ?? ''), + 'description' => (string)($cat['description'] ?? ''), + ]; + }, $categories); + } +} diff --git a/packages/vitec/Classes/UserFunc/MarketShowJsonRenderer.php b/packages/vitec/Classes/UserFunc/MarketShowJsonRenderer.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/UserFunc/NewsJsonRenderer.php b/packages/vitec/Classes/UserFunc/NewsJsonRenderer.php new file mode 100644 index 0000000..8e09ee1 --- /dev/null +++ b/packages/vitec/Classes/UserFunc/NewsJsonRenderer.php @@ -0,0 +1,753 @@ + 'Compact List', + '2' => 'Featured Story', + '3' => 'Editorial Grid', + '4' => 'Detail Spotlight', + ]; + + private const TEMPLATE_LAYOUT_DEFAULTS = [ + 'news_pi1' => '1', + 'news_newsliststicky' => '1', + 'news_newsselectedlist' => '1', + 'news_newsdetail' => '2', + 'news_newsdatemenu' => '3', + 'news_categorylist' => '3', + 'news_newssearchform' => '4', + 'news_newssearchresult' => '4', + 'news_taglist' => '3', + ]; + + #[AsAllowedCallable] + public function render(string $content, array $conf): string + { + try { + $row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null; + if ($row !== null && in_array((string)($row['CType'] ?? ''), self::NEWS_CTYPES, true)) { + return $this->renderForRecord($row); + } + + $pageId = $this->resolveCurrentPageId(); + if ($pageId <= 0) { + return ''; + } + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tt_content'); + + $ctypeConstraints = []; + foreach (self::NEWS_CTYPES as $ctype) { + $ctypeConstraints[] = $queryBuilder->expr()->eq( + 'CType', + $queryBuilder->createNamedParameter($ctype, ParameterType::STRING) + ); + } + + $contentElements = $queryBuilder + ->select('*') + ->from('tt_content') + ->where( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pageId, ParameterType::INTEGER)), + $queryBuilder->expr()->or(...$ctypeConstraints), + $queryBuilder->expr()->eq('deleted', 0), + $queryBuilder->expr()->eq('hidden', 0) + ) + ->orderBy('sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + if ($contentElements === []) { + return ''; + } + + return $this->renderForRecord($contentElements[0]); + } catch (\Throwable $e) { + return ''; + } + } + + /** + * Render exactly the given news tt_content row. + * + * @param array $contentElement + */ + public function renderForRecord(array $contentElement): string + { + try { + $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); + $flexFormData = $flexFormService->convertFlexFormContentToArray($contentElement['pi_flexform'] ?? ''); + $settings = $flexFormData['settings'] ?? []; + + $type = (string)($contentElement['CType'] ?? ''); + $mode = $type === 'news_newsdetail' ? 'detail' : 'list'; + $debug = (bool)($settings['debug'] ?? false); + + if ($mode === 'detail') { + $news = $this->resolveDetailNews($contentElement, $settings); + $response = [ + 'mode' => 'detail', + 'news' => $news !== null ? $this->serializeNews($news, $settings) : null, + 'settings' => $this->buildSettingsPayload($contentElement, $settings), + ]; + + if ($debug) { + $response['debug'] = [ + 'contentElementUid' => (int)($contentElement['uid'] ?? 0), + 'settings' => $settings, + ]; + } + + return json_encode($response) ?: ''; + } + + $newsRows = $this->fetchNewsList($contentElement, $settings); + $items = array_map(fn (array $newsRow): array => $this->serializeNews($newsRow, $settings), $newsRows); + + $response = [ + 'mode' => 'list', + 'items' => $items, + 'settings' => $this->buildSettingsPayload($contentElement, $settings), + ]; + + if ($debug) { + $response['debug'] = [ + 'contentElementUid' => (int)($contentElement['uid'] ?? 0), + 'count' => count($items), + 'settings' => $settings, + ]; + } + + return json_encode($response) ?: ''; + } catch (\Throwable $e) { + return json_encode([ + 'mode' => 'error', + 'message' => $e->getMessage(), + ]) ?: ''; + } + } + + /** + * @param array $contentElement + * @param array $settings + * @return array|null + */ + private function resolveDetailNews(array $contentElement, array $settings): ?array + { + $newsUid = $this->resolveNewsUid((string)($settings['singleNews'] ?? '')); + if ($newsUid <= 0) { + $queryParams = $GLOBALS['TYPO3_REQUEST']?->getQueryParams() ?? []; + $newsParam = $queryParams['tx_news_pi1']['news'] ?? null; + $newsUid = $this->resolveNewsUid((string)($newsParam ?? '')); + } + + if ($newsUid > 0) { + $news = $this->fetchNewsByUid($newsUid, (int)($contentElement['sys_language_uid'] ?? 0)); + if ($news !== null) { + return $news; + } + } + + $list = $this->fetchNewsList($contentElement, $settings, 1); + return $list[0] ?? null; + } + + /** + * @param array $contentElement + * @param array $settings + * @param int|null $limitOverride + * @return array> + */ + private function fetchNewsList(array $contentElement, array $settings, ?int $limitOverride = null): array + { + $selectedNews = $this->parseUidList((string)($settings['selectedList'] ?? '')); + $storagePids = $this->parseUidList((string)($settings['startingpoint'] ?? '')); + if ($storagePids === []) { + $storagePids = [(int)($contentElement['pid'] ?? 0)]; + } + + $categoryUids = $this->parseUidList((string)($settings['categories'] ?? '')); + $includeSubCategories = (bool)($settings['includeSubCategories'] ?? false); + $tagUids = $this->parseUidList((string)($settings['tags'] ?? '')); + $limit = $limitOverride ?? (int)($settings['limit'] ?? 0); + $orderDirection = strtoupper((string)($settings['orderDirection'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC'; + $topNewsFirst = (bool)($settings['topNewsFirst'] ?? false); + $searchTerm = $this->resolveSearchTerm((string)($contentElement['CType'] ?? '')); + $languageUid = (int)($contentElement['sys_language_uid'] ?? 0); + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_news_domain_model_news'); + + $rows = $queryBuilder + ->select('n.*') + ->from('tx_news_domain_model_news', 'n') + ->where( + $queryBuilder->expr()->eq('n.deleted', 0), + $queryBuilder->expr()->eq('n.hidden', 0), + $queryBuilder->expr()->in('n.pid', $queryBuilder->createNamedParameter($storagePids, ArrayParameterType::INTEGER)) + ) + ->orderBy('n.istopnews', $topNewsFirst ? 'DESC' : 'ASC') + ->addOrderBy('n.datetime', 'DESC') + ->executeQuery() + ->fetchAllAssociative(); + + if ($languageUid > 0) { + $rows = array_values(array_filter($rows, static fn (array $row): bool => (int)($row['sys_language_uid'] ?? 0) === $languageUid)); + } else { + $rows = array_values(array_filter($rows, static fn (array $row): bool => in_array((int)($row['sys_language_uid'] ?? 0), [0, -1], true))); + } + + if ($selectedNews !== []) { + $selectedLookup = array_fill_keys($selectedNews, true); + $rows = array_values(array_filter($rows, static fn (array $row): bool => isset($selectedLookup[(int)($row['uid'] ?? 0)]))); + } + + if ($categoryUids !== []) { + $categoryLookup = $this->newsUidsForCategories($categoryUids, $includeSubCategories); + if ($categoryLookup === [] && !$includeSubCategories) { + $categoryLookup = $this->newsUidsForCategories($this->expandCategoryUids($categoryUids), true); + } + + if ($categoryLookup !== []) { + $rows = array_values(array_filter($rows, static fn (array $row): bool => isset($categoryLookup[(int)($row['uid'] ?? 0)]))); + } + } + + if ($tagUids !== []) { + $tagLookup = $this->newsUidsForTags($tagUids); + if ($tagLookup !== []) { + $rows = array_values(array_filter($rows, static fn (array $row): bool => isset($tagLookup[(int)($row['uid'] ?? 0)]))); + } + } + + if ($searchTerm !== '') { + $needle = mb_strtolower($searchTerm); + $rows = array_values(array_filter($rows, static function (array $row) use ($needle): bool { + $haystack = mb_strtolower((string)($row['title'] ?? '') . ' ' . (string)($row['teaser'] ?? '') . ' ' . (string)($row['path_segment'] ?? '')); + return str_contains($haystack, $needle); + })); + } + + if ($limit > 0) { + $rows = array_slice($rows, 0, $limit); + } + + return $rows; + } + + /** + * @param int $newsUid + * @param int $languageUid + * @return array|null + */ + private function fetchNewsByUid(int $newsUid, int $languageUid): ?array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_news_domain_model_news'); + + $query = $queryBuilder + ->select('n.*') + ->from('tx_news_domain_model_news', 'n') + ->where( + $queryBuilder->expr()->eq('n.uid', $queryBuilder->createNamedParameter($newsUid, ParameterType::INTEGER)), + $queryBuilder->expr()->eq('n.deleted', 0), + $queryBuilder->expr()->eq('n.hidden', 0) + ); + + if ($languageUid > 0) { + $query->andWhere( + $queryBuilder->expr()->eq('n.sys_language_uid', $queryBuilder->createNamedParameter($languageUid, ParameterType::INTEGER)) + ); + } + + $news = $query->executeQuery()->fetchAssociative(); + return is_array($news) ? $news : null; + } + + /** + * @param array $news + * @param array $settings + * @return array + */ + private function serializeNews(array $news, array $settings = []): array + { + $uid = (int)($news['uid'] ?? 0); + $pathSegment = (string)($news['path_segment'] ?? ''); + $urls = $this->buildNewsUrls($pathSegment, $settings); + + return [ + 'uid' => $uid, + 'title' => (string)($news['title'] ?? ''), + 'alternativeTitle' => (string)($news['alternative_title'] ?? ''), + 'pathSegment' => $pathSegment, + 'detailUrl' => $urls['detailUrl'], + 'canonicalUrl' => $urls['canonicalUrl'], + 'teaser' => (string)($news['teaser'] ?? ''), + 'bodytext' => (string)($news['bodytext'] ?? ''), + 'datetime' => (int)($news['datetime'] ?? 0), + 'archive' => (int)($news['archive'] ?? 0), + 'istopnews' => (bool)($news['istopnews'] ?? false), + 'author' => (string)($news['author'] ?? ''), + 'authorEmail' => (string)($news['author_email'] ?? ''), + 'categories' => $this->resolveCategories($uid), + 'tags' => $this->resolveTags($uid), + 'media' => $this->resolveFiles('tx_news_domain_model_news', 'fal_media', $uid), + 'relatedFiles' => $this->resolveFiles('tx_news_domain_model_news', 'fal_related_files', $uid), + 'related' => $this->resolveRelatedNews($uid), + 'relatedLinks' => $this->resolveRelatedLinks($uid), + ]; + } + + /** + * @param array $settings + * @return array{detailUrl:string, canonicalUrl:string} + */ + private function buildNewsUrls(string $pathSegment, array $settings): array + { + $pathSegment = trim($pathSegment, '/'); + if ($pathSegment === '') { + return ['detailUrl' => '', 'canonicalUrl' => '']; + } + + $detailPid = (int)($settings['detailPid'] ?? 0); + if ($detailPid <= 0) { + $detailPid = $this->resolveCurrentPageId(); + } + $detailPageSlug = $detailPid > 0 ? $this->resolvePageSlug($detailPid) : ''; + if ($detailPageSlug === '') { + return ['detailUrl' => '', 'canonicalUrl' => '']; + } + + $detailUrl = rtrim($detailPageSlug, '/') . '/' . $pathSegment; + $canonicalUrl = $this->absoluteUrl($detailUrl); + + return [ + 'detailUrl' => $detailUrl, + 'canonicalUrl' => $canonicalUrl, + ]; + } + + private function resolvePageSlug(int $pageId): string + { + if ($pageId <= 0) { + return ''; + } + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('pages'); + + $row = $queryBuilder + ->select('slug') + ->from('pages') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($pageId, ParameterType::INTEGER)), + $queryBuilder->expr()->eq('deleted', 0), + $queryBuilder->expr()->eq('hidden', 0) + ) + ->executeQuery() + ->fetchAssociative(); + + return (string)($row['slug'] ?? ''); + } + + private function absoluteUrl(string $path): string + { + $path = '/' . ltrim($path, '/'); + + $request = $GLOBALS['TYPO3_REQUEST'] ?? null; + if ($request !== null) { + $normalizedParams = $request->getAttribute('normalizedParams'); + if ($normalizedParams !== null) { + return rtrim($normalizedParams->getSiteUrl(), '/') . $path; + } + } + + $site = $request?->getAttribute('site'); + if ($site !== null) { + return rtrim((string)$site->getBase(), '/') . $path; + } + + return $path; + } + + /** + * @return array> + */ + private function resolveCategories(int $newsUid): array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + return $queryBuilder + ->select('c.uid', 'c.title') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid' + ) + ->where( + $queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->createNamedParameter($newsUid, ParameterType::INTEGER)), + $queryBuilder->expr()->eq('mm.tablenames', $queryBuilder->createNamedParameter('tx_news_domain_model_news', ParameterType::STRING)), + $queryBuilder->expr()->eq('mm.fieldname', $queryBuilder->createNamedParameter('categories', ParameterType::STRING)) + ) + ->orderBy('c.title', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + } + + /** + * @return array> + */ + private function resolveTags(int $newsUid): array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_news_domain_model_tag'); + + return $queryBuilder + ->select('t.uid', 't.title') + ->from('tx_news_domain_model_tag', 't') + ->join( + 't', + 'tx_news_domain_model_news_tag_mm', + 'mm', + 'mm.uid_foreign = t.uid' + ) + ->where( + $queryBuilder->expr()->eq('mm.uid_local', $queryBuilder->createNamedParameter($newsUid, ParameterType::INTEGER)) + ) + ->orderBy('t.title', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + } + + /** + * @param list $categoryUids + * @return array + */ + private function newsUidsForCategories(array $categoryUids, bool $includeSubCategories): array + { + if ($categoryUids === []) { + return []; + } + + $categories = $includeSubCategories ? $this->expandCategoryUids($categoryUids) : $categoryUids; + if ($categories === []) { + return []; + } + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category_record_mm'); + + $uids = $queryBuilder + ->select('uid_foreign') + ->from('sys_category_record_mm') + ->where( + $queryBuilder->expr()->eq('tablenames', $queryBuilder->createNamedParameter('tx_news_domain_model_news', ParameterType::STRING)), + $queryBuilder->expr()->eq('fieldname', $queryBuilder->createNamedParameter('categories', ParameterType::STRING)), + $queryBuilder->expr()->in('uid_local', $queryBuilder->createNamedParameter($categories, ArrayParameterType::INTEGER)) + ) + ->executeQuery() + ->fetchFirstColumn(); + + return array_fill_keys(array_map('intval', $uids), true); + } + + /** + * @param list $tagUids + * @return array + */ + private function newsUidsForTags(array $tagUids): array + { + if ($tagUids === []) { + return []; + } + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_news_domain_model_news_tag_mm'); + + $uids = $queryBuilder + ->select('uid_local') + ->from('tx_news_domain_model_news_tag_mm') + ->where( + $queryBuilder->expr()->in('uid_foreign', $queryBuilder->createNamedParameter($tagUids, ArrayParameterType::INTEGER)) + ) + ->executeQuery() + ->fetchFirstColumn(); + + return array_fill_keys(array_map('intval', $uids), true); + } + + /** + * @return array> + */ + private function resolveRelatedNews(int $newsUid): array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_news_domain_model_news'); + + return $queryBuilder + ->select('n.uid', 'n.title', 'n.path_segment') + ->from('tx_news_domain_model_news', 'n') + ->join( + 'n', + 'tx_news_domain_model_news_related_mm', + 'mm', + 'mm.uid_foreign = n.uid' + ) + ->where( + $queryBuilder->expr()->eq('mm.uid_local', $queryBuilder->createNamedParameter($newsUid, ParameterType::INTEGER)), + $queryBuilder->expr()->eq('n.deleted', 0), + $queryBuilder->expr()->eq('n.hidden', 0) + ) + ->orderBy('n.datetime', 'DESC') + ->executeQuery() + ->fetchAllAssociative(); + } + + /** + * @return array> + */ + private function resolveRelatedLinks(int $newsUid): array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_news_domain_model_link'); + + return $queryBuilder + ->select('l.uid', 'l.title', 'l.description', 'l.uri') + ->from('tx_news_domain_model_link', 'l') + ->where( + $queryBuilder->expr()->eq('l.parent', $queryBuilder->createNamedParameter($newsUid, ParameterType::INTEGER)), + $queryBuilder->expr()->eq('l.deleted', 0), + $queryBuilder->expr()->eq('l.hidden', 0) + ) + ->orderBy('l.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + } + + /** + * @return array> + */ + private function resolveFiles(string $tableName, string $fieldName, int $uid): array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_file_reference'); + + $rows = $queryBuilder + ->select('uid') + ->from('sys_file_reference') + ->where( + $queryBuilder->expr()->eq('uid_foreign', $queryBuilder->createNamedParameter($uid, ParameterType::INTEGER)), + $queryBuilder->expr()->eq('tablenames', $queryBuilder->createNamedParameter($tableName, ParameterType::STRING)), + $queryBuilder->expr()->eq('fieldname', $queryBuilder->createNamedParameter($fieldName, ParameterType::STRING)), + $queryBuilder->expr()->eq('deleted', 0), + $queryBuilder->expr()->eq('hidden', 0) + ) + ->orderBy('sorting_foreign', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + if ($rows === []) { + return []; + } + + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); + $imageService = GeneralUtility::makeInstance(ImageService::class); + $files = []; + + foreach ($rows as $row) { + try { + $fileReference = $resourceFactory->getFileReferenceObject((int)$row['uid']); + $processed = $imageService->applyProcessingInstructions($fileReference, ['width' => 1400]); + + $files[] = [ + 'uid' => (int)$row['uid'], + 'url' => $imageService->getImageUri($processed), + ]; + } catch (\Throwable $e) { + continue; + } + } + + return $files; + } + + private function resolveNewsUid(string $rawValue): int + { + $rawValue = trim($rawValue); + if ($rawValue === '') { + return 0; + } + + if (ctype_digit($rawValue)) { + return (int)$rawValue; + } + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_news_domain_model_news'); + + $row = $queryBuilder + ->select('uid') + ->from('tx_news_domain_model_news') + ->where( + $queryBuilder->expr()->eq('path_segment', $queryBuilder->createNamedParameter($rawValue, ParameterType::STRING)), + $queryBuilder->expr()->eq('deleted', 0), + $queryBuilder->expr()->eq('hidden', 0) + ) + ->executeQuery() + ->fetchAssociative(); + + return (int)($row['uid'] ?? 0); + } + + /** + * @return list + */ + private function parseUidList(string $rawValue): array + { + $values = array_filter(array_map('trim', explode(',', $rawValue))); + + return array_values(array_filter(array_map(static fn (string $value): int => (int)$value, $values))); + } + + /** + * @param list $categoryUids + * @return list + */ + private function expandCategoryUids(array $categoryUids): array + { + if ($categoryUids === []) { + return []; + } + + $allUids = array_fill_keys($categoryUids, true); + $queue = $categoryUids; + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + while ($queue !== []) { + $currentUid = array_shift($queue); + if ($currentUid === null) { + continue; + } + + $children = $queryBuilder + ->select('uid') + ->from('sys_category') + ->where( + $queryBuilder->expr()->eq('parent', $queryBuilder->createNamedParameter($currentUid, ParameterType::INTEGER)), + $queryBuilder->expr()->eq('deleted', 0) + ) + ->executeQuery() + ->fetchFirstColumn(); + + foreach ($children as $childUid) { + $childUid = (int)$childUid; + if ($childUid <= 0 || isset($allUids[$childUid])) { + continue; + } + + $allUids[$childUid] = true; + $queue[] = $childUid; + } + } + + return array_values(array_map('intval', array_keys($allUids))); + } + + private function resolveCurrentPageId(): int + { + $request = $GLOBALS['TYPO3_REQUEST'] ?? null; + if ($request !== null) { + $pageInfo = $request->getAttribute('frontend.page.information'); + if ($pageInfo !== null) { + return (int)$pageInfo->getId(); + } + } + + return (int)($GLOBALS['TSFE']->id ?? 0); + } + + /** + * @param array $contentElement + * @param array $settings + * @return array + */ + private function buildSettingsPayload(array $contentElement, array $settings): array + { + $payload = $settings; + $payload['type'] = (string)($contentElement['CType'] ?? ''); + $payload['detailPid'] = (int)($settings['detailPid'] ?? 0); + $payload['listPid'] = (int)($settings['listPid'] ?? 0); + $payload['templateLayout'] = $this->resolveTemplateLayoutValue((string)($contentElement['CType'] ?? ''), (string)($settings['templateLayout'] ?? '')); + $payload['templateLayoutLabel'] = self::TEMPLATE_LAYOUTS[$payload['templateLayout']] ?? ''; + $payload['templateLayouts'] = array_map( + static fn (string $label, string $key): array => ['key' => $key, 'label' => $label], + self::TEMPLATE_LAYOUTS, + array_keys(self::TEMPLATE_LAYOUTS) + ); + + return $payload; + } + + private function resolveTemplateLayoutValue(string $type, string $value): string + { + $value = trim($value); + if ($value !== '' && isset(self::TEMPLATE_LAYOUTS[$value])) { + return $value; + } + + return self::TEMPLATE_LAYOUT_DEFAULTS[$type] ?? ''; + } + + private function resolveSearchTerm(string $type): string + { + if ($type !== 'news_newssearchresult') { + return ''; + } + + $queryParams = $GLOBALS['TYPO3_REQUEST']?->getQueryParams() ?? []; + $search = $queryParams['tx_news_pi1']['search']['sword'] ?? ''; + + return trim((string)$search); + } +} \ No newline at end of file diff --git a/packages/vitec/Classes/UserFunc/PageJsonLdRenderer.php b/packages/vitec/Classes/UserFunc/PageJsonLdRenderer.php old mode 100755 new mode 100644 index 05482c9..80fc10e --- a/packages/vitec/Classes/UserFunc/PageJsonLdRenderer.php +++ b/packages/vitec/Classes/UserFunc/PageJsonLdRenderer.php @@ -93,6 +93,24 @@ final class PageJsonLdRenderer $hasOrganization ); } + // FAQPage when the page contains at least one vitec_faq element. + $faqItems = $this->collectFaqItems($pageId); + if ($faqItems !== []) { + $nodes[] = $service->buildFaqPage($faqItems, $base); + } + // Event nodes when the page contains a vitec_eventlist element. + foreach ($this->collectUpcomingEvents($pageId) as $eventRow) { + $nodes[] = $service->buildEvent( + $eventRow, + $base, + $this->eventImageUrls((int)$eventRow['uid'], $base, $service), + $hasOrganization + ); + } + + + + return $service->encodeGraph($nodes); } catch (\Throwable $e) { @@ -225,4 +243,171 @@ final class PageJsonLdRenderer return $urls; } + + /** + * Collect question/answer pairs from all visible vitec_faq elements on + * this page (Content Blocks collection child table). + * + * @return list + */ + private function collectFaqItems(int $pageId): array + { + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tt_content'); + $elements = $qb + ->select('uid') + ->from('tt_content') + ->where( + $qb->expr()->eq('pid', $qb->createNamedParameter($pageId, ParameterType::INTEGER)), + $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_faq', ParameterType::STRING)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) + ) + ->executeQuery() + ->fetchAllAssociative(); + + if ($elements === []) { + return []; + } + + $items = []; + foreach ($elements as $element) { + $childQb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('vitec_faq_items'); + $rows = $childQb + ->select('*') + ->from('vitec_faq_items') + ->where( + $childQb->expr()->eq('foreign_table_parent_uid', $childQb->createNamedParameter((int)$element['uid'], ParameterType::INTEGER)), + $childQb->expr()->eq('deleted', 0), + $childQb->expr()->eq('hidden', 0) + ) + ->orderBy('sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($rows as $row) { + $items[] = [ + 'question' => (string)($row['question'] ?? $row['vitec_question'] ?? ''), + 'answer' => (string)($row['answer'] ?? $row['vitec_answer'] ?? ''), + ]; + } + } + + return $items; + } catch (\Throwable $e) { + // Table may not exist yet (schema not updated) — skip silently. + return []; + } + } + + + /** + * Upcoming event rows when this page contains at least one visible + * vitec_eventlist element. Empty array otherwise. + * + * @return list> + */ + private function collectUpcomingEvents(int $pageId): array + { + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tt_content'); + $eventlistElement = $qb + ->select('uid', 'pi_flexform') + ->from('tt_content') + ->where( + $qb->expr()->eq('pid', $qb->createNamedParameter($pageId, ParameterType::INTEGER)), + $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_eventlist', ParameterType::STRING)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) + ) + ->setMaxResults(1) + ->executeQuery() + ->fetchAssociative(); + + if (!$eventlistElement) { + return []; + } + + // Mirror the plugin's "days in advance" window so structured data + // matches what the page actually shows. + $daysInAdvance = 0; + $flexFormService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Service\FlexFormService::class); + $flexSettings = $flexFormService->convertFlexFormContentToArray((string)($eventlistElement['pi_flexform'] ?? ''))['settings'] ?? []; + $daysInAdvance = (int)($flexSettings['daysinadvance'] ?? 0); + + $todayMidnight = strtotime('today'); + $eventQb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_vitec_domain_model_event'); + $expr = $eventQb->expr(); + + $eventQb + ->select('*') + ->from('tx_vitec_domain_model_event') + ->where( + $expr->eq('deleted', 0), + $expr->eq('hidden', 0), + $expr->eq('hideonwebsite', 0), + $expr->or( + $expr->gte('eventend', $eventQb->createNamedParameter($todayMidnight, ParameterType::INTEGER)), + $expr->and( + $expr->eq('eventend', 0), + $expr->gte('eventstart', $eventQb->createNamedParameter($todayMidnight, ParameterType::INTEGER)) + ) + ) + ) + ->orderBy('eventstart', 'ASC'); + + if ($daysInAdvance > 0) { + $eventQb->andWhere( + $expr->lt('eventstart', $eventQb->createNamedParameter($todayMidnight + ($daysInAdvance * 86400), ParameterType::INTEGER)) + ); + } + + return $eventQb->executeQuery()->fetchAllAssociative(); + } catch (\Throwable $e) { + // Table may not exist yet — skip silently. + return []; + } + } + + /** + * Root-relative logo URLs for an event (fieldname=image). + * + * @return list + */ + private function eventImageUrls(int $eventUid, string $base, $service): array + { + try { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_file_reference'); + $rows = $qb + ->select('f.identifier') + ->from('sys_file_reference', 'fr') + ->join('fr', 'sys_file', 'f', 'fr.uid_local = f.uid') + ->where( + $qb->expr()->eq('fr.tablenames', $qb->createNamedParameter('tx_vitec_domain_model_event', ParameterType::STRING)), + $qb->expr()->eq('fr.fieldname', $qb->createNamedParameter('image', ParameterType::STRING)), + $qb->expr()->eq('fr.uid_foreign', $qb->createNamedParameter($eventUid, ParameterType::INTEGER)), + $qb->expr()->eq('fr.deleted', 0), + $qb->expr()->eq('f.missing', 0) + ) + ->executeQuery() + ->fetchAllAssociative(); + + $urls = []; + foreach ($rows as $row) { + $identifier = (string)($row['identifier'] ?? ''); + if ($identifier !== '') { + $urls[] = '/fileadmin' . $identifier; + } + } + return $urls; + } catch (\Throwable $e) { + return []; + } + } + } diff --git a/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php b/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php old mode 100755 new mode 100644 index 0221e00..a413495 --- a/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php @@ -9,6 +9,7 @@ use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use Doctrine\DBAL\ParameterType; use Evomedien\Vitec\Domain\Repository\ProductRepository; use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection; use TYPO3\CMS\Core\Resource\FileReference; @@ -141,6 +142,7 @@ class ProductListJsonRenderer 'categoryUids' => $categoryUids, 'productCount' => count($productsData), 'settings' => $settings, + 'fallbackFiles' => $this->collectFallbackFilesFromProducts($productsData), ], ]); } @@ -413,6 +415,168 @@ class ProductListJsonRenderer }, $categories); } + private function getDownloadFileType(int $downloadUid): string + { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + $categories = $qb + ->select('c.filetype') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid AND mm.tablenames = ' . + $qb->createNamedParameter('tx_vitec_domain_model_download', ParameterType::STRING) . + ' AND mm.fieldname = ' . + $qb->createNamedParameter('categories', ParameterType::STRING) + ) + ->where( + $qb->expr()->eq('mm.uid_foreign', $qb->createNamedParameter($downloadUid, ParameterType::INTEGER)), + $qb->expr()->eq('c.deleted', 0), + $qb->expr()->eq('c.hidden', 0), + $qb->expr()->eq('c.parent', $qb->createNamedParameter(4, ParameterType::INTEGER)) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($categories as $category) { + $filetype = trim((string)($category['filetype'] ?? '')); + if ($filetype !== '') { + return $filetype; + } + } + + return ''; + } + + /** + * @return array|null + */ + private function resolveFileByConvention(string $fileprefix, string $filetype): ?array + { + $fileprefix = trim($fileprefix); + $filetype = trim($filetype); + if ($fileprefix === '' || $filetype === '') { + return null; + } + + $baseDir = Environment::getPublicPath() . '/fileadmin/downloads/Collateral'; + if (!is_dir($baseDir) || !is_readable($baseDir)) { + return null; + } + + $escapedPrefix = preg_quote($fileprefix, '/'); + $escapedType = preg_quote($filetype, '/'); + $pattern = '/^' . $escapedPrefix . '__' . $escapedType . '__(\\d+)-([A-Za-z]+)\\.([A-Za-z0-9]+)$/'; + + $bestFile = null; + $bestNumber = -1; + $bestLetterRank = -1; + + $entries = scandir($baseDir); + if ($entries === false) { + return null; + } + + foreach ($entries as $entry) { + if (!is_string($entry) || $entry === '.' || $entry === '..') { + continue; + } + + if (!preg_match($pattern, $entry, $matches)) { + continue; + } + + $number = (int)$matches[1]; + $letterRank = $this->letterSequenceToRank((string)$matches[2]); + + if ($number > $bestNumber || ($number === $bestNumber && $letterRank > $bestLetterRank)) { + $bestNumber = $number; + $bestLetterRank = $letterRank; + $bestFile = $entry; + } + } + + if ($bestFile === null) { + return null; + } + + $fullPath = $baseDir . '/' . $bestFile; + if (!is_file($fullPath) || !is_readable($fullPath)) { + return null; + } + + $extension = strtolower(pathinfo($bestFile, PATHINFO_EXTENSION)); + $mimeType = function_exists('mime_content_type') ? (string)(mime_content_type($fullPath) ?: '') : ''; + + return [ + 'uid' => 0, + 'name' => $bestFile, + 'url' => '/fileadmin/downloads/Collateral/' . rawurlencode($bestFile), + 'size' => (int)(filesize($fullPath) ?: 0), + 'extension' => $extension, + 'mimeType' => $mimeType, + ]; + } + + private function letterSequenceToRank(string $letters): int + { + $rank = 0; + $letters = strtoupper($letters); + $length = strlen($letters); + + for ($i = 0; $i < $length; $i++) { + $char = ord($letters[$i]); + if ($char < 65 || $char > 90) { + continue; + } + + $rank = ($rank * 26) + ($char - 64); + } + + return $rank; + } + + /** + * @param array> $products + * @return array> + */ + private function collectFallbackFilesFromProducts(array $products): array + { + $fallbackFiles = []; + + foreach ($products as $product) { + $downloads = $product['downloads'] ?? null; + if (!is_array($downloads)) { + continue; + } + + foreach ($downloads as $download) { + if (!is_array($download)) { + continue; + } + + $file = $download['file'] ?? null; + if (!is_array($file) || (int)($file['uid'] ?? 1) !== 0) { + continue; + } + + $fallbackFiles[] = [ + 'productUid' => (int)($product['uid'] ?? 0), + 'downloadUid' => (int)($download['uid'] ?? 0), + 'name' => (string)($file['name'] ?? ''), + 'url' => (string)($file['url'] ?? ''), + 'source' => 'naming-convention-fallback', + ]; + } + } + + return $fallbackFiles; + } + protected function getProductDownloads(int $productUid): array { $queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class) @@ -440,6 +604,9 @@ class ProductListJsonRenderer $result = []; foreach ($downloads as $download) { $fileInfo = null; + $downloadUid = (int)$download['uid']; + $fileprefix = (string)($download['fileprefix'] ?? ''); + $filetype = $this->getDownloadFileType($downloadUid); if (!empty($download['file'])) { $fileQueryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class) @@ -450,7 +617,7 @@ class ProductListJsonRenderer ->from('sys_file_reference', 'fr') ->join('fr', 'sys_file', 'f', 'fr.uid_local = f.uid') ->where( - $fileQueryBuilder->expr()->eq('fr.uid_foreign', $fileQueryBuilder->createNamedParameter((int)$download['uid'], ParameterType::INTEGER)), + $fileQueryBuilder->expr()->eq('fr.uid_foreign', $fileQueryBuilder->createNamedParameter($downloadUid, ParameterType::INTEGER)), $fileQueryBuilder->expr()->eq('fr.tablenames', $fileQueryBuilder->createNamedParameter('tx_vitec_domain_model_download', ParameterType::STRING)), $fileQueryBuilder->expr()->eq('fr.fieldname', $fileQueryBuilder->createNamedParameter('file', ParameterType::STRING)), $fileQueryBuilder->expr()->eq('fr.deleted', 0), @@ -473,14 +640,20 @@ class ProductListJsonRenderer } } + if ($fileInfo === null) { + $fileInfo = $this->resolveFileByConvention($fileprefix, $filetype); + } + $result[] = [ - 'uid' => (int)$download['uid'], + 'uid' => $downloadUid, 'title' => $download['title'] ?? '', 'slug' => $download['slug'] ?? '', 'teaser' => $download['teaser'] ?? '', 'description' => $download['description'] ?? '', 'keywords' => $download['keywords'] ?? '', 'icon' => $download['icon'] ?? '', + 'fileprefix' => $fileprefix, + 'filetype' => $filetype, 'file' => $fileInfo, ]; } diff --git a/packages/vitec/Classes/UserFunc/ProductShowJsonRenderer.php b/packages/vitec/Classes/UserFunc/ProductShowJsonRenderer.php old mode 100755 new mode 100644 index 4ba8f80..2414b82 --- a/packages/vitec/Classes/UserFunc/ProductShowJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/ProductShowJsonRenderer.php @@ -7,6 +7,7 @@ namespace Evomedien\Vitec\UserFunc; use Evomedien\Vitec\Service\StructuredDataService; use TYPO3\CMS\Core\Attribute\AsAllowedCallable; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -160,6 +161,7 @@ class ProductShowJsonRenderer 'productUid' => $productUid, 'layout' => $layout, 'settings' => $settings, + 'fallbackFiles' => $this->collectFallbackFilesFromDownloads((array)($response['product']['downloads'] ?? [])), ]; } @@ -495,6 +497,160 @@ class ProductShowJsonRenderer }, $categories); } + private function getDownloadFileType(int $downloadUid): string + { + $qb = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + + $categories = $qb + ->select('c.filetype') + ->from('sys_category', 'c') + ->join( + 'c', + 'sys_category_record_mm', + 'mm', + 'mm.uid_local = c.uid AND mm.tablenames = ' . + $qb->createNamedParameter('tx_vitec_domain_model_download', ParameterType::STRING) . + ' AND mm.fieldname = ' . + $qb->createNamedParameter('categories', ParameterType::STRING) + ) + ->where( + $qb->expr()->eq('mm.uid_foreign', $qb->createNamedParameter($downloadUid, ParameterType::INTEGER)), + $qb->expr()->eq('c.deleted', 0), + $qb->expr()->eq('c.hidden', 0), + $qb->expr()->eq('c.parent', $qb->createNamedParameter(4, ParameterType::INTEGER)) + ) + ->orderBy('mm.sorting', 'ASC') + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($categories as $category) { + $filetype = trim((string)($category['filetype'] ?? '')); + if ($filetype !== '') { + return $filetype; + } + } + + return ''; + } + + /** + * @return array|null + */ + private function resolveFileByConvention(string $fileprefix, string $filetype): ?array + { + $fileprefix = trim($fileprefix); + $filetype = trim($filetype); + if ($fileprefix === '' || $filetype === '') { + return null; + } + + $baseDir = Environment::getPublicPath() . '/fileadmin/downloads/Collateral'; + if (!is_dir($baseDir) || !is_readable($baseDir)) { + return null; + } + + $escapedPrefix = preg_quote($fileprefix, '/'); + $escapedType = preg_quote($filetype, '/'); + $pattern = '/^' . $escapedPrefix . '__' . $escapedType . '__(\\d+)-([A-Za-z]+)\\.([A-Za-z0-9]+)$/'; + + $bestFile = null; + $bestNumber = -1; + $bestLetterRank = -1; + + $entries = scandir($baseDir); + if ($entries === false) { + return null; + } + + foreach ($entries as $entry) { + if (!is_string($entry) || $entry === '.' || $entry === '..') { + continue; + } + + if (!preg_match($pattern, $entry, $matches)) { + continue; + } + + $number = (int)$matches[1]; + $letterRank = $this->letterSequenceToRank((string)$matches[2]); + + if ($number > $bestNumber || ($number === $bestNumber && $letterRank > $bestLetterRank)) { + $bestNumber = $number; + $bestLetterRank = $letterRank; + $bestFile = $entry; + } + } + + if ($bestFile === null) { + return null; + } + + $fullPath = $baseDir . '/' . $bestFile; + if (!is_file($fullPath) || !is_readable($fullPath)) { + return null; + } + + $extension = strtolower(pathinfo($bestFile, PATHINFO_EXTENSION)); + $mimeType = function_exists('mime_content_type') ? (string)(mime_content_type($fullPath) ?: '') : ''; + + return [ + 'uid' => 0, + 'name' => $bestFile, + 'url' => '/fileadmin/downloads/Collateral/' . rawurlencode($bestFile), + 'size' => (int)(filesize($fullPath) ?: 0), + 'extension' => $extension, + 'mimeType' => $mimeType, + ]; + } + + private function letterSequenceToRank(string $letters): int + { + $rank = 0; + $letters = strtoupper($letters); + $length = strlen($letters); + + for ($i = 0; $i < $length; $i++) { + $char = ord($letters[$i]); + if ($char < 65 || $char > 90) { + continue; + } + + $rank = ($rank * 26) + ($char - 64); + } + + return $rank; + } + + /** + * @param array> $downloads + * @return array> + */ + private function collectFallbackFilesFromDownloads(array $downloads): array + { + $fallbackFiles = []; + + foreach ($downloads as $download) { + if (!is_array($download)) { + continue; + } + + $file = $download['file'] ?? null; + if (!is_array($file) || (int)($file['uid'] ?? 1) !== 0) { + continue; + } + + $fallbackFiles[] = [ + 'downloadUid' => (int)($download['uid'] ?? 0), + 'name' => (string)($file['name'] ?? ''), + 'url' => (string)($file['url'] ?? ''), + 'source' => 'naming-convention-fallback', + ]; + } + + return $fallbackFiles; + } + protected function getProductDownloads(int $productUid): array { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) @@ -522,6 +678,9 @@ class ProductShowJsonRenderer $result = []; foreach ($downloads as $download) { $fileInfo = null; + $downloadUid = (int)$download['uid']; + $fileprefix = (string)($download['fileprefix'] ?? ''); + $filetype = $this->getDownloadFileType($downloadUid); if (!empty($download['file'])) { $fileQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) @@ -532,7 +691,7 @@ class ProductShowJsonRenderer ->from('sys_file_reference', 'fr') ->join('fr', 'sys_file', 'f', 'fr.uid_local = f.uid') ->where( - $fileQueryBuilder->expr()->eq('fr.uid_foreign', $fileQueryBuilder->createNamedParameter((int)$download['uid'], ParameterType::INTEGER)), + $fileQueryBuilder->expr()->eq('fr.uid_foreign', $fileQueryBuilder->createNamedParameter($downloadUid, ParameterType::INTEGER)), $fileQueryBuilder->expr()->eq('fr.tablenames', $fileQueryBuilder->createNamedParameter('tx_vitec_domain_model_download', ParameterType::STRING)), $fileQueryBuilder->expr()->eq('fr.fieldname', $fileQueryBuilder->createNamedParameter('file', ParameterType::STRING)), $fileQueryBuilder->expr()->eq('fr.deleted', 0), @@ -555,14 +714,20 @@ class ProductShowJsonRenderer } } + if ($fileInfo === null) { + $fileInfo = $this->resolveFileByConvention($fileprefix, $filetype); + } + $result[] = [ - 'uid' => (int)$download['uid'], + 'uid' => $downloadUid, 'title' => $download['title'] ?? '', 'slug' => $download['slug'] ?? '', 'teaser' => $download['teaser'] ?? '', 'description' => $download['description'] ?? '', 'keywords' => $download['keywords'] ?? '', 'icon' => $download['icon'] ?? '', + 'fileprefix' => $fileprefix, + 'filetype' => $filetype, 'file' => $fileInfo, ]; } diff --git a/packages/vitec/Classes/UserFunc/SolutionShowJsonRenderer.php b/packages/vitec/Classes/UserFunc/SolutionShowJsonRenderer.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/UserFunc/UsecaseListJsonRenderer.php b/packages/vitec/Classes/UserFunc/UsecaseListJsonRenderer.php old mode 100755 new mode 100644 index d6e6852..9d1d2b6 --- a/packages/vitec/Classes/UserFunc/UsecaseListJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/UsecaseListJsonRenderer.php @@ -4,34 +4,33 @@ declare(strict_types=1); namespace Evomedien\Vitec\UserFunc; - -use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use Doctrine\DBAL\ParameterType; +use Evomedien\Vitec\Service\UsecaseSerializer; +use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Service\ImageService; /** - * UserFunc to render the usecase list as JSON for headless output. + * UserFunc: render the Success Story list as JSON (headless). * - * `render()` = page discovery (top-level plugin). `renderForRecord()` = - * one specific tt_content row, reused by ContainerChildrenProcessor for - * usecase-list plugins nested in a b13 container. Exception-safe. + * `render()` = top-level plugin / page discovery. `renderForRecord()` = one + * specific tt_content row (reused by ContainerChildrenProcessor for nested + * usecase-list plugins). All serialisation is delegated to UsecaseSerializer. + * Exception-safe. */ class UsecaseListJsonRenderer { + private const TABLE = 'tx_vitec_domain_model_usecase'; + #[AsAllowedCallable] public function render(string $content, array $conf): string { - // 1) cObj data path $row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null; if ($row && (string)($row['CType'] ?? '') === 'vitec_usecaselist') { return $this->renderForRecord($row); } - // 2) Page-id via v14 request attribute (TSFE->id is often null in JSON cObj context) $pageId = 0; $request = $GLOBALS['TYPO3_REQUEST'] ?? null; if ($request !== null) { @@ -47,29 +46,26 @@ class UsecaseListJsonRenderer return ''; } - $queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class) - ->getQueryBuilderForTable('tt_content'); - - $contentElements = $queryBuilder + $qb = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content'); + $ces = $qb ->select('*') ->from('tt_content') ->where( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pageId, ParameterType::INTEGER)), - $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('vitec_usecaselist', ParameterType::STRING)), - $queryBuilder->expr()->eq('deleted', 0), - $queryBuilder->expr()->eq('hidden', 0) + $qb->expr()->eq('pid', $qb->createNamedParameter($pageId, ParameterType::INTEGER)), + $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_usecaselist', ParameterType::STRING)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) ) ->executeQuery() ->fetchAllAssociative(); - if (empty($contentElements)) { + if (empty($ces)) { return ''; } - return $this->renderForRecord($contentElements[0]); + return $this->renderForRecord($ces[0]); } - /** * @param array $contentElement */ @@ -81,167 +77,36 @@ class UsecaseListJsonRenderer $settings = $flexFormData['settings'] ?? []; $debugMode = (bool)($settings['debug'] ?? false); - $usecaseQb = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('tx_vitec_domain_model_usecase'); - - $usecases = $usecaseQb - ->select('u.*') - ->from('tx_vitec_domain_model_usecase', 'u') + $qb = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE); + $rows = $qb + ->select('*') + ->from(self::TABLE) ->where( - $usecaseQb->expr()->eq('u.deleted', 0), - $usecaseQb->expr()->eq('u.hidden', 0), - $usecaseQb->expr()->eq('u.hideonwebsite', 0) + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0), + $qb->expr()->eq('hideonwebsite', 0) ) - ->orderBy('u.title', 'ASC') + ->orderBy('featured', 'DESC') + ->addOrderBy('title', 'ASC') ->executeQuery() ->fetchAllAssociative(); - $usecasesData = []; - foreach ($usecases as $usecase) { - $usecasesData[] = $this->serializeUsecase($usecase); - } + $serializer = GeneralUtility::makeInstance(UsecaseSerializer::class); + $usecases = array_map( + static fn (array $u): array => $serializer->serializeListItem($u), + $rows + ); if ($debugMode) { - return json_encode([ - 'usecases' => $usecasesData, - 'debug' => [ - 'pageId' => (int)($GLOBALS['TSFE']->id ?? 0), - 'usecaseCount' => count($usecasesData), - 'settings' => $settings, - ], + return (string)json_encode([ + 'usecases' => $usecases, + 'debug' => ['count' => count($usecases), 'settings' => $settings], ]); } - return json_encode($usecasesData); + return (string)json_encode($usecases); } catch (\Throwable $e) { return ''; } } - - /** - * @param array $usecase - * @return array - */ - protected function serializeUsecase(array $usecase): array - { - $uid = (int)$usecase['uid']; - - return [ - 'uid' => $uid, - 'title' => (string)($usecase['title'] ?? ''), - 'slug' => (string)($usecase['slug'] ?? ''), - 'subtitle' => (string)($usecase['subtitle'] ?? ''), - 'teaser' => (string)($usecase['teaser'] ?? ''), - 'description' => (string)($usecase['description'] ?? ''), - 'singlepid' => (string)($usecase['singlepid'] ?? ''), - 'hideonapp' => (bool)($usecase['hideonapp'] ?? false), - 'hideonwebsite' => (bool)($usecase['hideonwebsite'] ?? false), - 'categories' => $this->getUsecaseCategories($uid), - 'caseimage' => $this->getUsecaseImage($uid, 'caseimage'), - 'logoimage' => $this->getUsecaseImage($uid, 'logoimage'), - ]; - } - - /** - * @return array|null - */ - protected function getUsecaseImage(int $usecaseUid, string $fieldName): ?array - { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('sys_file_reference'); - - $fileRefData = $queryBuilder - ->select('sfr.uid', 'sfr.title', 'sfr.description', 'sfr.alternative', 'sfr.crop') - ->from('sys_file_reference', 'sfr') - ->where( - $queryBuilder->expr()->eq('sfr.tablenames', $queryBuilder->createNamedParameter('tx_vitec_domain_model_usecase', ParameterType::STRING)), - $queryBuilder->expr()->eq('sfr.fieldname', $queryBuilder->createNamedParameter($fieldName, ParameterType::STRING)), - $queryBuilder->expr()->eq('sfr.uid_foreign', $queryBuilder->createNamedParameter($usecaseUid, ParameterType::INTEGER)), - $queryBuilder->expr()->eq('sfr.deleted', 0), - $queryBuilder->expr()->eq('sfr.hidden', 0) - ) - ->orderBy('sfr.sorting_foreign') - ->setMaxResults(1) - ->executeQuery() - ->fetchAssociative(); - - if (!$fileRefData) { - return null; - } - - try { - $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); - $imageService = GeneralUtility::makeInstance(ImageService::class); - $fileReference = $resourceFactory->getFileReferenceObject((int)$fileRefData['uid']); - - $srcset = []; - foreach ([400, 800, 1200, 1600] as $width) { - $variant = $imageService->applyProcessingInstructions( - $fileReference, - ['width' => $width, 'crop' => $fileRefData['crop'] ?? null] - ); - $srcset[] = [ - 'url' => $imageService->getImageUri($variant), - 'width' => $width, - 'descriptor' => $width . 'w', - ]; - } - - $default = $imageService->applyProcessingInstructions( - $fileReference, - ['width' => 800, 'crop' => $fileRefData['crop'] ?? null] - ); - - return [ - 'uid' => (int)$fileRefData['uid'], - 'url' => $imageService->getImageUri($default), - 'title' => $fileRefData['title'] ?? '', - 'alternative' => $fileRefData['alternative'] ?? '', - 'description' => $fileRefData['description'] ?? '', - 'srcset' => $srcset, - 'properties' => [ - 'width' => $fileReference->getProperty('width'), - 'height' => $fileReference->getProperty('height'), - 'mimeType' => $fileReference->getProperty('mime_type'), - ], - ]; - } catch (\Exception $e) { - return null; - } - } - - protected function getUsecaseCategories(int $usecaseUid): array - { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('sys_category'); - - $categories = $queryBuilder - ->select('c.uid', 'c.title', 'c.description') - ->from('sys_category', 'c') - ->join( - 'c', - 'sys_category_record_mm', - 'mm', - 'mm.uid_local = c.uid AND mm.tablenames = ' . - $queryBuilder->createNamedParameter('tx_vitec_domain_model_usecase', ParameterType::STRING) . - ' AND mm.fieldname = ' . - $queryBuilder->createNamedParameter('categories', ParameterType::STRING) - ) - ->where( - $queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->createNamedParameter($usecaseUid, ParameterType::INTEGER)), - $queryBuilder->expr()->eq('c.deleted', 0), - $queryBuilder->expr()->eq('c.hidden', 0) - ) - ->orderBy('mm.sorting', 'ASC') - ->executeQuery() - ->fetchAllAssociative(); - - return array_map(static function ($cat) { - return [ - 'uid' => (int)$cat['uid'], - 'title' => $cat['title'] ?? '', - 'description' => $cat['description'] ?? '', - ]; - }, $categories); - } } diff --git a/packages/vitec/Classes/UserFunc/UsecaseShowJsonRenderer.php b/packages/vitec/Classes/UserFunc/UsecaseShowJsonRenderer.php old mode 100755 new mode 100644 index 49459ec..2d0925c --- a/packages/vitec/Classes/UserFunc/UsecaseShowJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/UsecaseShowJsonRenderer.php @@ -4,34 +4,32 @@ declare(strict_types=1); namespace Evomedien\Vitec\UserFunc; - -use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use Doctrine\DBAL\ParameterType; +use Evomedien\Vitec\Service\UsecaseSerializer; +use TYPO3\CMS\Core\Attribute\AsAllowedCallable; use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Service\ImageService; /** - * UserFunc to render a single usecase as JSON for headless output. + * UserFunc: render a single Success Story as JSON (headless). * - * `render()` = page discovery (top-level plugin). `renderForRecord()` = - * one specific tt_content row, reused by ContainerChildrenProcessor for - * usecase-show plugins nested in a b13 container. Exception-safe. + * The story is chosen from the plugin FlexForm (settings.usecase) or, when + * empty, from the request param tx_vitec_usecaseshow[usecase] (uid or slug). + * Full serialisation is delegated to UsecaseSerializer. Exception-safe. */ class UsecaseShowJsonRenderer { + private const TABLE = 'tx_vitec_domain_model_usecase'; + #[AsAllowedCallable] public function render(string $content, array $conf): string { - // 1) cObj data path $row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null; if ($row && (string)($row['CType'] ?? '') === 'vitec_usecaseshow') { return $this->renderForRecord($row); } - // 2) Page-id via v14 request attribute (TSFE->id is often null in JSON cObj context) $pageId = 0; $request = $GLOBALS['TYPO3_REQUEST'] ?? null; if ($request !== null) { @@ -47,243 +45,104 @@ class UsecaseShowJsonRenderer return ''; } - $queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class) - ->getQueryBuilderForTable('tt_content'); - - $contentElements = $queryBuilder + $qb = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content'); + $ces = $qb ->select('*') ->from('tt_content') ->where( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pageId, ParameterType::INTEGER)), - $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('vitec_usecaseshow', ParameterType::STRING)), - $queryBuilder->expr()->eq('deleted', 0), - $queryBuilder->expr()->eq('hidden', 0) + $qb->expr()->eq('pid', $qb->createNamedParameter($pageId, ParameterType::INTEGER)), + $qb->expr()->eq('CType', $qb->createNamedParameter('vitec_usecaseshow', ParameterType::STRING)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) ) ->executeQuery() ->fetchAllAssociative(); - if (empty($contentElements)) { + if (empty($ces)) { return ''; } - return $this->renderForRecord($contentElements[0]); + return $this->renderForRecord($ces[0]); } - /** * @param array $contentElement */ public function renderForRecord(array $contentElement): string { try { - $pageId = (int)($GLOBALS['TSFE']->id ?? 0); - $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); $flexFormData = $flexFormService->convertFlexFormContentToArray($contentElement['pi_flexform'] ?? ''); $settings = $flexFormData['settings'] ?? []; - $usecaseUid = (int)($settings['usecase'] ?? 0); - $layout = (string)($settings['layout'] ?? 'default'); + $layout = (string)($settings['layout'] ?? 'default'); $debugMode = (bool)($settings['debug'] ?? false); + $usecaseUid = (int)($settings['usecase'] ?? 0); + // Fallback: uid/slug from the request (React detail route). if (!$usecaseUid) { - $routeParams = $GLOBALS['TYPO3_REQUEST']->getQueryParams(); - $usecaseParam = $routeParams['tx_vitec_usecaseshow']['usecase'] ?? null; - - if ($usecaseParam) { - if (!is_numeric($usecaseParam)) { - $slugQb = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('tx_vitec_domain_model_usecase'); - $bySlug = $slugQb - ->select('uid') - ->from('tx_vitec_domain_model_usecase') - ->where( - $slugQb->expr()->eq('slug', $slugQb->createNamedParameter($usecaseParam)), - $slugQb->expr()->eq('deleted', 0), - $slugQb->expr()->eq('hidden', 0) - ) - ->executeQuery() - ->fetchAssociative(); - $usecaseUid = (int)($bySlug['uid'] ?? 0); - } else { - $usecaseUid = (int)$usecaseParam; - } + $params = $GLOBALS['TYPO3_REQUEST']?->getQueryParams() ?? []; + $param = $params['tx_vitec_usecaseshow']['usecase'] ?? null; + if ($param !== null && $param !== '') { + $usecaseUid = is_numeric($param) ? (int)$param : $this->resolveSlug((string)$param); } } if (!$usecaseUid) { return $debugMode - ? json_encode(['error' => 'No usecase selected or found', 'debug' => ['settings' => $settings]]) + ? (string)json_encode(['error' => 'No usecase selected or found', 'debug' => ['settings' => $settings]]) : ''; } - $usecaseQb = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('tx_vitec_domain_model_usecase'); - - $usecase = $usecaseQb + $qb = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE); + $usecase = $qb ->select('*') - ->from('tx_vitec_domain_model_usecase') + ->from(self::TABLE) ->where( - $usecaseQb->expr()->eq('uid', $usecaseQb->createNamedParameter($usecaseUid, ParameterType::INTEGER)), - $usecaseQb->expr()->eq('deleted', 0), - $usecaseQb->expr()->eq('hidden', 0) + $qb->expr()->eq('uid', $qb->createNamedParameter($usecaseUid, ParameterType::INTEGER)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) ) ->executeQuery() ->fetchAssociative(); if (!$usecase) { return $debugMode - ? json_encode(['error' => 'Usecase not found', 'debug' => ['usecaseUid' => $usecaseUid]]) + ? (string)json_encode(['error' => 'Usecase not found', 'debug' => ['usecaseUid' => $usecaseUid]]) : ''; } + $serializer = GeneralUtility::makeInstance(UsecaseSerializer::class); + $response = [ - 'usecase' => $this->serializeUsecase($usecase), - 'layout' => $layout, - 'settings' => [ - 'layout' => $layout, - ], + 'usecase' => $serializer->serializeDetail($usecase), + 'layout' => $layout, ]; if ($debugMode) { - $response['debug'] = [ - 'pageId' => $pageId, - 'usecaseUid' => $usecaseUid, - 'layout' => $layout, - 'settings' => $settings, - ]; + $response['debug'] = ['usecaseUid' => $usecaseUid, 'layout' => $layout, 'settings' => $settings]; } - return json_encode($response); + return (string)json_encode($response); } catch (\Throwable $e) { return ''; } } - /** - * @param array $usecase - * @return array - */ - protected function serializeUsecase(array $usecase): array + private function resolveSlug(string $slug): int { - $uid = (int)$usecase['uid']; - - return [ - 'uid' => $uid, - 'title' => (string)($usecase['title'] ?? ''), - 'slug' => (string)($usecase['slug'] ?? ''), - 'subtitle' => (string)($usecase['subtitle'] ?? ''), - 'teaser' => (string)($usecase['teaser'] ?? ''), - 'description' => (string)($usecase['description'] ?? ''), - 'singlepid' => (string)($usecase['singlepid'] ?? ''), - 'hideonapp' => (bool)($usecase['hideonapp'] ?? false), - 'hideonwebsite' => (bool)($usecase['hideonwebsite'] ?? false), - 'categories' => $this->getUsecaseCategories($uid), - 'caseimage' => $this->getUsecaseImage($uid, 'caseimage'), - 'logoimage' => $this->getUsecaseImage($uid, 'logoimage'), - ]; - } - - /** - * @return array|null - */ - protected function getUsecaseImage(int $usecaseUid, string $fieldName): ?array - { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('sys_file_reference'); - - $fileRefData = $queryBuilder - ->select('sfr.uid', 'sfr.title', 'sfr.description', 'sfr.alternative', 'sfr.crop') - ->from('sys_file_reference', 'sfr') + $qb = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE); + $row = $qb + ->select('uid') + ->from(self::TABLE) ->where( - $queryBuilder->expr()->eq('sfr.tablenames', $queryBuilder->createNamedParameter('tx_vitec_domain_model_usecase', ParameterType::STRING)), - $queryBuilder->expr()->eq('sfr.fieldname', $queryBuilder->createNamedParameter($fieldName, ParameterType::STRING)), - $queryBuilder->expr()->eq('sfr.uid_foreign', $queryBuilder->createNamedParameter($usecaseUid, ParameterType::INTEGER)), - $queryBuilder->expr()->eq('sfr.deleted', 0), - $queryBuilder->expr()->eq('sfr.hidden', 0) + $qb->expr()->eq('slug', $qb->createNamedParameter($slug)), + $qb->expr()->eq('deleted', 0), + $qb->expr()->eq('hidden', 0) ) - ->orderBy('sfr.sorting_foreign') - ->setMaxResults(1) ->executeQuery() ->fetchAssociative(); - if (!$fileRefData) { - return null; - } - - try { - $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); - $imageService = GeneralUtility::makeInstance(ImageService::class); - $fileReference = $resourceFactory->getFileReferenceObject((int)$fileRefData['uid']); - - $srcset = []; - foreach ([400, 800, 1200, 1600] as $width) { - $variant = $imageService->applyProcessingInstructions( - $fileReference, - ['width' => $width, 'crop' => $fileRefData['crop'] ?? null] - ); - $srcset[] = [ - 'url' => $imageService->getImageUri($variant), - 'width' => $width, - 'descriptor' => $width . 'w', - ]; - } - - $default = $imageService->applyProcessingInstructions( - $fileReference, - ['width' => 800, 'crop' => $fileRefData['crop'] ?? null] - ); - - return [ - 'uid' => (int)$fileRefData['uid'], - 'url' => $imageService->getImageUri($default), - 'title' => $fileRefData['title'] ?? '', - 'alternative' => $fileRefData['alternative'] ?? '', - 'description' => $fileRefData['description'] ?? '', - 'srcset' => $srcset, - 'properties' => [ - 'width' => $fileReference->getProperty('width'), - 'height' => $fileReference->getProperty('height'), - 'mimeType' => $fileReference->getProperty('mime_type'), - ], - ]; - } catch (\Exception $e) { - return null; - } - } - - protected function getUsecaseCategories(int $usecaseUid): array - { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('sys_category'); - - $categories = $queryBuilder - ->select('c.uid', 'c.title', 'c.description') - ->from('sys_category', 'c') - ->join( - 'c', - 'sys_category_record_mm', - 'mm', - 'mm.uid_local = c.uid AND mm.tablenames = ' . - $queryBuilder->createNamedParameter('tx_vitec_domain_model_usecase', ParameterType::STRING) . - ' AND mm.fieldname = ' . - $queryBuilder->createNamedParameter('categories', ParameterType::STRING) - ) - ->where( - $queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->createNamedParameter($usecaseUid, ParameterType::INTEGER)), - $queryBuilder->expr()->eq('c.deleted', 0), - $queryBuilder->expr()->eq('c.hidden', 0) - ) - ->orderBy('mm.sorting', 'ASC') - ->executeQuery() - ->fetchAllAssociative(); - - return array_map(static function ($cat) { - return [ - 'uid' => (int)$cat['uid'], - 'title' => $cat['title'] ?? '', - 'description' => $cat['description'] ?? '', - ]; - }, $categories); + return (int)($row['uid'] ?? 0); } } diff --git a/packages/vitec/Classes/View/BackendLayoutDataProvider.php b/packages/vitec/Classes/View/BackendLayoutDataProvider.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Classes/View/VitecBackendLayoutView.php b/packages/vitec/Classes/View/VitecBackendLayoutView.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/Backend/AjaxRoutes.php b/packages/vitec/Configuration/Backend/AjaxRoutes.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/FlexForms/CardsCarousel.xml b/packages/vitec/Configuration/FlexForms/CardsCarousel.xml new file mode 100644 index 0000000..e9d86f1 --- /dev/null +++ b/packages/vitec/Configuration/FlexForms/CardsCarousel.xml @@ -0,0 +1,96 @@ + + + + + + Carousel Settings + array + + + + + select + selectSingle + + + + 4 + + + + 3 + + + + 2 + + + + 1 + + + 4 + + + + + + + check + 1 + + + + + + + check + 1 + + + + + + + check + 0 + + + + + + + check + 0 + + + + + + + number + 5000 + + + + + + + input + 30 + trim + + + + + + + check + 0 + + + + + + + diff --git a/packages/vitec/Configuration/FlexForms/Container.xml b/packages/vitec/Configuration/FlexForms/Container.xml old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/FlexForms/Downloadcard.xml b/packages/vitec/Configuration/FlexForms/Downloadcard.xml old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/FlexForms/Eventlist.xml b/packages/vitec/Configuration/FlexForms/Eventlist.xml new file mode 100644 index 0000000..c6e1b36 --- /dev/null +++ b/packages/vitec/Configuration/FlexForms/Eventlist.xml @@ -0,0 +1,48 @@ + + + + 1 + + + + + Event List Settings + array + + + + Only show upcoming events starting within the next N days, e.g. 60. + + number + 0 + + + + + + + check + 0 + + + + + + + number + 0 + + + + + + + check + 0 + + + + + + + diff --git a/packages/vitec/Configuration/Icons.php b/packages/vitec/Configuration/Icons.php old mode 100755 new mode 100644 index 0925a62..b3fdf59 --- a/packages/vitec/Configuration/Icons.php +++ b/packages/vitec/Configuration/Icons.php @@ -32,6 +32,10 @@ return [ 'provider' => SvgIconProvider::class, 'source' => 'EXT:vitec/Resources/Public/Icons/vitec-plugin-usecaselist.svg', ], + 'vitec-plugin-eventlist' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:vitec/Resources/Public/Icons/vitec-plugin-eventlist.svg', + ], 'vitec-plugin-downloadcard' => [ 'provider' => SvgIconProvider::class, 'source' => 'EXT:vitec/Resources/Public/Icons/vitec-plugin-downloadcard.svg', diff --git a/packages/vitec/Configuration/JavaScriptModules.php b/packages/vitec/Configuration/JavaScriptModules.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/Sets/Vitecset/config.yaml b/packages/vitec/Configuration/Sets/Vitecset/config.yaml old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/Sets/Vitecset/setup.typoscript b/packages/vitec/Configuration/Sets/Vitecset/setup.typoscript old mode 100755 new mode 100644 index e77c74b..6bc1a58 --- a/packages/vitec/Configuration/Sets/Vitecset/setup.typoscript +++ b/packages/vitec/Configuration/Sets/Vitecset/setup.typoscript @@ -20,7 +20,7 @@ config { # ============================================================================= tt_content { - vitec_productlist < lib.contentElement + vitec_productlist < lib.contentElementWithHeader vitec_productlist { fields { content { @@ -32,7 +32,28 @@ tt_content { } } - vitec_productshow < lib.contentElement + news_pi1 < lib.contentElementWithHeader + news_pi1 { + fields { + content { + fields { + news = USER + news.userFunc = Evomedien\Vitec\UserFunc\NewsJsonRenderer->render + } + } + } + } + + news_newsliststicky < tt_content.news_pi1 + news_newsselectedlist < tt_content.news_pi1 + news_newsdetail < tt_content.news_pi1 + news_newsdatemenu < tt_content.news_pi1 + news_categorylist < tt_content.news_pi1 + news_newssearchform < tt_content.news_pi1 + news_newssearchresult < tt_content.news_pi1 + news_taglist < tt_content.news_pi1 + + vitec_productshow < lib.contentElementWithHeader vitec_productshow { fields { content { @@ -44,7 +65,7 @@ tt_content { } } - vitec_usecaselist < lib.contentElement + vitec_usecaselist < lib.contentElementWithHeader vitec_usecaselist { fields { content { @@ -56,7 +77,7 @@ tt_content { } } - vitec_usecaseshow < lib.contentElement + vitec_usecaseshow < lib.contentElementWithHeader vitec_usecaseshow { fields { content { @@ -68,7 +89,7 @@ tt_content { } } - vitec_marketshow < lib.contentElement + vitec_marketshow < lib.contentElementWithHeader vitec_marketshow { fields { content { @@ -80,7 +101,7 @@ tt_content { } } - vitec_solutionshow < lib.contentElement + vitec_solutionshow < lib.contentElementWithHeader vitec_solutionshow { fields { content { @@ -92,7 +113,7 @@ tt_content { } } - vitec_downloadcard < lib.contentElement + vitec_downloadcard < lib.contentElementWithHeader vitec_downloadcard { fields { content { @@ -104,7 +125,7 @@ tt_content { } } - vitec_downloadcardcollection < lib.contentElement + vitec_downloadcardcollection < lib.contentElementWithHeader vitec_downloadcardcollection { fields { content { @@ -116,7 +137,7 @@ tt_content { } } - vitec_datasheets < lib.contentElement + vitec_datasheets < lib.contentElementWithHeader vitec_datasheets { fields { content { @@ -127,6 +148,18 @@ tt_content { } } } + + vitec_eventlist =< lib.contentElementWithHeader + vitec_eventlist { + fields { + content { + fields { + eventlist = USER + eventlist.userFunc = Evomedien\Vitec\UserFunc\EventlistJsonRenderer->render + } + } + } + } } # Include container (layout) rendering definitions diff --git a/packages/vitec/Configuration/TCA/Overrides/pages.php b/packages/vitec/Configuration/TCA/Overrides/pages.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content.php b/packages/vitec/Configuration/TCA/Overrides/tt_content.php index ac8a692..119452a 100644 --- a/packages/vitec/Configuration/TCA/Overrides/tt_content.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content.php @@ -34,6 +34,7 @@ use TYPO3\CMS\Extbase\Utility\ExtensionUtility; $registerPluginWithFlexForm('Downloadcard', 'Download Card', 'FILE:EXT:vitec/Configuration/FlexForms/Downloadcard.xml', 'vitec-plugin-downloadcard'); $registerPluginWithFlexForm('Downloadcardcollection', 'Download Card Collection', 'FILE:EXT:vitec/Configuration/FlexForms/Downloadcardcollection.xml', 'vitec-plugin-downloadcardcollection'); $registerPluginWithFlexForm('Datasheets', 'Datasheets', 'FILE:EXT:vitec/Configuration/FlexForms/Datasheets.xml'); + $registerPluginWithFlexForm('Eventlist', 'Event List', 'FILE:EXT:vitec/Configuration/FlexForms/Eventlist.xml', 'vitec-plugin-eventlist'); // Change frame_class to allow multiple selections. $GLOBALS['TCA']['tt_content']['columns']['frame_class']['config']['renderType'] = 'selectCheckBox'; @@ -50,4 +51,9 @@ use TYPO3\CMS\Extbase\Utility\ExtensionUtility; ['label' => 'Vitec: Highlight Box', 'value' => 'vitec-highlight'], ] ); + + // Inline parent pointer: content elements owned by a Success Story record. + $GLOBALS['TCA']['tt_content']['columns']['tx_vitec_usecase_content'] = [ + 'config' => ['type' => 'passthrough'], + ]; })(); diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cards_carousel.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cards_carousel.php new file mode 100644 index 0000000..99c28ce --- /dev/null +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cards_carousel.php @@ -0,0 +1,63 @@ +configureContainer( + (new ContainerConfiguration( + 'vitec_cards_carousel', + $l . 'cards_carousel.title', + $l . 'cards_carousel.description', + [ + [ + ['name' => $l . 'cards_carousel.column', 'colPos' => 260], + ], + ] + )) + ->setIcon('EXT:vitec/Resources/Public/Icons/vitec-cards-carousel.svg') + ->setGroup('vitec_custom_components') + ->setSaveAndCloseInNewContentElementWizard(true) + ); + + $GLOBALS['TCA']['tt_content']['types']['vitec_cards_carousel']['showitem'] = + '--palette--;;general, + --palette--;;headers, + tx_vitec_bg_variant, + pi_flexform;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:cards_carousel.flexform.label, + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, + --palette--;;frames, + --palette--;;appearanceLinks, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, + --palette--;;language, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, + --palette--;;hidden, + --palette--;;access'; + + ExtensionManagementUtility::addPiFlexFormValue( + '*', + 'FILE:EXT:vitec/Configuration/FlexForms/CardsCarousel.xml', + 'vitec_cards_carousel' + ); + + $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] = ($GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] ?? '') . "\n" . <<<'TSCONFIG' +mod.wizards.newContentElement.wizardItems.vitec_custom_components.elements.vitec_cards_carousel { + iconIdentifier = vitec-cards-carousel + title = LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:cards_carousel.title + description = LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:cards_carousel.description + tt_content_defValues { + CType = vitec_cards_carousel + } +} +TSCONFIG; +})(); diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_25_25_25_25.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_25_25_25_25.php old mode 100755 new mode 100644 index e35ed3f..83bcb18 --- a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_25_25_25_25.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_25_25_25_25.php @@ -35,10 +35,14 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; $GLOBALS['TCA']['tt_content']['types']['vitec_cols_25_25_25_25']['showitem'] = '--palette--;;general, - header;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.heading, - subheader;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.subline, + --palette--;;headers, tx_vitec_bg_variant, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:palette.grid;vitec_grid, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.1;vitec_col1_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.2;vitec_col2_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.3;vitec_col3_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.4;vitec_col4_flex, --palette--;;frames, --palette--;;appearanceLinks, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_33_33.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_33_33.php old mode 100755 new mode 100644 index 84f26a1..d537a95 --- a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_33_33.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_33_33.php @@ -34,10 +34,13 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; $GLOBALS['TCA']['tt_content']['types']['vitec_cols_33_33_33']['showitem'] = '--palette--;;general, - header;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.heading, - subheader;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.subline, + --palette--;;headers, tx_vitec_bg_variant, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:palette.grid;vitec_grid, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.1;vitec_col1_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.2;vitec_col2_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.3;vitec_col3_flex, --palette--;;frames, --palette--;;appearanceLinks, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_66.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_66.php old mode 100755 new mode 100644 index f068f00..299049a --- a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_66.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_33_66.php @@ -33,10 +33,12 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; $GLOBALS['TCA']['tt_content']['types']['vitec_cols_33_66']['showitem'] = '--palette--;;general, - header;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.heading, - subheader;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.subline, + --palette--;;headers, tx_vitec_bg_variant, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:palette.grid;vitec_grid, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.sidebar_33;vitec_col1_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.main_66;vitec_col2_flex, --palette--;;frames, --palette--;;appearanceLinks, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_50_50.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_50_50.php old mode 100755 new mode 100644 index a183cf9..25062d5 --- a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_50_50.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_50_50.php @@ -33,10 +33,12 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; $GLOBALS['TCA']['tt_content']['types']['vitec_cols_50_50']['showitem'] = '--palette--;;general, - header;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.heading, - subheader;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.subline, + --palette--;;headers, tx_vitec_bg_variant, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:palette.grid;vitec_grid, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.1;vitec_col1_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.2;vitec_col2_flex, --palette--;;frames, --palette--;;appearanceLinks, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_66_33.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_66_33.php old mode 100755 new mode 100644 index a387c9d..b0df6dd --- a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_66_33.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_cols_66_33.php @@ -33,10 +33,12 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; $GLOBALS['TCA']['tt_content']['types']['vitec_cols_66_33']['showitem'] = '--palette--;;general, - header;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.heading, - subheader;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.subline, + --palette--;;headers, tx_vitec_bg_variant, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:palette.grid;vitec_grid, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.main_66;vitec_col1_flex, + --palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:column.sidebar_33;vitec_col2_flex, --palette--;;frames, --palette--;;appearanceLinks, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_container.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_container.php old mode 100755 new mode 100644 index 1c1f031..3a8088f --- a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_container.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_container.php @@ -32,8 +32,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; $GLOBALS['TCA']['tt_content']['types']['vitec_container']['showitem'] = '--palette--;;general, - header;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.heading, - subheader;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:section.subline, + --palette--;;headers, tx_vitec_bg_variant, pi_flexform;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:container.flexform.label, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, diff --git a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_shared.php b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_shared.php old mode 100755 new mode 100644 index 75a962a..654b6a6 --- a/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_shared.php +++ b/packages/vitec/Configuration/TCA/Overrides/tt_content_vitec_shared.php @@ -27,6 +27,87 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; ], ]); + // ------------------------------------------------------------------------- + // Shared parent-level setting: column gap scale (1–5) for the whole grid. + // Concerns the container itself (not a single column); maps to a spacing + // token in the React frontend. Rendered in the "Grid" palette on top of the + // Appearance tab, above the per-column rows. + // ------------------------------------------------------------------------- + ExtensionManagementUtility::addTCAcolumns('tt_content', [ + 'tx_vitec_gap' => [ + 'label' => $l . 'gap.label', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['label' => $l . 'gap.option.1', 'value' => '1'], + ['label' => $l . 'gap.option.2', 'value' => '2'], + ['label' => $l . 'gap.option.3', 'value' => '3'], + ['label' => $l . 'gap.option.4', 'value' => '4'], + ['label' => $l . 'gap.option.5', 'value' => '5'], + ], + 'default' => '3', + ], + ], + ]); + + // Parent-element palette: settings that concern the whole grid, not a column. + $GLOBALS['TCA']['tt_content']['palettes']['vitec_grid'] = [ + 'showitem' => 'tx_vitec_gap', + ]; + + // ------------------------------------------------------------------------- + // Shared per-column flex alignment fields for the X-column containers. + // Positional: col1 = first column, col2 = second, ... (max 4 columns). + // "Align" -> CSS align-items (cross-axis alignment of the column's items) + // "Justify" -> CSS justify-content (main-axis distribution within the column) + // Reused across vitec_cols_50_50 / 33_66 / 66_33 / 33_33_33 / 25_25_25_25. + // ------------------------------------------------------------------------- + $alignItems = [ + ['label' => $l . 'flex.align.flex_start', 'value' => 'flex-start'], + ['label' => $l . 'flex.align.center', 'value' => 'center'], + ['label' => $l . 'flex.align.flex_end', 'value' => 'flex-end'], + ['label' => $l . 'flex.align.stretch', 'value' => 'stretch'], + ]; + $justifyItems = [ + ['label' => $l . 'flex.justify.flex_start', 'value' => 'flex-start'], + ['label' => $l . 'flex.justify.center', 'value' => 'center'], + ['label' => $l . 'flex.justify.space_between', 'value' => 'space-between'], + ['label' => $l . 'flex.justify.space_around', 'value' => 'space-around'], + ['label' => $l . 'flex.justify.space_evenly', 'value' => 'space-evenly'], + ]; + + $columnFields = []; + for ($i = 1; $i <= 4; $i++) { + $columnFields['tx_vitec_col' . $i . '_align'] = [ + 'label' => $l . 'flex.align.label', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => $alignItems, + 'default' => 'stretch', + ], + ]; + $columnFields['tx_vitec_col' . $i . '_justify'] = [ + 'label' => $l . 'flex.justify.label', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => $justifyItems, + 'default' => 'flex-start', + ], + ]; + } + ExtensionManagementUtility::addTCAcolumns('tt_content', $columnFields); + + // One palette per column: Align + Justify on a single row. The visible row + // label is overridden per container in its showitem (--palette--;;). + for ($i = 1; $i <= 4; $i++) { + $GLOBALS['TCA']['tt_content']['palettes']['vitec_col' . $i . '_flex'] = [ + 'showitem' => 'tx_vitec_col' . $i . '_align, tx_vitec_col' . $i . '_justify', + ]; + } + // Register VITEC wizard group header $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] = ($GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] ?? '') . "\n" . <<<'TSCONFIG' mod.wizards.newContentElement.wizardItems.vitec { diff --git a/packages/vitec/Configuration/TCA/tx_vitec_domain_model_event.php b/packages/vitec/Configuration/TCA/tx_vitec_domain_model_event.php new file mode 100644 index 0000000..933dafd --- /dev/null +++ b/packages/vitec/Configuration/TCA/tx_vitec_domain_model_event.php @@ -0,0 +1,290 @@ + [ + 'title' => 'VITEC Event', + 'label' => 'title', + 'label_alt' => 'city,eventstart', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'versioningWS' => true, + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l10n_parent', + 'transOrigDiffSourceField' => 'l10n_diffsource', + 'delete' => 'deleted', + 'default_sortby' => 'eventstart ASC', + 'enablecolumns' => [ + 'disabled' => 'hidden', + 'starttime' => 'starttime', + 'endtime' => 'endtime', + ], + 'searchFields' => 'title,teaser,venue,booth,city,country', + 'iconfile' => 'EXT:vitec/Resources/Public/Icons/tx_vitec_domain_model_event.svg', + 'security' => [ + 'ignorePageTypeRestriction' => true, + ], + ], + 'types' => [ + '1' => [ + 'showitem' => 'title, slug, teaser, description, + --div--;Event Details, eventstart, eventend, venue, booth, city, country, attendancemode, eventstatus, + --div--;Links and Media, eventurl, meetinglink, image, + --div--;Visibility, hideonwebsite, hideonapp, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories, categories, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, sys_language_uid, l10n_parent, l10n_diffsource, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, hidden, starttime, endtime', + ], + ], + 'columns' => [ + 'sys_language_uid' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', + 'config' => [ + 'type' => 'language', + ], + ], + 'l10n_parent' => [ + 'displayCond' => 'FIELD:sys_language_uid:>:0', + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'default' => 0, + 'items' => [ + ['label' => '', 'value' => 0], + ], + 'foreign_table' => 'tx_vitec_domain_model_event', + 'foreign_table_where' => 'AND {#tx_vitec_domain_model_event}.{#pid}=###CURRENT_PID### AND {#tx_vitec_domain_model_event}.{#sys_language_uid} IN (-1,0)', + ], + ], + 'l10n_diffsource' => [ + 'config' => [ + 'type' => 'passthrough', + ], + ], + 'hidden' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible', + 'config' => [ + 'type' => 'check', + 'renderType' => 'checkboxToggle', + 'items' => [ + [ + 'label' => '', + 'invertStateDisplay' => true, + ], + ], + ], + ], + 'starttime' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime', + 'config' => [ + 'type' => 'datetime', + 'default' => 0, + ], + ], + 'endtime' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', + 'config' => [ + 'type' => 'datetime', + 'default' => 0, + ], + ], + + 'title' => [ + 'exclude' => false, + 'label' => 'Event Name', + 'config' => [ + 'type' => 'input', + 'size' => 40, + 'max' => 255, + 'eval' => 'trim', + 'required' => true, + ], + ], + 'slug' => [ + 'exclude' => true, + 'label' => 'Slug', + 'config' => [ + 'type' => 'slug', + 'size' => 50, + 'generatorOptions' => [ + 'fields' => ['title'], + 'replacements' => ['/' => '-'], + ], + 'fallbackCharacter' => '-', + 'eval' => 'uniqueInSite', + 'default' => '', + ], + ], + 'teaser' => [ + 'exclude' => true, + 'label' => 'Teaser', + 'config' => [ + 'type' => 'input', + 'size' => 40, + 'max' => 255, + 'eval' => 'trim', + ], + ], + 'description' => [ + 'exclude' => true, + 'label' => 'Description', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 8, + 'enableRichtext' => true, + ], + ], + + 'eventstart' => [ + 'exclude' => false, + 'label' => 'Event Start Date', + 'config' => [ + 'type' => 'datetime', + 'format' => 'date', + 'default' => 0, + 'required' => true, + ], + ], + 'eventend' => [ + 'exclude' => true, + 'label' => 'Event End Date', + 'config' => [ + 'type' => 'datetime', + 'format' => 'date', + 'default' => 0, + ], + ], + 'venue' => [ + 'exclude' => true, + 'label' => 'Venue', + 'description' => 'e.g. "Queen Sirikit National Convention Center (QSNCC)"', + 'config' => [ + 'type' => 'input', + 'size' => 40, + 'max' => 255, + 'eval' => 'trim', + ], + ], + 'booth' => [ + 'exclude' => true, + 'label' => 'Booth / Stand', + 'description' => 'e.g. "Stand H10"', + 'config' => [ + 'type' => 'input', + 'size' => 20, + 'max' => 255, + 'eval' => 'trim', + ], + ], + 'city' => [ + 'exclude' => true, + 'label' => 'City', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'max' => 255, + 'eval' => 'trim', + ], + ], + 'country' => [ + 'exclude' => true, + 'label' => 'Country', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'max' => 255, + 'eval' => 'trim', + ], + ], + 'attendancemode' => [ + 'exclude' => true, + 'label' => 'Attendance Mode', + 'description' => 'Used for schema.org structured data (eventAttendanceMode).', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'default' => 'offline', + 'items' => [ + ['label' => 'On-site (offline)', 'value' => 'offline'], + ['label' => 'Online', 'value' => 'online'], + ['label' => 'Hybrid (mixed)', 'value' => 'mixed'], + ], + ], + ], + 'eventstatus' => [ + 'exclude' => true, + 'label' => 'Event Status', + 'description' => 'Used for schema.org structured data (eventStatus).', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'default' => 'scheduled', + 'items' => [ + ['label' => 'Scheduled', 'value' => 'scheduled'], + ['label' => 'Cancelled', 'value' => 'cancelled'], + ['label' => 'Postponed', 'value' => 'postponed'], + ['label' => 'Rescheduled', 'value' => 'rescheduled'], + ['label' => 'Moved Online', 'value' => 'movedonline'], + ], + ], + ], + + 'eventurl' => [ + 'exclude' => true, + 'label' => 'Event Website', + 'config' => [ + 'type' => 'link', + 'allowedTypes' => ['url', 'page'], + ], + ], + 'meetinglink' => [ + 'exclude' => true, + 'label' => 'Book-a-Meeting Link', + 'description' => 'Link or email for the "Book a Meeting" call-to-action.', + 'config' => [ + 'type' => 'link', + 'allowedTypes' => ['url', 'email', 'page'], + ], + ], + 'image' => [ + 'exclude' => true, + 'label' => 'Event Logo / Image', + 'config' => [ + 'type' => 'file', + 'maxitems' => 1, + 'allowed' => 'common-image-types', + ], + ], + + 'hideonwebsite' => [ + 'exclude' => true, + 'label' => 'Hide on Website', + 'config' => [ + 'type' => 'check', + 'renderType' => 'checkboxToggle', + 'default' => 0, + ], + ], + 'hideonapp' => [ + 'exclude' => true, + 'label' => 'Hide in App', + 'config' => [ + 'type' => 'check', + 'renderType' => 'checkboxToggle', + 'default' => 0, + ], + ], + + 'categories' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.categories', + 'config' => [ + 'type' => 'category', + ], + ], + ], +]; diff --git a/packages/vitec/Configuration/TCA/tx_vitec_domain_model_product.php b/packages/vitec/Configuration/TCA/tx_vitec_domain_model_product.php old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/TCA/tx_vitec_domain_model_usecase.php b/packages/vitec/Configuration/TCA/tx_vitec_domain_model_usecase.php index 8ac1fd6..3581804 100644 --- a/packages/vitec/Configuration/TCA/tx_vitec_domain_model_usecase.php +++ b/packages/vitec/Configuration/TCA/tx_vitec_domain_model_usecase.php @@ -1,6 +1,6 @@ [ + 'ctrl' => [ 'title' => 'VITEC Success Story', 'label' => 'title', 'tstamp' => 'tstamp', @@ -16,303 +16,325 @@ return [ 'starttime' => 'starttime', 'endtime' => 'endtime', ], - 'searchFields' => 'title,slug', + 'searchFields' => 'title,slug,subtitle,teaser,seo_title,seo_description', 'iconfile' => 'EXT:vitec/Resources/Public/Icons/tx_vitec_domain_model_usecase.gif', 'security' => [ 'ignorePageTypeRestriction' => true, ], ], - 'types' => [ - '1' => ['showitem' => 'title, slug, subtitle, teaser, description, singlepid, caseimage, logoimage, - --div--;Visibility, hideonapp, hideonwebsite, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, sys_language_uid, l10n_parent, l10n_diffsource, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories, categories, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, hidden, starttime, endtime', ], + 'types' => [ + '1' => [ + 'showitem' => + '--div--;General, + title, slug, subtitle, + --div--;List view, + card_image, customer_logo, teaser, + --div--;Detail · Hero, + hero_bgimage, hero_small_image, hero_video, hero_overlay_color, hero_overlay_opacity, + --div--;Detail · Content, + content_elements, + --div--;Detail · Related, + market, solutions, products, categories, + --div--;SEO, + seo_title, seo_description, no_index, no_follow, canonical_link, + --palette--;Open Graph;ogPalette, + --palette--;Twitter;twitterPalette, + --div--;Appearance, + layout_variant, background_variant, accent_color, + featured, show_related, hero_layout, text_theme, + --palette--;Visibility;visibilityPalette, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, + sys_language_uid, l10n_parent, l10n_diffsource, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, + hidden, starttime, endtime', + ], ], - 'columns' => [ + 'palettes' => [ + 'ogPalette' => ['showitem' => 'og_title, og_description, --linebreak--, og_image'], + 'twitterPalette' => ['showitem' => 'twitter_title, twitter_description, --linebreak--, twitter_image'], + 'visibilityPalette' => ['showitem' => 'hideonwebsite, hideonapp'], + ], + 'columns' => [ + // ------------------------------------------------------------ system 'sys_language_uid' => [ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', - 'config' => [ - 'type' => 'language', - ], + 'config' => ['type' => 'language'], ], - 'l10n_parent' => [ + 'l10n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', 'default' => 0, - 'items' => [ - ['', 0], - ], - 'foreign_table' => 'tx_vitec_domain_model_download', - 'foreign_table_where' => 'AND {#tx_vitec_domain_model_download}.{#pid}=###CURRENT_PID### AND {#tx_vitec_domain_model_download}.{#sys_language_uid} IN (-1,0)', + 'items' => [['label' => '', 'value' => 0]], + 'foreign_table' => 'tx_vitec_domain_model_usecase', + 'foreign_table_where' => 'AND {#tx_vitec_domain_model_usecase}.{#pid}=###CURRENT_PID### AND {#tx_vitec_domain_model_usecase}.{#sys_language_uid} IN (-1,0)', ], ], - 'l10n_diffsource' => [ - 'config' => [ - 'type' => 'passthrough', - ], - ], - 'hidden' => [ + 'l10n_diffsource' => ['config' => ['type' => 'passthrough']], + 'hidden' => [ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible', 'config' => [ 'type' => 'check', 'renderType' => 'checkboxToggle', - 'items' => [ - [ - 0 => '', - 1 => '', - 'invertStateDisplay' => true, - ], - ], + 'items' => [['value' => '', 'label' => '', 'invertStateDisplay' => true]], ], ], - 'starttime' => [ + 'starttime' => [ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime', - 'config' => [ - 'type' => 'input', - 'renderType' => 'inputDateTime', - 'eval' => 'datetime,int', - 'default' => 0, - 'behaviour' => [ - 'allowLanguageSynchronization' => true, - ], - ], + 'config' => ['type' => 'datetime', 'default' => 0, 'behaviour' => ['allowLanguageSynchronization' => true]], ], - 'endtime' => [ + 'endtime' => [ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', - 'config' => [ - 'type' => 'input', - 'renderType' => 'inputDateTime', - 'eval' => 'datetime,int', - 'default' => 0, - 'range' => [ - 'upper' => mktime(0, 0, 0, 1, 1, 2038), - ], - 'behaviour' => [ - 'allowLanguageSynchronization' => true, - ], - ], + 'config' => ['type' => 'datetime', 'default' => 0, 'range' => ['upper' => mktime(0, 0, 0, 1, 1, 2038)], 'behaviour' => ['allowLanguageSynchronization' => true]], ], - 'title' => [ - 'exclude' => false, - 'label' => 'LLL:EXT:vitec/Resources/Private/Language/locallang_db.xlf:tx_vitec_domain_model_download.title', - 'description' => 'LLL:EXT:vitec/Resources/Private/Language/locallang_db.xlf:tx_vitec_domain_model_download.title.description', - 'config' => [ - 'type' => 'input', - 'size' => 30, - 'eval' => 'trim', - 'required' => true, - 'default' => '', - ], + // ----------------------------------------------------------- General + 'title' => [ + 'label' => 'Title', + 'config' => ['type' => 'input', 'size' => 40, 'eval' => 'trim', 'required' => true, 'default' => ''], ], - 'slug' => [ - 'exclude' => false, - 'label' => 'LLL:EXT:vitec/Resources/Private/Language/locallang_db.xlf:tx_vitec_domain_model_download.slug', - 'description' => 'LLL:EXT:vitec/Resources/Private/Language/locallang_db.xlf:tx_vitec_domain_model_download.slug.description', - 'config' => [ + 'slug' => [ + 'label' => 'Slug', + 'config' => [ 'type' => 'slug', 'size' => 50, - 'generatorOptions' => [ - 'fields' => ['title'], // TODO: adjust this field to the one you want to use - 'fieldSeparator' => '-', - 'replacements' => [ - '/' => '', - ], - ], + 'generatorOptions' => ['fields' => ['title'], 'fieldSeparator' => '-', 'replacements' => ['/' => '']], 'fallbackCharacter' => '-', 'eval' => 'uniqueInPid', ], + ], + 'subtitle' => [ + 'label' => 'Subtitle', + 'config' => ['type' => 'input', 'size' => 40, 'eval' => 'trim', 'default' => ''], + ], + // --------------------------------------------------------- List view + 'card_image' => [ + 'label' => 'Card Image', + 'config' => ['type' => 'file', 'maxitems' => 1, 'allowed' => 'common-image-types'], ], - 'singlepid' => [ - 'exclude' => false, - 'label' => 'Page ID of Success Story', - 'description' => 'LLL:EXT:vitec/Resources/Private/Language/locallang_db.xlf:tx_vitec_domain_model_download.title.description', - 'config' => [ - 'type' => 'input', - 'size' => 30, - 'eval' => 'trim', - 'required' => false, - 'default' => '', - ], + 'customer_logo' => [ + 'label' => 'Customer Logo', + 'config' => ['type' => 'file', 'maxitems' => 1, 'allowed' => 'common-image-types'], ], - 'teaser' => [ - 'exclude' => true, - 'label' => 'Short Teaser (optional)', - 'config' => [ - 'type' => 'input', - 'size' => 30, - 'eval' => 'trim', - 'default' => '', - ], + 'teaser' => [ + 'label' => 'Teaser', + 'config' => ['type' => 'text', 'cols' => 40, 'rows' => 4, 'eval' => 'trim'], ], - 'subtitle' => [ - 'exclude' => true, - 'label' => 'Subtitle', - 'config' => [ - 'type' => 'input', - 'size' => 30, - 'eval' => 'trim', - 'default' => '', - ], + + // ------------------------------------------------------ Detail · Hero + 'hero_bgimage' => [ + 'label' => 'Background Image', + 'config' => ['type' => 'file', 'maxitems' => 1, 'allowed' => 'common-image-types'], ], - 'hideonapp' => [ - 'exclude' => true, - 'label' => 'If checked - Product will not be shown on App', - 'config' => [ - 'type' => 'check', - 'renderType' => 'checkboxToggle', - 'items' => [ - [ - 0 => '', - 1 => '', - 'invertStateDisplay' => false, - ], - ], - ], + 'hero_small_image' => [ + 'label' => 'Small Image', + 'config' => ['type' => 'file', 'maxitems' => 1, 'allowed' => 'common-image-types'], ], - 'hideonwebsite' => [ - 'exclude' => true, - 'label' => 'If checked - Product will not be shown on Website', - 'config' => [ - 'type' => 'check', - 'renderType' => 'checkboxToggle', - 'items' => [ - [ - 0 => '', - 1 => '', - 'invertStateDisplay' => false, - ], - ], - ], + 'hero_video' => [ + 'label' => 'Video', + 'config' => ['type' => 'file', 'maxitems' => 1, 'allowed' => 'mp4,webm,ogv,mov,m4v'], ], - 'description' => [ - 'exclude' => true, - 'label' => 'Description', - 'config' => [ - 'type' => 'text', - 'enableRichtext' => 'true', - 'eval' => 'trim', - 'default' => '', - ], - 'defaultExtras' => 'richtext:rte_transform[mode=ts_css]', + 'hero_overlay_color' => [ + 'label' => 'Overlay Color', + 'config' => ['type' => 'color'], ], - 'caseimage' => [ - 'exclude' => true, - 'label' => 'Case Image', - 'config' => [ - 'type' => 'inline', - 'foreign_table' => 'sys_file_reference', - 'foreign_field' => 'uid_foreign', - 'foreign_sortby' => 'sorting_foreign', - 'foreign_table_field' => 'tablenames', - 'foreign_match_fields' => [ - 'fieldname' => 'caseimage', - ], - 'foreign_label' => 'uid_local', - 'foreign_selector' => 'uid_local', - 'overrideChildTca' => [ - 'columns' => [ - 'uid_local' => [ - 'config' => [ - 'appearance' => [ - 'elementBrowserType' => 'file', - 'elementBrowserAllowed' => 'jpg,jpeg,png,gif', - ], - ], - ], - ], - 'types' => [ - '0' => [ - 'showitem' => ' - --palette--;;imageoverlayPalette, - --palette--;;filePalette', - ], - ], - ], - 'maxitems' => 1, - 'appearance' => [ - 'headerThumbnail' => [ - 'field' => 'uid_local', - 'width' => '45', - 'height' => '45', - ], - 'enabledControls' => [ - 'info' => true, - 'new' => false, - 'dragdrop' => true, - 'sort' => false, - 'hide' => true, - 'delete' => true, - ], - 'fileUploadAllowed' => true, - ], - ], - ], - 'logoimage' => [ - 'exclude' => true, - 'label' => 'Customer Logo', - 'config' => [ - 'type' => 'inline', - 'foreign_table' => 'sys_file_reference', - 'foreign_field' => 'uid_foreign', - 'foreign_sortby' => 'sorting_foreign', - 'foreign_table_field' => 'tablenames', - 'foreign_match_fields' => [ - 'fieldname' => 'logoimage', - ], - 'foreign_label' => 'uid_local', - 'foreign_selector' => 'uid_local', - 'overrideChildTca' => [ - 'columns' => [ - 'uid_local' => [ - 'config' => [ - 'appearance' => [ - 'elementBrowserType' => 'file', - 'elementBrowserAllowed' => 'jpg,jpeg,png,gif', - ], - ], - ], - ], - 'types' => [ - '0' => [ - 'showitem' => ' - --palette--;;imageoverlayPalette, - --palette--;;filePalette', - ], - ], - ], - 'maxitems' => 1, - 'appearance' => [ - 'headerThumbnail' => [ - 'field' => 'uid_local', - 'width' => '45', - 'height' => '45', - ], - 'enabledControls' => [ - 'info' => true, - 'new' => false, - 'dragdrop' => true, - 'sort' => false, - 'hide' => true, - 'delete' => true, - ], - 'fileUploadAllowed' => true, - ], - ], - ], - 'categories' => [ + 'hero_overlay_opacity' => [ + 'label' => 'Overlay Opacity (0–1)', 'config' => [ - 'type' => 'category' - ] + 'type' => 'number', + 'format' => 'decimal', + 'default' => 0, + 'range' => ['lower' => 0, 'upper' => 1], + 'slider' => ['step' => 0.05, 'width' => 200], + ], + ], + + // --------------------------------------------------- Detail · Content + 'content_elements' => [ + 'label' => 'Content Elements', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tt_content', + 'foreign_field' => 'tx_vitec_usecase_content', + 'foreign_sortby' => 'sorting', + 'appearance' => [ + 'collapseAll' => true, + 'expandSingle' => true, + 'levelLinksPosition' => 'top', + 'showSynchronizationLink' => false, + 'showAllLocalizationLink' => false, + 'showPossibleLocalizationRecords' => false, + 'useSortable' => true, + ], + 'overrideChildTca' => [ + 'columns' => [ + 'colPos' => ['config' => ['default' => 999]], + ], + ], + ], + ], + + // --------------------------------------------------- Detail · Related + 'market' => [ + 'label' => 'Market', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_vitec_domain_model_market', + 'items' => [['label' => '', 'value' => 0]], + 'default' => 0, + 'maxitems' => 1, + ], + ], + 'solutions' => [ + 'label' => 'Solutions', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectMultipleSideBySide', + 'foreign_table' => 'tx_vitec_domain_model_solution', + 'MM' => 'tx_vitec_usecase_solution_mm', + 'size' => 6, + 'autoSizeMax' => 20, + 'maxitems' => 9999, + ], + ], + 'products' => [ + 'label' => 'Products', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectMultipleSideBySide', + 'foreign_table' => 'tx_vitec_domain_model_product', + 'MM' => 'tx_vitec_usecase_product_mm', + 'size' => 6, + 'autoSizeMax' => 20, + 'maxitems' => 9999, + ], + ], + 'categories' => ['config' => ['type' => 'category']], + + // --------------------------------------------------------------- SEO + 'seo_title' => [ + 'label' => 'SEO Title', + 'config' => ['type' => 'input', 'size' => 40, 'eval' => 'trim'], + ], + 'seo_description' => [ + 'label' => 'Meta Description', + 'config' => ['type' => 'text', 'cols' => 40, 'rows' => 3, 'eval' => 'trim'], + ], + 'no_index' => [ + 'label' => 'No Index', + 'config' => ['type' => 'check', 'renderType' => 'checkboxToggle', 'items' => [['value' => '', 'label' => '']]], + ], + 'no_follow' => [ + 'label' => 'No Follow', + 'config' => ['type' => 'check', 'renderType' => 'checkboxToggle', 'items' => [['value' => '', 'label' => '']]], + ], + 'canonical_link' => [ + 'label' => 'Canonical URL', + 'config' => ['type' => 'link'], + ], + 'og_title' => [ + 'label' => 'og:title', + 'config' => ['type' => 'input', 'size' => 40, 'eval' => 'trim'], + ], + 'og_description' => [ + 'label' => 'og:description', + 'config' => ['type' => 'text', 'cols' => 40, 'rows' => 3, 'eval' => 'trim'], + ], + 'og_image' => [ + 'label' => 'og:image', + 'config' => ['type' => 'file', 'maxitems' => 1, 'allowed' => 'common-image-types'], + ], + 'twitter_title' => [ + 'label' => 'twitter:title', + 'config' => ['type' => 'input', 'size' => 40, 'eval' => 'trim'], + ], + 'twitter_description' => [ + 'label' => 'twitter:description', + 'config' => ['type' => 'text', 'cols' => 40, 'rows' => 3, 'eval' => 'trim'], + ], + 'twitter_image' => [ + 'label' => 'twitter:image', + 'config' => ['type' => 'file', 'maxitems' => 1, 'allowed' => 'common-image-types'], + ], + + // -------------------------------------------------------- Appearance + 'layout_variant' => [ + 'label' => 'Detail Layout', + 'config' => [ + 'type' => 'select', 'renderType' => 'selectSingle', 'default' => 'standard', + 'items' => [ + ['label' => 'Standard', 'value' => 'standard'], + ['label' => 'Wide', 'value' => 'wide'], + ['label' => 'Centered', 'value' => 'centered'], + ['label' => 'Media-first', 'value' => 'media_first'], + ], + ], + ], + 'background_variant' => [ + 'label' => 'Background', + 'config' => [ + 'type' => 'select', 'renderType' => 'selectSingle', 'default' => 'none', + 'items' => [ + ['label' => 'None', 'value' => 'none'], + ['label' => 'Orange', 'value' => 'orange'], + ['label' => 'Blue', 'value' => 'blue'], + ['label' => 'Graphite', 'value' => 'graphite'], + ['label' => 'Midnight', 'value' => 'midnight'], + ['label' => 'Light', 'value' => 'light'], + ['label' => 'Dark', 'value' => 'dark'], + ], + ], + ], + 'accent_color' => [ + 'label' => 'Accent Color', + 'config' => ['type' => 'color'], + ], + 'hideonwebsite' => [ + 'exclude' => true, + 'label' => 'Hide on Website', + 'config' => ['type' => 'check', 'renderType' => 'checkboxToggle', 'items' => [['value' => '', 'label' => '']]], + ], + 'hideonapp' => [ + 'exclude' => true, + 'label' => 'Hide on App', + 'config' => ['type' => 'check', 'renderType' => 'checkboxToggle', 'items' => [['value' => '', 'label' => '']]], + ], + 'featured' => [ + 'label' => 'Featured', + 'config' => ['type' => 'check', 'renderType' => 'checkboxToggle', 'items' => [['value' => '', 'label' => '']]], + ], + 'show_related' => [ + 'label' => 'Show Related section', + 'config' => ['type' => 'check', 'renderType' => 'checkboxToggle', 'default' => 1, 'items' => [['value' => '', 'label' => '']]], + ], + 'hero_layout' => [ + 'label' => 'Hero Layout', + 'config' => [ + 'type' => 'select', 'renderType' => 'selectSingle', 'default' => 'fullscreen', + 'items' => [ + ['label' => 'Fullscreen', 'value' => 'fullscreen'], + ['label' => 'Medium', 'value' => 'md'], + ['label' => 'Small', 'value' => 'sm'], + ], + ], + ], + 'text_theme' => [ + 'label' => 'Text Theme', + 'config' => [ + 'type' => 'select', 'renderType' => 'selectSingle', 'default' => 'light', + 'items' => [ + ['label' => 'Light', 'value' => 'light'], + ['label' => 'Dark', 'value' => 'dark'], + ], + ], ], ], -]; \ No newline at end of file +]; diff --git a/packages/vitec/Configuration/TypoScript/Headless/vitec_containers.typoscript b/packages/vitec/Configuration/TypoScript/Headless/vitec_containers.typoscript old mode 100755 new mode 100644 index 9c9c56e..395e411 --- a/packages/vitec/Configuration/TypoScript/Headless/vitec_containers.typoscript +++ b/packages/vitec/Configuration/TypoScript/Headless/vitec_containers.typoscript @@ -2,6 +2,12 @@ # VITEC container content elements — self-contained JSON rendering # Children collected via Evomedien\Vitec\DataProcessing\ContainerChildrenProcessor # (exception-safe; returns [] on any error, never crashes the outer CE). +# +# Per-column flex settings (align/justify) live on the PARENT record +# (tx_vitec_col{1..4}_align/justify) and are attached by the processor to each +# column in `items` (items[].config.align/justify) — so they apply to ALL +# children of that column. The whole-grid gap (tx_vitec_gap) is emitted here as +# the parent-level `gap`. # ============================================================================= tt_content.vitec_cols_50_50 = JSON @@ -70,9 +76,27 @@ tt_content.vitec_cols_50_50 { header.field = header subheader = TEXT subheader.field = subheader + headerLayout = INT + headerLayout.field = header_layout + headerPosition = TEXT + headerPosition.field = header_position + headerLink = TEXT + headerLink { + htmlSpecialChars = 1 + typolink { + parameter.field = header_link + returnLast = result + } + } tx_vitec_bg_variant = TEXT tx_vitec_bg_variant.field = tx_vitec_bg_variant + # Parent-level: column gap scale (1–5) for the whole grid. + gap = TEXT + gap.field = tx_vitec_gap + + # Columns with their children + per-column flex (align/justify) in + # items[].config — assembled by ContainerChildrenProcessor. items = JSON items { dataProcessing { @@ -83,18 +107,48 @@ tt_content.vitec_cols_50_50 { } } -tt_content.vitec_cols_33_33_33 =< tt_content.vitec_cols_50_50 -tt_content.vitec_cols_25_25_25_25 =< tt_content.vitec_cols_50_50 -tt_content.vitec_cols_66_33 =< tt_content.vitec_cols_50_50 -tt_content.vitec_cols_33_66 =< tt_content.vitec_cols_50_50 +tt_content.vitec_cols_33_33_33 < tt_content.vitec_cols_50_50 +tt_content.vitec_cols_25_25_25_25 < tt_content.vitec_cols_50_50 +tt_content.vitec_cols_66_33 < tt_content.vitec_cols_50_50 +tt_content.vitec_cols_33_66 < tt_content.vitec_cols_50_50 # ----------------------------------------------------------------------------- # VITEC · Container — single-column container with a custom CSS class. # Inherits the full structure of the grid containers and adds the `cssClass` # field, read from the element's FlexForm (settings.cssClass). +# Single column -> no grid gap. # ----------------------------------------------------------------------------- -tt_content.vitec_container =< tt_content.vitec_cols_50_50 +tt_content.vitec_container < tt_content.vitec_cols_50_50 +tt_content.vitec_container.fields.gap > tt_content.vitec_container.fields.cssClass = TEXT tt_content.vitec_container.fields.cssClass.data = flexform:pi_flexform:settings.cssClass tt_content.vitec_container.fields.cssClass.stdWrap.ifEmpty.cObject = TEXT tt_content.vitec_container.fields.cssClass.stdWrap.ifEmpty.cObject.value = + +# ----------------------------------------------------------------------------- +# VITEC · Cards Carousel — container whose children (typically vitec_card +# elements) become the slides. Inherits the grid-container JSON structure +# (`items` via ContainerChildrenProcessor) and adds carousel settings read +# from the element's FlexForm. Single slide track -> no grid gap. +# ----------------------------------------------------------------------------- +tt_content.vitec_cards_carousel < tt_content.vitec_cols_50_50 +tt_content.vitec_cards_carousel.fields.gap > +tt_content.vitec_cards_carousel.fields.carousel = JSON +tt_content.vitec_cards_carousel.fields.carousel { + fields { + slidesPerView = TEXT + slidesPerView.data = flexform:pi_flexform:settings.slidesperview + showArrows = TEXT + showArrows.data = flexform:pi_flexform:settings.showarrows + showIndicators = TEXT + showIndicators.data = flexform:pi_flexform:settings.showindicators + loop = TEXT + loop.data = flexform:pi_flexform:settings.loop + autoplay = TEXT + autoplay.data = flexform:pi_flexform:settings.autoplay + autoplayInterval = TEXT + autoplayInterval.data = flexform:pi_flexform:settings.autoplayinterval + } +} +tt_content.vitec_cards_carousel.fields.cssClass = TEXT +tt_content.vitec_cards_carousel.fields.cssClass.data = flexform:pi_flexform:settings.cssClass diff --git a/packages/vitec/Configuration/TypoScript/Headless/vitec_menus.typoscript b/packages/vitec/Configuration/TypoScript/Headless/vitec_menus.typoscript old mode 100755 new mode 100644 diff --git a/packages/vitec/Configuration/TypoScript/Headless/vitec_news.typoscript b/packages/vitec/Configuration/TypoScript/Headless/vitec_news.typoscript new file mode 100644 index 0000000..943d917 --- /dev/null +++ b/packages/vitec/Configuration/TypoScript/Headless/vitec_news.typoscript @@ -0,0 +1,30 @@ +# ============================================================================= +# VITEC news integration — headless JSON output +# +# All supported EXT:news content element types use the same JSON renderer. +# The renderer returns a stable payload with: +# - mode = list | detail +# - items/news = serialised records +# - settings = the relevant FlexForm settings for the frontend +# ============================================================================= + +tt_content.news_pi1 =< lib.contentElementWithHeader +tt_content.news_pi1 { + fields { + content { + fields { + news = USER + news.userFunc = Evomedien\Vitec\UserFunc\NewsJsonRenderer->render + } + } + } +} + +tt_content.news_newsliststicky < tt_content.news_pi1 +tt_content.news_newsselectedlist < tt_content.news_pi1 +tt_content.news_newsdetail < tt_content.news_pi1 +tt_content.news_newsdatemenu < tt_content.news_pi1 +tt_content.news_categorylist < tt_content.news_pi1 +tt_content.news_newssearchform < tt_content.news_pi1 +tt_content.news_newssearchresult < tt_content.news_pi1 +tt_content.news_taglist < tt_content.news_pi1 \ No newline at end of file diff --git a/packages/vitec/Configuration/page.tsconfig b/packages/vitec/Configuration/page.tsconfig old mode 100755 new mode 100644 index 2191f64..b477a16 --- a/packages/vitec/Configuration/page.tsconfig +++ b/packages/vitec/Configuration/page.tsconfig @@ -80,6 +80,14 @@ mod { CType = vitec_datasheets } } + eventlist { + iconIdentifier = vitec-plugin-eventlist + title = VITEC Event List + description = Upcoming VITEC events (trade shows) with date, venue, booth and links + tt_content_defValues { + CType = vitec_eventlist + } + } simplecard { iconIdentifier = vitec-plugin-simplecard title = Simple Card @@ -97,6 +105,13 @@ mod { } } +tx_news.templateLayouts { + 1 = Compact List + 2 = Featured Story + 3 = Editorial Grid + 4 = Detail Spotlight +} + ############################################################ # Backend Previews für klassische Plugins (list_type) ############################################################ diff --git a/packages/vitec/ContentBlocks/Basics/ButtonStyle.yaml b/packages/vitec/ContentBlocks/Basics/ButtonStyle.yaml old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/Basics/SecondaryButtonStyle.yaml b/packages/vitec/ContentBlocks/Basics/SecondaryButtonStyle.yaml old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/card/assets/icon.svg b/packages/vitec/ContentBlocks/ContentElements/card/assets/icon.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/card/config.yaml b/packages/vitec/ContentBlocks/ContentElements/card/config.yaml old mode 100755 new mode 100644 index f70852f..f275f16 --- a/packages/vitec/ContentBlocks/ContentElements/card/config.yaml +++ b/packages/vitec/ContentBlocks/ContentElements/card/config.yaml @@ -13,12 +13,27 @@ fields: type: Text max: 50 - - identifier: header - useExistingField: true - required: true + - identifier: header_section + type: Palette + label: Header + fields: + - identifier: header + useExistingField: true + required: true + - type: Linebreak + - identifier: header_layout + useExistingField: true + - identifier: header_position + useExistingField: true + - identifier: date + useExistingField: true + - type: Linebreak + - identifier: header_link + useExistingField: true + - type: Linebreak + - identifier: subheader + useExistingField: true - - identifier: subheader - useExistingField: true - identifier: bodytext useExistingField: true diff --git a/packages/vitec/ContentBlocks/ContentElements/card/language/labels.xlf b/packages/vitec/ContentBlocks/ContentElements/card/language/labels.xlf old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/card/templates/backend-preview.html b/packages/vitec/ContentBlocks/ContentElements/card/templates/backend-preview.html old mode 100755 new mode 100644 index 576085a..7160094 --- a/packages/vitec/ContentBlocks/ContentElements/card/templates/backend-preview.html +++ b/packages/vitec/ContentBlocks/ContentElements/card/templates/backend-preview.html @@ -50,7 +50,7 @@ {data.header} - ⚠ Headline fehlt + ⚠ Headline missing diff --git a/packages/vitec/ContentBlocks/ContentElements/card/templates/frontend.html b/packages/vitec/ContentBlocks/ContentElements/card/templates/frontend.html old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/columns/assets/icon.svg b/packages/vitec/ContentBlocks/ContentElements/columns/assets/icon.svg new file mode 100644 index 0000000..46aa6f0 --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/columns/assets/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/vitec/ContentBlocks/ContentElements/columns/config.yaml b/packages/vitec/ContentBlocks/ContentElements/columns/config.yaml new file mode 100644 index 0000000..dfc6682 --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/columns/config.yaml @@ -0,0 +1,91 @@ +name: vitec/columns +group: vitec_custom_components +prefixFields: true +prefixType: vendor + +fields: + - identifier: header_section + type: Palette + label: Header + fields: + - identifier: header + useExistingField: true + required: true + - type: Linebreak + - identifier: header_layout + useExistingField: true + - identifier: header_position + useExistingField: true + - identifier: date + useExistingField: true + - type: Linebreak + - identifier: header_link + useExistingField: true + - type: Linebreak + - identifier: subheader + useExistingField: true + - identifier: layout + type: Select + renderType: selectSingle + default: cols_50_50 + items: + - label: '50 / 50' + value: cols_50_50 + - label: '66 / 33' + value: cols_66_33 + - label: '33 / 66' + value: cols_33_66 + + - identifier: items + type: Collection + label: Items + labelField: headline + fields: + - identifier: column + type: Select + renderType: selectSingle + default: left + items: + - label: Left column + value: left + - label: Right column + value: right + - identifier: item_type + type: Select + renderType: selectSingle + default: text + items: + - label: Text + value: text + - label: Image + value: image + - label: Video + value: video + - label: CTA / Button + value: cta + - identifier: headline + type: Text + max: 255 + - identifier: text + type: Textarea + enableRichtext: true + - identifier: image + type: File + minitems: 0 + maxitems: 1 + allowed: common-image-types + - identifier: video + type: File + minitems: 0 + maxitems: 1 + allowed: mp4,webm,ogv,mov,m4v + - identifier: link + type: Link + allowedTypes: + - page + - url + - file + - email + - identifier: link_label + type: Text + max: 60 diff --git a/packages/vitec/ContentBlocks/ContentElements/columns/language/labels.xlf b/packages/vitec/ContentBlocks/ContentElements/columns/language/labels.xlf new file mode 100644 index 0000000..1b4ca10 --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/columns/language/labels.xlf @@ -0,0 +1,45 @@ + + + + + + VITEC · Columns + + + Two-column layout (50/50, 66/33, 33/66). Add items and assign each to the left or right column. + + + + Layout + + + + Items + + + Column + + + Type + + + Headline + + + Text + + + Image + + + Video + + + Link + + + Link Label + + + + diff --git a/packages/vitec/ContentBlocks/ContentElements/columns/templates/backend-preview.html b/packages/vitec/ContentBlocks/ContentElements/columns/templates/backend-preview.html new file mode 100644 index 0000000..eae1d0a --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/columns/templates/backend-preview.html @@ -0,0 +1,19 @@ + + + + + + +
+
+
+
VITEC · Columns
+

Two-column layout — {data.layout}

+
+
+ {data.layout} +
+
+ +
+ diff --git a/packages/vitec/ContentBlocks/ContentElements/columns/templates/frontend.html b/packages/vitec/ContentBlocks/ContentElements/columns/templates/frontend.html new file mode 100644 index 0000000..4b9267a --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/columns/templates/frontend.html @@ -0,0 +1,3 @@ + + + diff --git a/packages/vitec/ContentBlocks/ContentElements/cta-banner/config.yaml b/packages/vitec/ContentBlocks/ContentElements/cta-banner/config.yaml old mode 100755 new mode 100644 index 5129152..79e8354 --- a/packages/vitec/ContentBlocks/ContentElements/cta-banner/config.yaml +++ b/packages/vitec/ContentBlocks/ContentElements/cta-banner/config.yaml @@ -4,9 +4,26 @@ prefixFields: true prefixType: vendor fields: - - identifier: header - useExistingField: true - required: true + - identifier: header_section + type: Palette + label: Header + fields: + - identifier: header + useExistingField: true + required: true + - type: Linebreak + - identifier: header_layout + useExistingField: true + - identifier: header_position + useExistingField: true + - identifier: date + useExistingField: true + - type: Linebreak + - identifier: header_link + useExistingField: true + - type: Linebreak + - identifier: subheader + useExistingField: true - identifier: bodytext useExistingField: true diff --git a/packages/vitec/ContentBlocks/ContentElements/cta-banner/language/labels.xlf b/packages/vitec/ContentBlocks/ContentElements/cta-banner/language/labels.xlf index e49f186..f7823c7 100644 --- a/packages/vitec/ContentBlocks/ContentElements/cta-banner/language/labels.xlf +++ b/packages/vitec/ContentBlocks/ContentElements/cta-banner/language/labels.xlf @@ -6,7 +6,7 @@ VITEC · CTA Banner - Call-to-Action Banner mit optionalem zweiten Button und Background-Varianten + Call-to-action banner with optional secondary button and background variants @@ -35,7 +35,7 @@ Background Image (optional) - Optionales Hintergrundbild — überlagert die Background-Variant-Farbe + Optional background image — overlays the background variant colour diff --git a/packages/vitec/ContentBlocks/ContentElements/cta-banner/templates/backend-preview.html b/packages/vitec/ContentBlocks/ContentElements/cta-banner/templates/backend-preview.html index d5b2c74..228bc8b 100644 --- a/packages/vitec/ContentBlocks/ContentElements/cta-banner/templates/backend-preview.html +++ b/packages/vitec/ContentBlocks/ContentElements/cta-banner/templates/backend-preview.html @@ -6,7 +6,7 @@
- Thumbnail (Background Image oder Farb-Placeholder) + Thumbnail (background image or colour placeholder) {data.header} - ⚠ Headline fehlt + ⚠ Headline missing @@ -75,7 +75,7 @@ - Layout Variant Badge mit Icon + Layout variant badge with icon ◎ Centered @@ -85,9 +85,9 @@ - Warnung wenn Primary-CTA-Link fehlt + Warning when primary CTA link is missing - ⚠ Kein Primary-Link + ⚠ Primary link missing
diff --git a/packages/vitec/ContentBlocks/ContentElements/faq/assets/icon.svg b/packages/vitec/ContentBlocks/ContentElements/faq/assets/icon.svg new file mode 100644 index 0000000..fd78199 --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/faq/assets/icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/vitec/ContentBlocks/ContentElements/faq/config.yaml b/packages/vitec/ContentBlocks/ContentElements/faq/config.yaml new file mode 100644 index 0000000..663d36d --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/faq/config.yaml @@ -0,0 +1,56 @@ +name: vitec/faq +group: vitec_custom_components +prefixFields: true +prefixType: vendor + +fields: + - identifier: header_section + type: Palette + label: Header + fields: + - identifier: header + useExistingField: true + required: true + - type: Linebreak + - identifier: header_layout + useExistingField: true + - identifier: header_position + useExistingField: true + - identifier: date + useExistingField: true + - type: Linebreak + - identifier: header_link + useExistingField: true + - type: Linebreak + - identifier: subheader + useExistingField: true + + + + + + - identifier: faq_items + type: Collection + labelField: question + minitems: 1 + fields: + - identifier: question + type: Text + required: true + max: 255 + + - identifier: answer + type: Textarea + enableRichtext: true + + - identifier: first_item_open + type: Checkbox + default: 1 + + - identifier: allow_multiple_open + type: Checkbox + default: 0 + + - identifier: debug + type: Checkbox + default: 0 diff --git a/packages/vitec/ContentBlocks/ContentElements/faq/language/labels.xlf b/packages/vitec/ContentBlocks/ContentElements/faq/language/labels.xlf new file mode 100644 index 0000000..5034ab9 --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/faq/language/labels.xlf @@ -0,0 +1,33 @@ + + + + + + VITEC · FAQ + + + Accordion with repeatable question/answer items. First item can start expanded. + + + + FAQ Entries + + + Question + + + Answer + + + + Open first item by default + + + Allow multiple items open at once + + + Allow Debug Output + + + + diff --git a/packages/vitec/ContentBlocks/ContentElements/faq/templates/backend-preview.html b/packages/vitec/ContentBlocks/ContentElements/faq/templates/backend-preview.html new file mode 100644 index 0000000..e7f7dce --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/faq/templates/backend-preview.html @@ -0,0 +1,66 @@ + + + + + + +
+ +
?
+ +
+
VITEC · FAQ
+ +

+ + {data.header} + + ⚠ Headline missing + + +

+ + +
{data.subheader}
+
+ + + +
+ + ▸ {item.question}
+
+
+
+ +
+ ⚠ No FAQ entries +
+
+
+
+ +
+ + + ❓ entries + + + + ▽ First item open + + + + ≡ Multiple open allowed + + + + ⚙ Debug ON + + +
+ +
+ +
+ diff --git a/packages/vitec/ContentBlocks/ContentElements/faq/templates/frontend.html b/packages/vitec/ContentBlocks/ContentElements/faq/templates/frontend.html new file mode 100644 index 0000000..da9c5f0 --- /dev/null +++ b/packages/vitec/ContentBlocks/ContentElements/faq/templates/frontend.html @@ -0,0 +1,3 @@ + + + diff --git a/packages/vitec/ContentBlocks/ContentElements/hero-section/config.yaml b/packages/vitec/ContentBlocks/ContentElements/hero-section/config.yaml old mode 100755 new mode 100644 index 0a3d732..27c3dca --- a/packages/vitec/ContentBlocks/ContentElements/hero-section/config.yaml +++ b/packages/vitec/ContentBlocks/ContentElements/hero-section/config.yaml @@ -8,21 +8,30 @@ fields: type: Text max: 50 - - identifier: header - useExistingField: true - required: true + - identifier: header_section + type: Palette + label: Header + fields: + - identifier: header + useExistingField: true + required: true + - type: Linebreak + - identifier: header_layout + useExistingField: true + - identifier: header_position + useExistingField: true + - identifier: date + useExistingField: true + - type: Linebreak + - identifier: header_link + useExistingField: true + - type: Linebreak + - identifier: subheader + useExistingField: true - - identifier: header_layout - useExistingField: true - - identifier: header_position - useExistingField: true - - identifier: header_link - useExistingField: true - - identifier: subheader - useExistingField: true - identifier: bodytext useExistingField: true diff --git a/packages/vitec/ContentBlocks/ContentElements/hero-section/language/labels.xlf b/packages/vitec/ContentBlocks/ContentElements/hero-section/language/labels.xlf old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/hero-section/templates/backend-preview.html b/packages/vitec/ContentBlocks/ContentElements/hero-section/templates/backend-preview.html index 1c1c794..ce1e316 100644 --- a/packages/vitec/ContentBlocks/ContentElements/hero-section/templates/backend-preview.html +++ b/packages/vitec/ContentBlocks/ContentElements/hero-section/templates/backend-preview.html @@ -31,7 +31,7 @@ {data.header} - ⚠ Headline fehlt + ⚠ Headline missing @@ -53,7 +53,7 @@ - Settings Sidebar (ohne Partial) + Settings sidebar (without partial)
@@ -65,7 +65,7 @@ - ⚠ Kein Bild + ⚠ No image
diff --git a/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/assets/icon.svg b/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/assets/icon.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/config.yaml b/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/config.yaml old mode 100755 new mode 100644 index dc82845..8614a56 --- a/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/config.yaml +++ b/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/config.yaml @@ -4,21 +4,30 @@ prefixFields: true prefixType: vendor fields: - - identifier: header - useExistingField: true - required: true + - identifier: header_section + type: Palette + label: Header + fields: + - identifier: header + useExistingField: true + required: true + - type: Linebreak + - identifier: header_layout + useExistingField: true + - identifier: header_position + useExistingField: true + - identifier: date + useExistingField: true + - type: Linebreak + - identifier: header_link + useExistingField: true + - type: Linebreak + - identifier: subheader + useExistingField: true - - identifier: header_layout - useExistingField: true - - identifier: header_position - useExistingField: true - - identifier: header_link - useExistingField: true - - identifier: subheader - useExistingField: true - identifier: bodytext useExistingField: true diff --git a/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/language/labels.xlf b/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/language/labels.xlf old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/backend-preview.html b/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/backend-preview.html old mode 100755 new mode 100644 index b8e5138..7c0cdcb --- a/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/backend-preview.html +++ b/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/backend-preview.html @@ -12,7 +12,7 @@ {data.header} - ⚠ Headline fehlt + ⚠ Headline missing @@ -61,7 +61,7 @@ - ⚠ Button-Text ohne Link + ⚠ Button text without link diff --git a/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/frontend.html b/packages/vitec/ContentBlocks/ContentElements/intro-paragraph/templates/frontend.html old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/video/assets/icon.svg b/packages/vitec/ContentBlocks/ContentElements/video/assets/icon.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/video/config.yaml b/packages/vitec/ContentBlocks/ContentElements/video/config.yaml old mode 100755 new mode 100644 index 8a033b8..4f6e6dd --- a/packages/vitec/ContentBlocks/ContentElements/video/config.yaml +++ b/packages/vitec/ContentBlocks/ContentElements/video/config.yaml @@ -4,21 +4,30 @@ prefixFields: true prefixType: vendor fields: - - identifier: header - useExistingField: true - required: true + - identifier: header_section + type: Palette + label: Header + fields: + - identifier: header + useExistingField: true + required: true + - type: Linebreak + - identifier: header_layout + useExistingField: true + - identifier: header_position + useExistingField: true + - identifier: date + useExistingField: true + - type: Linebreak + - identifier: header_link + useExistingField: true + - type: Linebreak + - identifier: subheader + useExistingField: true - - identifier: header_layout - useExistingField: true - - identifier: header_position - useExistingField: true - - identifier: header_link - useExistingField: true - - identifier: subheader - useExistingField: true - identifier: youtube_code type: Text diff --git a/packages/vitec/ContentBlocks/ContentElements/video/language/labels.xlf b/packages/vitec/ContentBlocks/ContentElements/video/language/labels.xlf old mode 100755 new mode 100644 diff --git a/packages/vitec/ContentBlocks/ContentElements/video/templates/backend-preview.html b/packages/vitec/ContentBlocks/ContentElements/video/templates/backend-preview.html old mode 100755 new mode 100644 index 04cd7da..5ab3bad --- a/packages/vitec/ContentBlocks/ContentElements/video/templates/backend-preview.html +++ b/packages/vitec/ContentBlocks/ContentElements/video/templates/backend-preview.html @@ -27,7 +27,7 @@ {data.header} - ⚠ Headline fehlt + ⚠ Headline missing @@ -59,7 +59,7 @@ - ⚠ Kein Video-Source + ⚠ No video source ⏸ Controls hidden diff --git a/packages/vitec/ContentBlocks/ContentElements/video/templates/frontend.html b/packages/vitec/ContentBlocks/ContentElements/video/templates/frontend.html old mode 100755 new mode 100644 diff --git a/packages/vitec/Documentation/Headless-JSON-Architecture.md b/packages/vitec/Documentation/Headless-JSON-Architecture.md new file mode 100644 index 0000000..b885358 --- /dev/null +++ b/packages/vitec/Documentation/Headless-JSON-Architecture.md @@ -0,0 +1,619 @@ +# VITEC Headless JSON Architecture — Software Architecture and Interface Specification + +| | | +|---|---| +| **Document identifier** | EVO‑VITEC‑HL‑001 | +| **Version** | 1.0 | +| **Status** | Released | +| **Date** | 2026‑07‑09 | +| **Applies to** | `evomedien/vitec` on TYPO3 v14.3 (headless) | +| **Owner** | evomedien — VITEC relaunch | + +This document is drafted in the style of, and adopts the terminology conventions of, +ISO/IEC/IEEE 42010 (architecture description), ISO/IEC/IEEE 26514 (information for +users) and ISO/IEC 25010 (product quality). The key words **shall**, **should** and +**may** are to be interpreted as normative requirements, recommendations and +permissions respectively. + +--- + +## Foreword + +The VITEC web platform is a *headless* TYPO3 installation: the CMS does not render +HTML pages, it emits JSON that is consumed by a separate React front end. This +specification describes the architecture, the public JSON interface, and the +engineering conventions that keep the JSON output **consistent** across all content +types and **maintainable** across TYPO3 and extension upgrades. + +It supersedes, as the authoritative reference, the informal tutorial +`Documentation/HeadlessIntegration.md`, which is retained as an informative how‑to. + +## Introduction + +The platform combines the generic headless page renderer (`friendsoftypo3/headless`) +with three sources of content JSON: + +1. **Custom plugins** (product, use case/success story, market, solution, downloads, + datasheets, events, news) rendered by dedicated *UserFunc* classes; +2. **Layout containers** (b13/container based column grids and a card carousel) + rendered by a *DataProcessor*; +3. **Content Blocks** (`friendsoftypo3/content-blocks`) serialised automatically by + `nb-headless-content-blocks`. + +All three are unified under a single **content‑element envelope** so that the front +end can consume every element with one predictable shape. + +--- + +## 1 Scope + +### 1.1 In scope +This document specifies: +- the runtime environment and the software stack (Clause 5); +- the JSON rendering pipeline and its layers (Clause 6); +- the public JSON interface — envelope, payloads, structured data (Clause 7); +- the catalogue of content types and their JSON keys (Clause 8); +- the mandatory conventions for implementing and extending renderers (Clause 9); +- maintainability and upgrade‑safety requirements (Clause 10); +- conformance criteria (Clause 11). + +### 1.2 Out of scope +Front‑end (React) implementation, hosting/deployment, the editorial (backend) TCA +form design except where it determines JSON output, and non‑headless (Fluid) rendering +paths. + +## 2 Normative references + +The following documents are referred to in the text. For dated references, only the +edition cited applies. + +- ISO/IEC/IEEE 42010, *Software, systems and enterprise — Architecture description* +- ISO/IEC 25010, *Systems and software Quality Requirements and Evaluation (SQuaRE) — Product quality model* +- ISO/IEC/IEEE 26514, *Systems and software engineering — Design and development of information for users* +- ISO 8601‑1, *Date and time — Representations for information interchange* +- IETF RFC 8259, *The JavaScript Object Notation (JSON) Data Interchange Format* +- IETF RFC 2119, *Key words for use in RFCs to indicate requirement levels* +- schema.org vocabulary (informative), *https://schema.org* + +## 3 Terms and definitions + +**3.1 headless** — operating mode in which TYPO3 returns JSON instead of HTML; +enabled per site by `headless: 1` and the headless Site Sets. + +**3.2 content element** — a `tt_content` record; the atomic unit of page content. + +**3.3 CType** — the content‑element type identifier stored in `tt_content.CType` +(e.g. `vitec_productlist`, `news_pi1`, `vitec_cols_50_50`). + +**3.4 envelope** — the invariant outer JSON structure shared by every content element +(Clause 7.2). + +**3.5 payload** — the domain‑specific JSON produced for one content element and placed +inside the envelope (Clause 7.3). + +**3.6 renderer** — a *UserFunc* class under `Classes/UserFunc/` that produces a payload. + +**3.7 serializer** — a service class under `Classes/Service/` that converts a domain +record into JSON, used by one or more renderers. + +**3.8 resolver / processor** — `ContentElementResolver` and `ContainerChildrenProcessor`; +they normalise a raw `tt_content` row into an envelope and resolve nested elements. + +**3.9 container** — a b13/container CType that owns child content elements via +`tx_container_parent` and emits them as `items`. + +**3.10 Content Block** — a declaratively defined content element +(`friendsoftypo3/content-blocks`), serialised by `nb-headless-content-blocks`. + +## 4 Symbols and abbreviated terms + +| Term | Meaning | +|---|---| +| FAL | File Abstraction Layer (TYPO3 file handling) | +| IRRE | Inline Relational Record Editing (`type: inline`) | +| MM | Many‑to‑many junction table | +| CB | Content Block | +| TS | TypoScript | +| CE | Content element | + +--- + +## 5 Runtime environment (architecture context) + +### 5.1 Software stack +| Component | Version | Role | +|---|---|---| +| TYPO3 CMS | ^14.3 | Core CMS | +| PHP | 8.x (per TYPO3 14) | Runtime | +| `friendsoftypo3/headless` | ^5.0@rc | Page‑to‑JSON renderer, `lib.contentElement` | +| `friendsoftypo3/content-blocks` | ^2.4 | Declarative content elements | +| `netzbewegung/nb-headless-content-blocks` | ^0.0.23 | Content Blocks → JSON | +| `b13/container` | ^3.1 | Nested column containers | +| `georgringer/news` | ^14.0 | News records and plugins | +| `evomedien/vitec` | ^1.0 | This project’s custom extension | + +> **NOTE** `friendsoftypo3/headless` is pinned to a **release candidate** (`^5.0@rc`). +> This is an upgrade‑sensitivity point; see 10.4. + +### 5.2 Site configuration +The headless mode is activated in `config/sites/vitec/config.yaml`: + +```yaml +base: / +headless: 1 +frontendBase: '' +dependencies: + - friendsoftypo3/headless + - friendsoftypo3/headless-mixed + - nb-headless-content-blocks/headless-content-blocks + - georgringer/news +``` + +The Site **Sets** listed under `dependencies` load, in order, the headless TypoScript +base, the mixed‑mode overrides, the Content Blocks JSON integration and the News +integration. The VITEC Set (`EXT:vitec/Configuration/Sets/Vitecset`) layers the custom +definitions on top. The headless page response carries +`Content-Type: application/json; charset=utf-8`. Slug routing is configured with route +enhancers for products (`tx_vitec_domain_model_product.slug`) and news detail +(`path_segment`). + +### 5.3 Architectural principles (rationale) +- **P1 — One envelope.** Every content element, regardless of source, is exposed with + the same outer shape so the front end has a single rendering contract. +- **P2 — Payload isolation.** Domain JSON is produced in PHP, fully decoupled from + TypoScript, so business logic is testable and versionable. +- **P3 — Dual entry.** Each renderer works both as a top‑level plugin and as a nested + child of a container (Clause 9.3). +- **P4 — Fail soft.** A failing element yields empty output, never a broken page + (Clause 9.5). + +--- + +## 6 Rendering pipeline + +The JSON for one page is assembled top‑down through the following layers. + +``` +HTTP request (Accept: application/json, headless:1) + │ + ▼ +[L1] Page renderer friendsoftypo3/headless + │ builds { meta, content[], … , jsonLd } + ▼ +[L2] Content‑element envelope lib.contentElement / lib.contentElementWithHeader + │ per CType: id, type, colPos, appearance, content{header,…} + ▼ +[L3] Payload injection USER cObj → Classes/UserFunc/*JsonRenderer::render + │ places domain JSON under content. + ▼ +[L4] Containers tt_content.vitec_cols_* = JSON + │ ContainerChildrenProcessor → items[].contentElements[] + ▼ +[L5] Normalisation & nesting ContentElementResolver / PLUGIN_RENDERERS + ▼ +[L6] Structured data (JSON‑LD) PageJsonLdRenderer + StructuredDataService +``` + +### 6.1 L1 — Page renderer +`friendsoftypo3/headless` converts the requested page into a JSON document containing +page metadata, the ordered array of content elements, navigation and the JSON‑LD +graph. VITEC does not replace this layer; it contributes elements to `content[]` +(L2–L5) and the `jsonLd` field (L6). + +### 6.2 L2 — Content‑element envelope +Each CType is bound to a headless library object: + +```typoscript +tt_content. < lib.contentElementWithHeader +``` + +`lib.contentElement` provides `id`, `type`, `colPos`, `categories`, `appearance`. +`lib.contentElementWithHeader` additionally provides, under `content`, the standard +header fields: `header`, `subheader`, `headerLayout`, `headerPosition`, `headerLink` +(link resolved via typolink). **All VITEC plugins and all News CTypes inherit +`lib.contentElementWithHeader`**, giving a uniform header section in both backend and +JSON (see the companion header convention). + +### 6.3 L3 — Payload injection +The domain payload is added as a `USER` content object under `content.fields.`: + +```typoscript +tt_content.vitec_productlist < lib.contentElementWithHeader +tt_content.vitec_productlist { + fields { + content { + fields { + products = USER + products.userFunc = Evomedien\Vitec\UserFunc\ProductListJsonRenderer->render + } + } + } +} +``` + +`render()` returns a JSON string that the headless JSON cObject embeds verbatim at +`content.products`. The key is **plural for list plugins** and **singular for detail +plugins** (Clause 9.6). + +### 6.4 L4 — Containers +Column containers are defined as a self‑contained JSON object, not via +`lib.contentElement`: + +```typoscript +tt_content.vitec_cols_50_50 = JSON +tt_content.vitec_cols_50_50.fields { + id … type … appearance … header … subheader … + gap = TEXT # tx_vitec_gap (whole‑grid gap) + items = JSON + items.dataProcessing.10 = Evomedien\Vitec\DataProcessing\ContainerChildrenProcessor +} +tt_content.vitec_cols_33_66 < tt_content.vitec_cols_50_50 +tt_content.vitec_container < tt_content.vitec_cols_50_50 # single column, no gap +tt_content.vitec_cards_carousel < tt_content.vitec_cols_50_50 # + carousel settings +``` + +> **RULE (normative)** Container CTypes **shall** be derived with the **copy** +> operator `<`, never the reference operator `=<`. A `tt_content → tt_content` +> reference is not recognised as an independent renderer by the headless content +> mapper and silently falls back to raw output (see 10.5, and Annex B‑1). + +### 6.5 L5 — Normalisation and nested plugins +`ContainerChildrenProcessor` queries children by `tx_container_parent`, groups them by +`colPos` and emits, per column, a flex configuration plus the resolved children. Each +child is normalised by the same envelope logic as `ContentElementResolver`. When a +child is itself a VITEC plugin, it is resolved through the shared `PLUGIN_RENDERERS` +map (Clause 7.4). + +### 6.6 L6 — Structured data (JSON‑LD) +`PageJsonLdRenderer` (bound at `page…fields.jsonLd`) assembles a schema.org `@graph` +via `StructuredDataService`, encoded with `JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE`. +Node types and their triggers: + +| Node | Emitted when | +|---|---| +| `Organization` | every page (from site settings `seo.organization.*`) | +| `WebSite` | only on the site root page | +| `BreadcrumbList` | from the rootline (spacer/folder/recycler doktypes skipped) | +| `NewsArticle` | on news‑detail page layouts (`pages.layout ∈ {13,14,15}`) | +| `FAQPage` | when the page contains `vitec_faq` elements → `vitec_faq_items` collection | +| `ExhibitionEvent` | from `vitec_eventlist` elements → `tx_vitec_domain_model_event` (windowed by the FlexForm `daysinadvance`) | +| `Product`, `VideoObject` | via `ProductShowJsonRenderer` for product detail pages | + +FAQ and event nodes are collected from the respective tables; event image URLs are +currently built with a hard‑coded `/fileadmin` prefix (see 10.3 / Annex B‑5). + +--- + +## 7 JSON interface specification + +### 7.1 Encoding +Output **shall** be RFC 8259 JSON, UTF‑8. Timestamps **shall** be Unix epoch seconds +(integer); where ISO 8601 strings are required by schema.org they are produced inside +the JSON‑LD layer. + +### 7.2 Content‑element envelope +Every element in `content[]` conforms to: + +```jsonc +{ + "id": 123, // tt_content.uid + "type": "vitec_productlist", // tt_content.CType + "colPos": 0, + "appearance": { + "layout": "0", + "frameClass": "default", + "spaceBefore": "", + "spaceAfter": "" + }, + "content": { // present for lib.contentElement(WithHeader) CTypes + "header": "…", "subheader": "…", + "headerLayout": 2, "headerPosition": "", "headerLink": "https://…", + "": { /* payload, Clause 7.3 */ } + } +} +``` + +Elements produced by the resolver/processor (container children, inline story CEs) use +a lean variant of the envelope: + +```jsonc +{ "id": 456, "type": "text", "colPos": 211, "sorting": 1, + "appearance": { … }, "data": { /* non‑system fields */ } } +``` + +### 7.3 Payload keys +| Kind | Key | Cardinality | +|---|---|---| +| List plugin | plural noun (`products`, `usecases`, `news → items`) | array | +| Detail plugin | singular noun (`product`, `usecase`, `market`, `solution`) | object | +| Container | `items` | array of `{config, contentElements}` | + +### 7.4 Container payload +```jsonc +{ + "type": "vitec_cols_33_66", + "header": "…", "headerLayout": 2, "headerLink": "…", + "gap": "3", + "items": [ + { "config": { "colPos": 251, "align": "stretch", "justify": "flex-start" }, + "contentElements": [ /* normalised children, recursively */ ] }, + { "config": { "colPos": 252, "align": "center", "justify": "space-between" }, + "contentElements": [ … ] } + ] +} +``` + +- `gap` is a **parent‑level** property (whole‑grid gap). +- `align`/`justify` are **per‑column** and are read from the parent record + (`tx_vitec_col{N}_align/justify`); they therefore apply to **all** children of that + column. These container‑only fields **shall not** appear in a child’s `data` + (enforced by `CONTAINER_FIELDS` filtering). + +### 7.5 Success Story (use case) detail payload +Produced by `UsecaseSerializer::serializeDetail()` — the reference implementation of +the centralised pattern (Clause 9.2): + +```jsonc +{ + "uid": 1, "title": "…", "slug": "…", "subtitle": "…", "teaser": "…", + "cardImage": { "url": "…", "srcset": [ … ] }, "customerLogo": { … }, + "hero": { "bgImage": …, "smallImage": …, "video": …, + "overlayColor": "#000", "overlayOpacity": 0.4, + "layout": "fullscreen", "textTheme": "light" }, + "contentElements": [ /* inline CEs; the vitec_columns block is resolved specially */ ], + "related": { "show": true, "market": {…}, "solutions": [ … ], "products": [ … ], + "categories": [ … ] }, + "seo": { "title": "…", "description": "…", "canonical": "…", + "robots": { "noIndex": false, "noFollow": false }, + "openGraph": { "title": …, "description": …, "image": … }, + "twitter": { "title": …, "description": …, "image": … } }, + "appearance": { "layoutVariant": "standard", "backgroundVariant": "none", + "accentColor": "", "featured": false, … } +} +``` + +SEO fields use fallback resolution (`seo_* → title/teaser`; `og_* → seo_* → title`; +`twitter_* → og_*`; images `og_image → card_image → hero_bgimage`) so the front end +always receives complete metadata. + +### 7.6 News payload +Produced by `NewsJsonRenderer` under `content.news`: + +```jsonc +{ "mode": "list", // "list" | "detail" | "error" + "items": [ { "uid": 1, "title": "…", "alternativeTitle": "…", + "pathSegment": "…", "detailUrl": "/news/…", + "canonicalUrl": "https://…", "teaser": "…", "bodytext": "…", + "datetime": 1625097600, "categories": [ … ], "media": [ … ] } ], + "settings": { "type": "news_pi1", "templateLayout": "1", + "templateLayoutLabel": "Compact List", "detailPid": 45, … } } +``` + +Ten News CTypes (`news_pi1`, `news_newsdetail`, `news_newsliststicky`, …) share one +renderer; `news_newsdetail` yields `mode: "detail"` with a single `news` object. + +### 7.7 Content Blocks +Content Blocks (`card`, `cta-banner`, `hero-section`, `intro-paragraph`, `video`, +`faq`, `columns`) are serialised automatically by `nb-headless-content-blocks`: its +`ContentBlocksJsonDataProcessor` converts the resolved record via `RecordToArray`, +dropping system fields and recursing into files (→ URL + metadata), collections +(e.g. `faq_items` → array of child records) and typolinks. The output uses the lean +envelope (`{id, type, colPos, sorting, appearance, data}`). An optional per‑block +`headless.php` hook may transform the array (none are currently defined). Fields carry +the `vitec_` vendor prefix in storage. The **`vitec_columns`** block is +the single exception: because it is authored **inline inside a Success Story record**, +its collection items are resolved explicitly by `UsecaseSerializer::resolveColumnsElement()` +into `{ header…, layout, columns: { left: [], right: [] } }`, with the collection +storage table discovered from TCA (`foreign_table`) rather than hard‑coded. + +--- + +## 8 Content‑type catalogue + +| CType | TS pattern | Renderer / Processor | Payload key | Kind | +|---|---|---|---|---| +| `vitec_productlist` | `< lib.contentElementWithHeader` | ProductListJsonRenderer | `products` | list | +| `vitec_productshow` | `< lib.…WithHeader` | ProductShowJsonRenderer | `product` | detail | +| `vitec_usecaselist` | `< lib.…WithHeader` | UsecaseListJsonRenderer → **UsecaseSerializer** | `usecases` | list | +| `vitec_usecaseshow` | `< lib.…WithHeader` | UsecaseShowJsonRenderer → **UsecaseSerializer** | `usecase` | detail | +| `vitec_marketshow` | `< lib.…WithHeader` | MarketShowJsonRenderer | `market` | detail | +| `vitec_solutionshow` | `< lib.…WithHeader` | SolutionShowJsonRenderer | `solution` | detail | +| `vitec_downloadcard` | `< lib.…WithHeader` | DownloadcardJsonRenderer | `downloadcard` | detail | +| `vitec_downloadcardcollection` | `< lib.…WithHeader` | DownloadcardcollectionJsonRenderer | `downloadcardcollection` | list | +| `vitec_datasheets` | `< lib.…WithHeader` | DatasheetsJsonRenderer | `datasheets` | list | +| `vitec_eventlist` | `=< lib.…WithHeader` ⚠ | EventlistJsonRenderer | `eventlist` | list | +| `news_pi1` (+9 variants) | `=< lib.…WithHeader`; variants `<` | NewsJsonRenderer | `news` | list/detail | +| `vitec_cols_50_50` | `= JSON` | ContainerChildrenProcessor | `items` | container | +| `vitec_cols_33_66 / 66_33 / 33_33_33 / 25_25_25_25` | `< vitec_cols_50_50` | ContainerChildrenProcessor | `items` | container | +| `vitec_container` | `< vitec_cols_50_50` | ContainerChildrenProcessor | `items` | container (1 col) | +| `vitec_cards_carousel` | `< vitec_cols_50_50` | ContainerChildrenProcessor | `items` + `carousel` | container | +| Content Blocks (`vitec_card`, …) | Content Blocks + nb‑headless | — | (auto) | element | +| `vitec_columns` (CB, inline) | Content Blocks | UsecaseSerializer (special) | `columns` | element | + +⚠ = uses the reference operator `=<`; see Annex B‑1. + +--- + +## 9 Conventions (normative) + +These rules define the **single, uniform way** to implement and extend headless +renderers. New code **shall** comply; existing code **should** be aligned when touched. + +### 9.1 Renderer class shape +A payload renderer **shall**: +1. reside in `Classes/UserFunc/` and be named `JsonRenderer`; +2. expose `#[AsAllowedCallable] public function render(string $content, array $conf): string`; +3. expose `public function renderForRecord(array $row): string` for reuse by + containers/resolvers (Clause 9.3); +4. return a JSON **string** (never an array/object). + +### 9.2 Serialisation ownership +Domain‑to‑JSON conversion **should** live in a `Classes/Service/*Serializer` class, and +the renderer **should** be a thin wrapper around it. `UsecaseSerializer` is the +reference implementation. New list/detail pairs **shall** share one serializer. + +### 9.3 Dual‑entry pattern +`render()` **shall** handle top‑level invocation: use `$this->cObj->data` when it is the +plugin’s own row, otherwise perform page discovery (Clause 9.4). `renderForRecord()` +**shall** accept an explicit `tt_content` row and be free of page/context assumptions, +so it can be called by `ContainerChildrenProcessor` and `ContentElementResolver`. + +### 9.4 Page‑id discovery +Renderers **shall** resolve the current page id in this order: +```php +$id = $GLOBALS['TYPO3_REQUEST']?->getAttribute('frontend.page.information')?->getId() ?? 0; +if ($id <= 0) { $id = (int)($GLOBALS['TSFE']->id ?? 0); } // fallback +``` +Reliance on `$GLOBALS['TSFE']->id` alone is **prohibited** (it is frequently `null` in +the JSON cObject context). + +### 9.5 Fail‑soft error handling +The body of `renderForRecord()` **shall** be wrapped in +`try { … } catch (\Throwable $e) { return ''; }`. Diagnostic output **may** be emitted +only when a FlexForm `debug` flag is set. A failing element **shall not** propagate an +exception to the page. + +### 9.6 Naming +- List payload keys **shall** be plural; detail keys **shall** be singular. +- JSON property names **shall** be `camelCase` for computed/composed fields; raw + passthrough fields in `data` retain their database names. + +### 9.7 Nested‑plugin registration +A plugin that may appear inside a container **shall** be registered in the +`PLUGIN_RENDERERS` map in **both** `ContentElementResolver` and +`ContainerChildrenProcessor`, as `CType => [RendererClass::class, 'jsonKey']`. + +> **NOTE** The duplicated map is a known maintenance hazard (10.3). Until it is +> centralised, both copies **shall** be kept in sync. + +### 9.8 Header section +Every custom CE/plugin/container **shall** expose the standard header section (the core +`headers` palette; Content Blocks use a `header_section` palette). See the companion +"header convention". Header fields in JSON use the names `header`, `subheader`, +`headerLayout`, `headerPosition`, `headerLink`. + +--- + +## 10 Maintainability and upgrade‑safety (ISO 25010) + +This clause records the quality characteristics *maintainability* and *portability* +and the concrete risks and rules that preserve them. + +### 10.1 Modularity — current state +Strengths: uniform envelope, dual‑entry pattern, exception safety, a shared +`PLUGIN_RENDERERS` map, and the `UsecaseSerializer` reference pattern. +Weakness: **substantial duplication** across the inline renderers. + +### 10.2 Reusability — duplication register +The following logic is duplicated across many renderers and **should** be extracted +into shared services (target design in parentheses): + +| Duplicated logic | Occurrences | Target service | +|---|---|---| +| FAL image/`srcset` resolution | Product(List/Show), Market, Solution, Event, Datasheets | `FalImageResolver` | +| FAL video resolution | Product, Usecase, hero | `FalImageResolver::video()` | +| `sys_category` MM query | ≥ 9 renderers | `CategoryResolver` | +| Custom MM (product↔download, …) | ≥ 5 renderers | `RelationResolver::resolveMany()` | +| Download file‑by‑convention | 5 renderers | `ConventionFileResolver` | +| `letterSequenceToRank()` sort helper | 5 renderers | static utility | +| Page‑id discovery | all renderers | `PageIdResolver::resolve()` | + +> **RULE** When a shared resolver service exists, new renderers **shall** use it and +> **shall not** re‑implement the logic inline. + +### 10.3 Analysability — single sources of truth +- The `PLUGIN_RENDERERS` map exists in two files (10.2/9.7); it **should** be promoted + to one shared constant/class. +- Table and field names are string literals scattered across renderers. New code + **shall** define table/field names as **class constants** (as `UsecaseSerializer` + and the processors already do) to localise upgrade impact. + +### 10.4 Portability — upgrade‑sensitivity points +| Point | Risk | Mitigation | +|---|---|---| +| `friendsoftypo3/headless ^5.0@rc` | RC; `lib.contentElement(WithHeader)` shape may change | Pin exact RC; re‑verify envelope after any bump; keep payloads decoupled (P2) | +| `nb-headless-content-blocks ^0.0.x` | pre‑1.0; CB→JSON shape and collection storage may change | `vitec_columns` resolution reads the table from TCA (`foreign_table`) — do **not** hard‑code CB tables | +| `georgringer/news ^14` | 10 News CTypes hard‑mapped in `NewsJsonRenderer` | Keep the CType→layout map in one place; re‑verify on major news upgrade | +| `b13/container ^3.1` | child linkage via `tx_container_parent`; page‑module grid required | Documented limitation: containers cannot be authored inside IRRE (Annex B‑2) | + +### 10.5 Modifiability — mandatory rules distilled +1. Container CTypes **shall** use `<` (copy), never `=<` (reference) — see Annex B‑1. +2. Table/field names **shall** be class constants, not inline literals. +3. Renderers **shall** reuse shared resolver services once they exist. +4. Magic numeric literals (e.g. a hard‑coded parent‑category uid) **shall** be replaced + by named constants or configuration. + +--- + +## 11 Conformance + +An implementation conforms to this specification if, for every content type it +exposes: +- **C1** the output validates as RFC 8259 JSON and matches the envelope of 7.2; +- **C2** the responsible renderer satisfies the class shape of 9.1 and the dual‑entry + pattern of 9.3; +- **C3** page‑id discovery follows 9.4 and error handling follows 9.5; +- **C4** payload keys follow 9.6 and the header section follows 9.8; +- **C5** container derivation follows the `<`‑copy rule of 6.4/10.5(1); +- **C6** any container‑nestable plugin is registered per 9.7. + +Deviations are recorded in Annex B and **shall** carry a remediation plan. + +--- + +## Annex A (normative) — Checklist: adding a new headless plugin + +1. **Model/TCA/SQL** — create the domain table and TCA; define table/field names as + constants. +2. **Serializer** — add `Classes/Service/Serializer` with `serializeListItem()` + and/or `serializeDetail()`; reuse existing resolver services. +3. **Renderer** — add `Classes/UserFunc/JsonRenderer` per 9.1, delegating + to the serializer; implement `render()` (9.3/9.4) and `renderForRecord()`. +4. **TypoScript** — in `Configuration/Sets/Vitecset/setup.typoscript`: + `tt_content. < lib.contentElementWithHeader` and + `content.fields. = USER` + `.userFunc = …->render`. +5. **Header section** — ensure the `headers` palette is present (9.8). +6. **Nesting** — if the plugin may sit inside a container, register it in + `PLUGIN_RENDERERS` in **both** the resolver and the processor (9.7). +7. **Deploy** — `vendor/bin/typo3 database:updateschema "*.add,*.change"` then + `vendor/bin/typo3 cache:flush`. +8. **Verify** — fetch the page JSON; confirm envelope (C1), keys (C4) and nested output. + +--- + +## Annex B (informative) — Nonconformity and technical‑debt register + +The following items were identified during architecture analysis. Items marked +*(to verify)* were reported by static review and **shall** be confirmed before +remediation. + +- **B‑1 — `=<` on Event/News CTypes.** `vitec_eventlist` and `news_pi1` use the + reference operator `=< lib.contentElementWithHeader`. Reference *to a `lib.*` object* + is used by headless itself and is generally safe; however, for consistency with + 10.5(1) these are VERIFIED SAFE and left as-is (references to lib.* are idiomatic in headless; only tt_content-to-tt_content references are unsafe, and those are already `<` for containers). +- **B‑2 — Containers cannot be authored inline (IRRE).** b13 container children live in + `tx_container_parent` and require the page‑module grid; they cannot be created inside + an inline field. This is a platform limitation, not a defect. The Success Story + "Columns" Content Block (`vitec_columns`) is the sanctioned inline alternative. +- **B‑3 — Duplicated `PLUGIN_RENDERERS` map** in `ContentElementResolver` and + `ContainerChildrenProcessor` (9.7/10.3). +- **B‑4 — Inline duplication** of image/category/MM/page‑id logic (10.2). +- **B‑5 — Hard‑coded literals** — model/MM table names, a `/fileadmin` prefix for + event JSON‑LD image URLs (`PageJsonLdRenderer`), and at least one magic + parent‑category uid appear as inline literals across download/datasheet/structured‑data + code *(to verify and extract to constants)*. `COLPOS_TO_COLUMN` in + `ContainerChildrenProcessor` must be kept in sync with the container TCA colPos values. +- **B‑6 — `DownloadcardcollectionJsonRenderer`**: two misplaced thumbnail output lines referenced an undefined variable in the image resolver. FIXED 2026-07-09 (removed; the PDF-thumbnail method is unaffected). +- **B‑7 — v13→v14 `CType`/`list_type` compatibility branches** in some download/ + datasheet renderers FIXED 2026-07-09: the unsatisfiable legacy OR branch was removed; the query now filters on the v14 CType only. + +--- + +## Annex C (informative) — Related documents + +- `Documentation/HeadlessIntegration.md` — informal how‑to (superseded as the + authoritative reference by this document). +- Header convention — the uniform header section across CEs, plugins and containers. +- `Configuration/Sets/Vitecset/setup.typoscript` — the single TypoScript entry point. + +*End of document EVO‑VITEC‑HL‑001 v1.0.* diff --git a/packages/vitec/Resources/Private/Language/locallang_buttons.xlf b/packages/vitec/Resources/Private/Language/locallang_buttons.xlf old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Private/Language/locallang_containers.xlf b/packages/vitec/Resources/Private/Language/locallang_containers.xlf old mode 100755 new mode 100644 index aea755f..2ae841d --- a/packages/vitec/Resources/Private/Language/locallang_containers.xlf +++ b/packages/vitec/Resources/Private/Language/locallang_containers.xlf @@ -111,6 +111,73 @@ Sidebar (33%) + + VITEC · Cards Carousel + + + Horizontal carousel/slider. Place VITEC Card elements (or other content) inside; arrows, dots, autoplay and slides-per-view are configurable. + + + Slides + + + Carousel Settings + + + Align + + + flex-start + + + center + + + flex-end + + + stretch + + + Justify + + + flex-start + + + center + + + space-between + + + space-around + + + space-evenly + + + Grid + + + Gap + + + 1 + + + 2 + + + 3 + + + 4 + + + 5 + + diff --git a/packages/vitec/Resources/Private/Language/locallang_pages.xlf b/packages/vitec/Resources/Private/Language/locallang_pages.xlf old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Private/Templates/Downloadcard/Backendpreview.html b/packages/vitec/Resources/Private/Templates/Downloadcard/Backendpreview.html old mode 100755 new mode 100644 index c904f43..785b0fc --- a/packages/vitec/Resources/Private/Templates/Downloadcard/Backendpreview.html +++ b/packages/vitec/Resources/Private/Templates/Downloadcard/Backendpreview.html @@ -13,16 +13,16 @@ {data.header} - Download Card (kein Header) + Download Card (no header)
- Konfiguration im FlexForm: - Produkt oder Download wählen, - Layout-Variante setzen. + Configured via FlexForm: + Select a product or download, + set the layout variant.
diff --git a/packages/vitec/Resources/Private/Templates/Downloadcardcollection/Backendpreview.html b/packages/vitec/Resources/Private/Templates/Downloadcardcollection/Backendpreview.html old mode 100755 new mode 100644 index 01f01ca..5fb3bf7 --- a/packages/vitec/Resources/Private/Templates/Downloadcardcollection/Backendpreview.html +++ b/packages/vitec/Resources/Private/Templates/Downloadcardcollection/Backendpreview.html @@ -13,15 +13,15 @@ {data.header} - Download Card Collection (kein Header) + Download Card Collection (no header)
- Multi-Download-Auswahl mit optionalem Header-Image. - Konfiguration im FlexForm. + Multi-download selection with optional header image. + Configured via FlexForm.
diff --git a/packages/vitec/Resources/Public/Css/backend-container-collapse.css b/packages/vitec/Resources/Public/Css/backend-container-collapse.css new file mode 100644 index 0000000..8d3e19b --- /dev/null +++ b/packages/vitec/Resources/Public/Css/backend-container-collapse.css @@ -0,0 +1,22 @@ +/* ============================================================= + VITEC — container collapse/expand in the Page module + ============================================================= */ + +/* Hide the container body (nested child columns) when collapsed. */ +.t3-page-ce.vitec-ce-collapsed > .t3-page-ce-element > .t3-page-ce-body { + display: none; +} + +/* Optional: dim/round the collapsed container header a touch. */ +.t3-page-ce.vitec-ce-collapsed > .t3-page-ce-element > .t3-page-ce-header { + border-bottom: 1px dashed var(--typo3-component-border-color, #ccc); +} + +/* Chevron rotates when collapsed. */ +.vitec-collapse-toggle typo3-backend-icon { + display: inline-flex; + transition: transform 0.15s ease-in-out; +} +.t3-page-ce.vitec-ce-collapsed .vitec-collapse-toggle typo3-backend-icon { + transform: rotate(180deg); +} diff --git a/packages/vitec/Resources/Public/Css/backend-preview.css b/packages/vitec/Resources/Public/Css/backend-preview.css old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Public/Icons/tx_vitec_domain_model_event.svg b/packages/vitec/Resources/Public/Icons/tx_vitec_domain_model_event.svg new file mode 100644 index 0000000..1762f93 --- /dev/null +++ b/packages/vitec/Resources/Public/Icons/tx_vitec_domain_model_event.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/vitec/Resources/Public/Icons/vitec-cards-carousel.svg b/packages/vitec/Resources/Public/Icons/vitec-cards-carousel.svg new file mode 100644 index 0000000..ba359b5 --- /dev/null +++ b/packages/vitec/Resources/Public/Icons/vitec-cards-carousel.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/vitec/Resources/Public/Icons/vitec-cols-25-25-25-25.svg b/packages/vitec/Resources/Public/Icons/vitec-cols-25-25-25-25.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Public/Icons/vitec-cols-33-33-33.svg b/packages/vitec/Resources/Public/Icons/vitec-cols-33-33-33.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Public/Icons/vitec-cols-33-66.svg b/packages/vitec/Resources/Public/Icons/vitec-cols-33-66.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Public/Icons/vitec-cols-50-50.svg b/packages/vitec/Resources/Public/Icons/vitec-cols-50-50.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Public/Icons/vitec-cols-66-33.svg b/packages/vitec/Resources/Public/Icons/vitec-cols-66-33.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Public/Icons/vitec-container.svg b/packages/vitec/Resources/Public/Icons/vitec-container.svg old mode 100755 new mode 100644 diff --git a/packages/vitec/Resources/Public/Icons/vitec-plugin-datasheets.svg b/packages/vitec/Resources/Public/Icons/vitec-plugin-datasheets.svg new file mode 100644 index 0000000..2ad65d5 --- /dev/null +++ b/packages/vitec/Resources/Public/Icons/vitec-plugin-datasheets.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/vitec/Resources/Public/Icons/vitec-plugin-eventlist.svg b/packages/vitec/Resources/Public/Icons/vitec-plugin-eventlist.svg new file mode 100644 index 0000000..59de362 --- /dev/null +++ b/packages/vitec/Resources/Public/Icons/vitec-plugin-eventlist.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/vitec/Resources/Public/Javascript/container-collapse.js b/packages/vitec/Resources/Public/Javascript/container-collapse.js new file mode 100644 index 0000000..e61a74b --- /dev/null +++ b/packages/vitec/Resources/Public/Javascript/container-collapse.js @@ -0,0 +1,131 @@ +/** + * VITEC — collapse/expand toggle for container content elements in the + * TYPO3 v14 Page module. + * + * Adds a chevron button into the `.btn-toolbar` of every VITEC container + * (vitec_container, vitec_cols_*, vitec_cards_carousel — anything that + * renders a nested b13 grid). Clicking it hides/shows the container body + * (the nested child columns). State is persisted per element uid in + * localStorage, so it survives reloads. + * + * Pure DOM enhancement — no core or b13 template overrides. + */ +class VitecContainerCollapse { + constructor() { + this.storagePrefix = 'vitec-ce-collapsed-'; + this.ready(); + } + + ready() { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => this.boot()); + } else { + this.boot(); + } + } + + boot() { + this.processAll(); + // Page module can re-render columns via AJAX; watch for new elements. + const root = document.querySelector('.t3js-page-columns-wrapper, .module, body'); + if (root) { + const observer = new MutationObserver(() => { + window.clearTimeout(this._debounce); + this._debounce = window.setTimeout(() => this.processAll(), 150); + }); + observer.observe(root, { childList: true, subtree: true }); + } + } + + processAll() { + document.querySelectorAll('.t3-page-ce[data-uid]').forEach((ce) => this.enhance(ce)); + } + + isCollapsed(uid) { + try { + return window.localStorage.getItem(this.storagePrefix + uid) === '1'; + } catch (e) { + return false; + } + } + + setCollapsed(uid, collapsed) { + try { + if (collapsed) { + window.localStorage.setItem(this.storagePrefix + uid, '1'); + } else { + window.localStorage.removeItem(this.storagePrefix + uid); + } + } catch (e) { + /* storage unavailable — ignore */ + } + } + + enhance(ce) { + if (ce.dataset.vitecCollapseReady === '1') { + return; + } + + // The direct body of THIS element (not a nested child's body). + const element = ce.querySelector(':scope > .t3-page-ce-element'); + if (!element) { + return; + } + const body = element.querySelector(':scope > .t3-page-ce-body'); + if (!body) { + return; + } + + // A container is recognised by a nested b13 grid inside its body. + const hasNestedGrid = body.querySelector('.t3-grid-container') !== null; + if (!hasNestedGrid) { + return; + } + + // Best-effort VITEC filter via the header icon identifier + // (b13 sets the icon identifier to the CType, e.g. "vitec_container"). + const iconEl = ce.querySelector( + '.t3-page-ce-header-left typo3-backend-icon[identifier], .t3-page-ce-header-left [data-identifier]' + ); + if (iconEl) { + const identifier = + iconEl.getAttribute('identifier') || iconEl.getAttribute('data-identifier') || ''; + if (identifier && identifier.indexOf('vitec') === -1) { + return; // a non-VITEC container — leave it alone + } + } + + const toolbar = element.querySelector( + ':scope > .t3-page-ce-header .btn-toolbar .btn-group' + ); + if (!toolbar) { + return; + } + + ce.dataset.vitecCollapseReady = '1'; + const uid = ce.dataset.uid; + + const button = document.createElement('button'); + button.type = 'button'; + button.className = 'btn btn-sm btn-default btn-borderless vitec-collapse-toggle'; + button.title = 'Collapse / expand container'; + button.setAttribute('aria-label', 'Collapse or expand container'); + button.innerHTML = + ''; + + toolbar.insertBefore(button, toolbar.firstChild); + + if (this.isCollapsed(uid)) { + ce.classList.add('vitec-ce-collapsed'); + } + + button.addEventListener('click', (event) => { + event.preventDefault(); + event.stopPropagation(); + const collapsed = ce.classList.toggle('vitec-ce-collapsed'); + this.setCollapsed(uid, collapsed); + }); + } +} + +export default new VitecContainerCollapse(); diff --git a/packages/vitec/Resources/Public/Javascript/structured-data-generator.js b/packages/vitec/Resources/Public/Javascript/structured-data-generator.js old mode 100755 new mode 100644 diff --git a/packages/vitec/ext_localconf.php b/packages/vitec/ext_localconf.php old mode 100755 new mode 100644 index b57ed44..c2e64b0 --- a/packages/vitec/ext_localconf.php +++ b/packages/vitec/ext_localconf.php @@ -147,4 +147,14 @@ $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1750000000] = [ ] ); + ExtensionUtility::configurePlugin( + 'Vitec', + 'Eventlist', + [ + \Evomedien\Vitec\Controller\EventController::class => 'list' + ], + [ + \Evomedien\Vitec\Controller\EventController::class => 'list' + ] + ); })(); diff --git a/packages/vitec/ext_tables.sql b/packages/vitec/ext_tables.sql old mode 100755 new mode 100644 index dc321ca..97a8c56 --- a/packages/vitec/ext_tables.sql +++ b/packages/vitec/ext_tables.sql @@ -93,27 +93,51 @@ CREATE TABLE tx_vitec_product_related_mm ( ); CREATE TABLE tx_vitec_domain_model_usecase ( - uid int(11) NOT NULL auto_increment, - pid int(11) DEFAULT '0' NOT NULL, - tstamp int(11) DEFAULT '0' NOT NULL, - crdate int(11) DEFAULT '0' NOT NULL, - cruser_id int(11) DEFAULT '0' NOT NULL, - deleted tinyint(4) DEFAULT '0' NOT NULL, - hidden tinyint(4) DEFAULT '0' NOT NULL, - starttime int(11) DEFAULT '0' NOT NULL, - endtime int(11) DEFAULT '0' NOT NULL, title varchar(255) DEFAULT '' NOT NULL, slug varchar(255) DEFAULT '' NOT NULL, - teaser varchar(255) DEFAULT '' NOT NULL, - subtitle varchar(255) DEFAULT '' NOT NULL, - description text, - caseimage INTEGER, - logoimage INTEGER, - singlepid varchar(255) DEFAULT '' NOT NULL, + subtitle varchar(255) DEFAULT '' NOT NULL, + + card_image int(11) unsigned DEFAULT '0' NOT NULL, + customer_logo int(11) unsigned DEFAULT '0' NOT NULL, + teaser text, + market int(11) unsigned DEFAULT '0' NOT NULL, + + hero_bgimage int(11) unsigned DEFAULT '0' NOT NULL, + hero_small_image int(11) unsigned DEFAULT '0' NOT NULL, + hero_video int(11) unsigned DEFAULT '0' NOT NULL, + hero_overlay_color varchar(20) DEFAULT '' NOT NULL, + hero_overlay_opacity decimal(3,2) DEFAULT '0.00' NOT NULL, + + content_elements int(11) unsigned DEFAULT '0' NOT NULL, + + solutions int(11) unsigned DEFAULT '0' NOT NULL, + products int(11) unsigned DEFAULT '0' NOT NULL, + categories int(11) unsigned DEFAULT '0' NOT NULL, + + seo_title varchar(255) DEFAULT '' NOT NULL, + seo_description text, + no_index smallint(5) unsigned DEFAULT '0' NOT NULL, + no_follow smallint(5) unsigned DEFAULT '0' NOT NULL, + canonical_link varchar(1024) DEFAULT '' NOT NULL, + og_title varchar(255) DEFAULT '' NOT NULL, + og_description text, + og_image int(11) unsigned DEFAULT '0' NOT NULL, + twitter_title varchar(255) DEFAULT '' NOT NULL, + twitter_description text, + twitter_image int(11) unsigned DEFAULT '0' NOT NULL, + + layout_variant varchar(30) DEFAULT 'standard' NOT NULL, + background_variant varchar(20) DEFAULT 'none' NOT NULL, + accent_color varchar(20) DEFAULT '' NOT NULL, hideonapp smallint(5) unsigned DEFAULT '0' NOT NULL, - hideonwebsite smallint(5) unsigned DEFAULT '0' NOT NULL, - PRIMARY KEY (uid), - KEY parent (pid) + hideonwebsite smallint(5) unsigned DEFAULT '0' NOT NULL, + featured smallint(5) unsigned DEFAULT '0' NOT NULL, + show_related smallint(5) unsigned DEFAULT '1' NOT NULL, + hero_layout varchar(20) DEFAULT 'fullscreen' NOT NULL, + text_theme varchar(20) DEFAULT 'light' NOT NULL, + + description text, + singlepid varchar(255) DEFAULT '' NOT NULL ); CREATE TABLE tx_vitec_domain_model_solution ( @@ -169,5 +193,53 @@ ADD type VARCHAR(255) DEFAULT '' NOT NULL; CREATE TABLE tt_content ( - tx_vitec_bg_variant VARCHAR(20) DEFAULT 'none' NOT NULL + tx_vitec_bg_variant VARCHAR(20) DEFAULT 'none' NOT NULL, + tx_vitec_gap VARCHAR(5) DEFAULT '3' NOT NULL, + tx_vitec_col1_align VARCHAR(20) DEFAULT 'stretch' NOT NULL, + tx_vitec_col1_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL, + tx_vitec_col2_align VARCHAR(20) DEFAULT 'stretch' NOT NULL, + tx_vitec_col2_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL, + tx_vitec_col3_align VARCHAR(20) DEFAULT 'stretch' NOT NULL, + tx_vitec_col3_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL, + tx_vitec_col4_align VARCHAR(20) DEFAULT 'stretch' NOT NULL, + tx_vitec_col4_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL, + tx_vitec_usecase_content int(11) unsigned DEFAULT '0' NOT NULL +); + +CREATE TABLE tx_vitec_domain_model_event ( + title varchar(255) DEFAULT '' NOT NULL, + slug varchar(255) DEFAULT '' NOT NULL, + teaser varchar(255) DEFAULT '' NOT NULL, + description text, + eventstart int(11) DEFAULT '0' NOT NULL, + eventend int(11) DEFAULT '0' NOT NULL, + venue varchar(255) DEFAULT '' NOT NULL, + booth varchar(255) DEFAULT '' NOT NULL, + city varchar(255) DEFAULT '' NOT NULL, + country varchar(255) DEFAULT '' NOT NULL, + attendancemode varchar(20) DEFAULT 'offline' NOT NULL, + eventstatus varchar(20) DEFAULT 'scheduled' NOT NULL, + eventurl varchar(1024) DEFAULT '' NOT NULL, + meetinglink varchar(1024) DEFAULT '' NOT NULL, + image int(11) unsigned DEFAULT '0' NOT NULL, + hideonwebsite smallint(5) unsigned DEFAULT '0' NOT NULL, + hideonapp smallint(5) unsigned DEFAULT '0' NOT NULL +); + +CREATE TABLE tx_vitec_usecase_solution_mm ( + uid_local int(11) unsigned DEFAULT '0' NOT NULL, + uid_foreign int(11) unsigned DEFAULT '0' NOT NULL, + sorting int(11) unsigned DEFAULT '0' NOT NULL, + sorting_foreign int(11) unsigned DEFAULT '0' NOT NULL, + KEY uid_local (uid_local), + KEY uid_foreign (uid_foreign) +); + +CREATE TABLE tx_vitec_usecase_product_mm ( + uid_local int(11) unsigned DEFAULT '0' NOT NULL, + uid_foreign int(11) unsigned DEFAULT '0' NOT NULL, + sorting int(11) unsigned DEFAULT '0' NOT NULL, + sorting_foreign int(11) unsigned DEFAULT '0' NOT NULL, + KEY uid_local (uid_local), + KEY uid_foreign (uid_foreign) ); diff --git a/public/.htaccess b/public/.htaccess index 522d097..6e6d24e 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -318,6 +318,11 @@ AddDefaultCharset utf-8 RewriteCond %{SCRIPT_FILENAME} -f RewriteRule (?:^|/)\. - [F] + # Redirect missing hardcoded Collateral file URLs to a resolver that + # chooses the newest available version by filename convention. + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^fileadmin/downloads/Collateral/(.+)$ %{ENV:CWD}collateral-fallback.php?requested=$1 [QSA,L,NC] + # Stop rewrite processing, if we are in any known directory # NOTE: Add your additional local storages here RewriteRule ^(?:fileadmin/|typo3conf/|typo3temp/|uploads/) - [L] @@ -392,7 +397,7 @@ FileETag None # Add your own rules here. -AuthUserFile "/usr/www/users/vitecevo/live/public/.htpasswd" -AuthName "DEV" -AuthType Basic -require valid-user +#AuthUserFile "/usr/www/users/vitecevo/live/public/.htpasswd" +#AuthName "DEV" +#AuthType Basic +#require valid-user diff --git a/public/_frontend/.htaccess b/public/_frontend/.htaccess index 3ca08b9..15135c6 100644 --- a/public/_frontend/.htaccess +++ b/public/_frontend/.htaccess @@ -9,8 +9,19 @@ RewriteRule ^ - [L] RewriteRule ^ index.html [L] +# ── Cache headers ──────────────────────────────────────────────────────────── + +# index.html: never cache — always fetch fresh so the browser picks up +# the latest hashed JS/CSS filenames after a deploy. - Header set Cache-Control "no-cache, no-store, must-revalidate" + Header set Cache-Control "no-store, no-cache, must-revalidate" Header set Pragma "no-cache" - Header set Expires 0 - \ No newline at end of file + Header set Expires "0" + + +# Hashed assets (JS, CSS, fonts, images inside /assets/): +# Vite appends a content hash to every filename, so these are immutable. +# Cache them for 1 year — a new deploy produces new filenames automatically. + + Header set Cache-Control "public, max-age=31536000, immutable" + diff --git a/public/_frontend/assets/VitecDebugToggle-9pp4AW9x.js b/public/_frontend/assets/VitecDebugToggle-9pp4AW9x.js deleted file mode 100644 index 4346a66..0000000 --- a/public/_frontend/assets/VitecDebugToggle-9pp4AW9x.js +++ /dev/null @@ -1 +0,0 @@ -import{B as e,E as t,F as n,I as r,K as i,L as a,M as o,N as s,O as c,P as l,R as u,U as d,V as f,j as p,k as m,r as h,w as g,z as _}from"./index-BI31wk8i.js";var v=i(d());function y(e){let{controlled:t,default:n,name:r,state:i=`value`}=e,{current:a}=v.useRef(t!==void 0),[o,s]=v.useState(n);return[a?t:o,v.useCallback(e=>{a||s(e)},[])]}var b=y,x=v.createContext(void 0);function S(){return v.useContext(x)}function C(e){return _(`PrivateSwitchBase`,e)}u(`PrivateSwitchBase`,[`root`,`checked`,`disabled`,`input`,`edgeStart`,`edgeEnd`]);var w=f(),T=e=>{let{classes:t,checked:n,disabled:r,edge:i}=e;return a({root:[`root`,n&&`checked`,r&&`disabled`,i&&`edge${l(i)}`],input:[`input`]},C,t)},E=n(m,{name:`MuiSwitchBase`})({padding:9,borderRadius:`50%`,variants:[{props:{edge:`start`,size:`small`},style:{marginLeft:-3}},{props:({edge:e,ownerState:t})=>e===`start`&&t.size!==`small`,style:{marginLeft:-12}},{props:{edge:`end`,size:`small`},style:{marginRight:-3}},{props:({edge:e,ownerState:t})=>e===`end`&&t.size!==`small`,style:{marginRight:-12}}]}),D=n(`input`,{name:`MuiSwitchBase`,shouldForwardProp:r})({cursor:`inherit`,position:`absolute`,opacity:0,width:`100%`,height:`100%`,top:0,left:0,margin:0,padding:0,zIndex:1}),O=v.forwardRef(function(e,t){let{autoFocus:n,checked:r,checkedIcon:i,defaultChecked:a,disabled:o,disableFocusRipple:s=!1,edge:c=!1,icon:l,id:u,inputProps:d,inputRef:f,name:m,onBlur:h,onChange:g,onFocus:_,readOnly:v,required:y=!1,tabIndex:x,type:C,value:O,slots:k={},slotProps:A={},...j}=e,[M,N]=b({controlled:r,default:!!a,name:`SwitchBase`,state:`checked`}),P=S(),F=e=>{_&&_(e),P&&P.onFocus&&P.onFocus(e)},I=e=>{h&&h(e),P&&P.onBlur&&P.onBlur(e)},L=e=>{if(e.nativeEvent.defaultPrevented)return;let t=e.target.checked;N(t),g&&g(e,t)},R=o;P&&R===void 0&&(R=P.disabled);let z=C===`checkbox`||C===`radio`,B={...e,checked:M,disabled:R,disableFocusRipple:s,edge:c},V=T(B),H={slots:k,slotProps:{input:d,...A}},[U,W]=p(`root`,{ref:t,elementType:E,className:V.root,shouldForwardComponentProp:!0,externalForwardedProps:{...H,component:`span`,...j},getSlotProps:e=>({...e,onFocus:t=>{e.onFocus?.(t),F(t)},onBlur:t=>{e.onBlur?.(t),I(t)}}),ownerState:B,additionalProps:{centerRipple:!0,focusRipple:!s,disabled:R,role:void 0,tabIndex:null}}),[G,K]=p(`input`,{ref:f,elementType:D,className:V.input,externalForwardedProps:H,getSlotProps:e=>({...e,onChange:t=>{e.onChange?.(t),L(t)}}),ownerState:B,additionalProps:{autoFocus:n,checked:r,defaultChecked:a,disabled:R,id:z?u:void 0,name:m,readOnly:v,required:y,tabIndex:x,type:C,...C===`checkbox`&&O===void 0?{}:{value:O}}});return(0,w.jsxs)(U,{...W,children:[(0,w.jsx)(G,{...K}),M?i:l]})});function k(e){return _(`MuiSwitch`,e)}var A=u(`MuiSwitch`,[`root`,`edgeStart`,`edgeEnd`,`switchBase`,`colorPrimary`,`colorSecondary`,`sizeSmall`,`sizeMedium`,`checked`,`disabled`,`input`,`thumb`,`track`]),j=e=>{let{classes:t,edge:n,size:r,color:i,checked:o,disabled:s}=e,c=a({root:[`root`,n&&`edge${l(n)}`,`size${l(r)}`],switchBase:[`switchBase`,`color${l(i)}`,o&&`checked`,s&&`disabled`],thumb:[`thumb`],track:[`track`],input:[`input`]},k,t);return{...t,...c}},M=n(`span`,{name:`MuiSwitch`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.edge&&t[`edge${l(n.edge)}`],t[`size${l(n.size)}`]]}})({display:`inline-flex`,width:58,height:38,overflow:`hidden`,padding:12,boxSizing:`border-box`,position:`relative`,flexShrink:0,zIndex:0,verticalAlign:`middle`,"@media print":{colorAdjust:`exact`},variants:[{props:{edge:`start`},style:{marginLeft:-8}},{props:{edge:`end`},style:{marginRight:-8}},{props:{size:`small`},style:{width:40,height:24,padding:7,[`& .${A.thumb}`]:{width:16,height:16},[`& .${A.switchBase}`]:{padding:4,[`&.${A.checked}`]:{transform:`translateX(16px)`}}}}]}),N=n(O,{name:`MuiSwitch`,slot:`SwitchBase`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.switchBase,{[`& .${A.input}`]:t.input},n.color!==`default`&&t[`color${l(n.color)}`]]}})(s(({theme:e})=>({position:`absolute`,top:0,left:0,zIndex:1,color:e.vars?e.vars.palette.Switch.defaultColor:`${e.palette.mode===`light`?e.palette.common.white:e.palette.grey[300]}`,transition:e.transitions.create([`left`,`transform`],{duration:e.transitions.duration.shortest}),[`&.${A.checked}`]:{transform:`translateX(20px)`},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch.defaultDisabledColor:`${e.palette.mode===`light`?e.palette.grey[100]:e.palette.grey[600]}`},[`&.${A.checked} + .${A.track}`]:{opacity:.5},[`&.${A.disabled} + .${A.track}`]:{opacity:e.vars?e.vars.opacity.switchTrackDisabled:`${e.palette.mode===`light`?.12:.2}`},[`& .${A.input}`]:{left:`-100%`,width:`300%`}})),s(({theme:e})=>({"&:hover":{backgroundColor:e.alpha((e.vars||e).palette.action.active,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},variants:[...Object.entries(e.palette).filter(c([`light`])).map(([t])=>({props:{color:t},style:{[`&.${A.checked}`]:{color:(e.vars||e).palette[t].main,"&:hover":{backgroundColor:e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch[`${t}DisabledColor`]:`${e.palette.mode===`light`?e.lighten(e.palette[t].main,.62):e.darken(e.palette[t].main,.55)}`}},[`&.${A.checked} + .${A.track}`]:{backgroundColor:(e.vars||e).palette[t].main}}}))]}))),P=n(`span`,{name:`MuiSwitch`,slot:`Track`})(s(({theme:e})=>({height:`100%`,width:`100%`,borderRadius:14/2,zIndex:-1,transition:e.transitions.create([`opacity`,`background-color`],{duration:e.transitions.duration.shortest}),backgroundColor:e.vars?e.vars.palette.common.onBackground:`${e.palette.mode===`light`?e.palette.common.black:e.palette.common.white}`,opacity:e.vars?e.vars.opacity.switchTrack:`${e.palette.mode===`light`?.38:.3}`}))),F=n(`span`,{name:`MuiSwitch`,slot:`Thumb`})(s(({theme:e})=>({boxShadow:(e.vars||e).shadows[1],backgroundColor:`currentColor`,width:20,height:20,borderRadius:`50%`}))),I=v.forwardRef(function(t,n){let r=o({props:t,name:`MuiSwitch`}),{className:i,color:a=`primary`,edge:s=!1,size:c=`medium`,sx:l,slots:u={},slotProps:d={},...f}=r,m={...r,color:a,edge:s,size:c},h=j(m),g={slots:u,slotProps:d},[_,v]=p(`root`,{className:e(h.root,i),elementType:M,externalForwardedProps:g,ownerState:m,additionalProps:{sx:l}}),[y,b]=p(`thumb`,{className:h.thumb,elementType:F,externalForwardedProps:g,ownerState:m}),x=(0,w.jsx)(y,{...b}),[S,C]=p(`track`,{className:h.track,elementType:P,externalForwardedProps:g,ownerState:m});return(0,w.jsxs)(_,{...v,children:[(0,w.jsx)(N,{type:`checkbox`,icon:x,checkedIcon:x,ref:n,ownerState:m,...f,classes:{...h,root:h.switchBase},slots:{...u.switchBase&&{root:u.switchBase},...u.input&&{input:u.input}},slotProps:{...d.switchBase&&{root:typeof d.switchBase==`function`?d.switchBase(m):d.switchBase},input:{role:`switch`},...d.input&&{input:typeof d.input==`function`?d.input(m):d.input}}}),(0,w.jsx)(S,{...C})]})});function L({enabled:e,onChange:n}){return h?(0,w.jsxs)(g,{sx:{position:`fixed`,bottom:`1rem`,right:`1rem`,zIndex:9999,display:`flex`,alignItems:`center`,gap:`0.5rem`,bgcolor:`background.paper`,border:`1px solid`,borderColor:`divider`,borderRadius:`2rem`,px:`0.75rem`,py:`0.25rem`,boxShadow:3},children:[(0,w.jsx)(t,{variant:`caption`,sx:{userSelect:`none`,fontWeight:600,letterSpacing:`0.05em`},children:`Debug`}),(0,w.jsx)(I,{size:`small`,checked:e,onChange:(e,t)=>n(t)})]}):null}export{L as VitecDebugToggle}; \ No newline at end of file diff --git a/public/_frontend/assets/VitecDebugToggle-BzU_nymF.js b/public/_frontend/assets/VitecDebugToggle-BzU_nymF.js deleted file mode 100644 index 768adce..0000000 --- a/public/_frontend/assets/VitecDebugToggle-BzU_nymF.js +++ /dev/null @@ -1 +0,0 @@ -import{B as e,E as t,F as n,I as r,K as i,L as a,M as o,N as s,O as c,P as l,R as u,U as d,V as f,j as p,k as m,r as h,w as g,z as _}from"./index-jouuqNaB.js";var v=i(d());function y(e){let{controlled:t,default:n,name:r,state:i=`value`}=e,{current:a}=v.useRef(t!==void 0),[o,s]=v.useState(n);return[a?t:o,v.useCallback(e=>{a||s(e)},[])]}var b=y,x=v.createContext(void 0);function S(){return v.useContext(x)}function C(e){return _(`PrivateSwitchBase`,e)}u(`PrivateSwitchBase`,[`root`,`checked`,`disabled`,`input`,`edgeStart`,`edgeEnd`]);var w=f(),T=e=>{let{classes:t,checked:n,disabled:r,edge:i}=e;return a({root:[`root`,n&&`checked`,r&&`disabled`,i&&`edge${l(i)}`],input:[`input`]},C,t)},E=n(m,{name:`MuiSwitchBase`})({padding:9,borderRadius:`50%`,variants:[{props:{edge:`start`,size:`small`},style:{marginLeft:-3}},{props:({edge:e,ownerState:t})=>e===`start`&&t.size!==`small`,style:{marginLeft:-12}},{props:{edge:`end`,size:`small`},style:{marginRight:-3}},{props:({edge:e,ownerState:t})=>e===`end`&&t.size!==`small`,style:{marginRight:-12}}]}),D=n(`input`,{name:`MuiSwitchBase`,shouldForwardProp:r})({cursor:`inherit`,position:`absolute`,opacity:0,width:`100%`,height:`100%`,top:0,left:0,margin:0,padding:0,zIndex:1}),O=v.forwardRef(function(e,t){let{autoFocus:n,checked:r,checkedIcon:i,defaultChecked:a,disabled:o,disableFocusRipple:s=!1,edge:c=!1,icon:l,id:u,inputProps:d,inputRef:f,name:m,onBlur:h,onChange:g,onFocus:_,readOnly:v,required:y=!1,tabIndex:x,type:C,value:O,slots:k={},slotProps:A={},...j}=e,[M,N]=b({controlled:r,default:!!a,name:`SwitchBase`,state:`checked`}),P=S(),F=e=>{_&&_(e),P&&P.onFocus&&P.onFocus(e)},I=e=>{h&&h(e),P&&P.onBlur&&P.onBlur(e)},L=e=>{if(e.nativeEvent.defaultPrevented)return;let t=e.target.checked;N(t),g&&g(e,t)},R=o;P&&R===void 0&&(R=P.disabled);let z=C===`checkbox`||C===`radio`,B={...e,checked:M,disabled:R,disableFocusRipple:s,edge:c},V=T(B),H={slots:k,slotProps:{input:d,...A}},[U,W]=p(`root`,{ref:t,elementType:E,className:V.root,shouldForwardComponentProp:!0,externalForwardedProps:{...H,component:`span`,...j},getSlotProps:e=>({...e,onFocus:t=>{e.onFocus?.(t),F(t)},onBlur:t=>{e.onBlur?.(t),I(t)}}),ownerState:B,additionalProps:{centerRipple:!0,focusRipple:!s,disabled:R,role:void 0,tabIndex:null}}),[G,K]=p(`input`,{ref:f,elementType:D,className:V.input,externalForwardedProps:H,getSlotProps:e=>({...e,onChange:t=>{e.onChange?.(t),L(t)}}),ownerState:B,additionalProps:{autoFocus:n,checked:r,defaultChecked:a,disabled:R,id:z?u:void 0,name:m,readOnly:v,required:y,tabIndex:x,type:C,...C===`checkbox`&&O===void 0?{}:{value:O}}});return(0,w.jsxs)(U,{...W,children:[(0,w.jsx)(G,{...K}),M?i:l]})});function k(e){return _(`MuiSwitch`,e)}var A=u(`MuiSwitch`,[`root`,`edgeStart`,`edgeEnd`,`switchBase`,`colorPrimary`,`colorSecondary`,`sizeSmall`,`sizeMedium`,`checked`,`disabled`,`input`,`thumb`,`track`]),j=e=>{let{classes:t,edge:n,size:r,color:i,checked:o,disabled:s}=e,c=a({root:[`root`,n&&`edge${l(n)}`,`size${l(r)}`],switchBase:[`switchBase`,`color${l(i)}`,o&&`checked`,s&&`disabled`],thumb:[`thumb`],track:[`track`],input:[`input`]},k,t);return{...t,...c}},M=n(`span`,{name:`MuiSwitch`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.edge&&t[`edge${l(n.edge)}`],t[`size${l(n.size)}`]]}})({display:`inline-flex`,width:58,height:38,overflow:`hidden`,padding:12,boxSizing:`border-box`,position:`relative`,flexShrink:0,zIndex:0,verticalAlign:`middle`,"@media print":{colorAdjust:`exact`},variants:[{props:{edge:`start`},style:{marginLeft:-8}},{props:{edge:`end`},style:{marginRight:-8}},{props:{size:`small`},style:{width:40,height:24,padding:7,[`& .${A.thumb}`]:{width:16,height:16},[`& .${A.switchBase}`]:{padding:4,[`&.${A.checked}`]:{transform:`translateX(16px)`}}}}]}),N=n(O,{name:`MuiSwitch`,slot:`SwitchBase`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.switchBase,{[`& .${A.input}`]:t.input},n.color!==`default`&&t[`color${l(n.color)}`]]}})(s(({theme:e})=>({position:`absolute`,top:0,left:0,zIndex:1,color:e.vars?e.vars.palette.Switch.defaultColor:`${e.palette.mode===`light`?e.palette.common.white:e.palette.grey[300]}`,transition:e.transitions.create([`left`,`transform`],{duration:e.transitions.duration.shortest}),[`&.${A.checked}`]:{transform:`translateX(20px)`},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch.defaultDisabledColor:`${e.palette.mode===`light`?e.palette.grey[100]:e.palette.grey[600]}`},[`&.${A.checked} + .${A.track}`]:{opacity:.5},[`&.${A.disabled} + .${A.track}`]:{opacity:e.vars?e.vars.opacity.switchTrackDisabled:`${e.palette.mode===`light`?.12:.2}`},[`& .${A.input}`]:{left:`-100%`,width:`300%`}})),s(({theme:e})=>({"&:hover":{backgroundColor:e.alpha((e.vars||e).palette.action.active,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},variants:[...Object.entries(e.palette).filter(c([`light`])).map(([t])=>({props:{color:t},style:{[`&.${A.checked}`]:{color:(e.vars||e).palette[t].main,"&:hover":{backgroundColor:e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch[`${t}DisabledColor`]:`${e.palette.mode===`light`?e.lighten(e.palette[t].main,.62):e.darken(e.palette[t].main,.55)}`}},[`&.${A.checked} + .${A.track}`]:{backgroundColor:(e.vars||e).palette[t].main}}}))]}))),P=n(`span`,{name:`MuiSwitch`,slot:`Track`})(s(({theme:e})=>({height:`100%`,width:`100%`,borderRadius:14/2,zIndex:-1,transition:e.transitions.create([`opacity`,`background-color`],{duration:e.transitions.duration.shortest}),backgroundColor:e.vars?e.vars.palette.common.onBackground:`${e.palette.mode===`light`?e.palette.common.black:e.palette.common.white}`,opacity:e.vars?e.vars.opacity.switchTrack:`${e.palette.mode===`light`?.38:.3}`}))),F=n(`span`,{name:`MuiSwitch`,slot:`Thumb`})(s(({theme:e})=>({boxShadow:(e.vars||e).shadows[1],backgroundColor:`currentColor`,width:20,height:20,borderRadius:`50%`}))),I=v.forwardRef(function(t,n){let r=o({props:t,name:`MuiSwitch`}),{className:i,color:a=`primary`,edge:s=!1,size:c=`medium`,sx:l,slots:u={},slotProps:d={},...f}=r,m={...r,color:a,edge:s,size:c},h=j(m),g={slots:u,slotProps:d},[_,v]=p(`root`,{className:e(h.root,i),elementType:M,externalForwardedProps:g,ownerState:m,additionalProps:{sx:l}}),[y,b]=p(`thumb`,{className:h.thumb,elementType:F,externalForwardedProps:g,ownerState:m}),x=(0,w.jsx)(y,{...b}),[S,C]=p(`track`,{className:h.track,elementType:P,externalForwardedProps:g,ownerState:m});return(0,w.jsxs)(_,{...v,children:[(0,w.jsx)(N,{type:`checkbox`,icon:x,checkedIcon:x,ref:n,ownerState:m,...f,classes:{...h,root:h.switchBase},slots:{...u.switchBase&&{root:u.switchBase},...u.input&&{input:u.input}},slotProps:{...d.switchBase&&{root:typeof d.switchBase==`function`?d.switchBase(m):d.switchBase},input:{role:`switch`},...d.input&&{input:typeof d.input==`function`?d.input(m):d.input}}}),(0,w.jsx)(S,{...C})]})});function L({enabled:e,onChange:n}){return h?(0,w.jsxs)(g,{sx:{position:`fixed`,bottom:`1rem`,right:`1rem`,zIndex:9999,display:`flex`,alignItems:`center`,gap:`0.5rem`,bgcolor:`background.paper`,border:`1px solid`,borderColor:`divider`,borderRadius:`2rem`,px:`0.75rem`,py:`0.25rem`,boxShadow:3},children:[(0,w.jsx)(t,{variant:`caption`,sx:{userSelect:`none`,fontWeight:600,letterSpacing:`0.05em`},children:`Debug`}),(0,w.jsx)(I,{size:`small`,checked:e,onChange:(e,t)=>n(t)})]}):null}export{L as VitecDebugToggle}; \ No newline at end of file diff --git a/public/_frontend/assets/VitecDebugToggle-C76AUijU.js b/public/_frontend/assets/VitecDebugToggle-C76AUijU.js new file mode 100644 index 0000000..e923825 --- /dev/null +++ b/public/_frontend/assets/VitecDebugToggle-C76AUijU.js @@ -0,0 +1 @@ +import{t as e}from"./useControlled-OB0I4oAK.js";import{B as t,D as n,H as r,J as i,M as a,P as o,Q as s,U as c,W as l,X as u,Y as d,Z as f,j as p,k as m,q as h,r as g,tt as _,z as v}from"./index-7LYai_r-.js";var y=_(s()),b=y.createContext(void 0);function x(){return y.useContext(b)}function S(e){return d(`PrivateSwitchBase`,e)}i(`PrivateSwitchBase`,[`root`,`checked`,`disabled`,`input`,`edgeStart`,`edgeEnd`]);var C=f(),w=e=>{let{classes:n,checked:r,disabled:i,edge:a}=e;return h({root:[`root`,r&&`checked`,i&&`disabled`,a&&`edge${t(a)}`],input:[`input`]},S,n)},T=c(a,{name:`MuiSwitchBase`})({padding:9,borderRadius:`50%`,variants:[{props:{edge:`start`,size:`small`},style:{marginLeft:-3}},{props:({edge:e,ownerState:t})=>e===`start`&&t.size!==`small`,style:{marginLeft:-12}},{props:{edge:`end`,size:`small`},style:{marginRight:-3}},{props:({edge:e,ownerState:t})=>e===`end`&&t.size!==`small`,style:{marginRight:-12}}]}),E=c(`input`,{name:`MuiSwitchBase`,shouldForwardProp:l})({cursor:`inherit`,position:`absolute`,opacity:0,width:`100%`,height:`100%`,top:0,left:0,margin:0,padding:0,zIndex:1}),D=y.forwardRef(function(t,n){let{autoFocus:r,checked:i,checkedIcon:a,defaultChecked:s,disabled:c,disableFocusRipple:l=!1,edge:u=!1,icon:d,id:f,inputProps:p,inputRef:m,name:h,onBlur:g,onChange:_,onFocus:v,readOnly:y,required:b=!1,tabIndex:S,type:D,value:O,slots:k={},slotProps:A={},...j}=t,[M,N]=e({controlled:i,default:!!s,name:`SwitchBase`,state:`checked`}),P=x(),F=e=>{v&&v(e),P&&P.onFocus&&P.onFocus(e)},I=e=>{g&&g(e),P&&P.onBlur&&P.onBlur(e)},L=e=>{if(e.nativeEvent.defaultPrevented)return;let t=e.target.checked;N(t),_&&_(e,t)},R=c;P&&R===void 0&&(R=P.disabled);let z=D===`checkbox`||D===`radio`,B={...t,checked:M,disabled:R,disableFocusRipple:l,edge:u},V=w(B),H={slots:k,slotProps:{input:p,...A}},[U,W]=o(`root`,{ref:n,elementType:T,className:V.root,shouldForwardComponentProp:!0,externalForwardedProps:{...H,component:`span`,...j},getSlotProps:e=>({...e,onFocus:t=>{e.onFocus?.(t),F(t)},onBlur:t=>{e.onBlur?.(t),I(t)}}),ownerState:B,additionalProps:{centerRipple:!0,focusRipple:!l,disabled:R,role:void 0,tabIndex:null}}),[G,K]=o(`input`,{ref:m,elementType:E,className:V.input,externalForwardedProps:H,getSlotProps:e=>({...e,onChange:t=>{e.onChange?.(t),L(t)}}),ownerState:B,additionalProps:{autoFocus:r,checked:i,defaultChecked:s,disabled:R,id:z?f:void 0,name:h,readOnly:y,required:b,tabIndex:S,type:D,...D===`checkbox`&&O===void 0?{}:{value:O}}});return(0,C.jsxs)(U,{...W,children:[(0,C.jsx)(G,{...K}),M?a:d]})});function O(e){return d(`MuiSwitch`,e)}var k=i(`MuiSwitch`,[`root`,`edgeStart`,`edgeEnd`,`switchBase`,`colorPrimary`,`colorSecondary`,`sizeSmall`,`sizeMedium`,`checked`,`disabled`,`input`,`thumb`,`track`]),A=e=>{let{classes:n,edge:r,size:i,color:a,checked:o,disabled:s}=e,c=h({root:[`root`,r&&`edge${t(r)}`,`size${t(i)}`],switchBase:[`switchBase`,`color${t(a)}`,o&&`checked`,s&&`disabled`],thumb:[`thumb`],track:[`track`],input:[`input`]},O,n);return{...n,...c}},j=c(`span`,{name:`MuiSwitch`,slot:`Root`,overridesResolver:(e,n)=>{let{ownerState:r}=e;return[n.root,r.edge&&n[`edge${t(r.edge)}`],n[`size${t(r.size)}`]]}})({display:`inline-flex`,width:58,height:38,overflow:`hidden`,padding:12,boxSizing:`border-box`,position:`relative`,flexShrink:0,zIndex:0,verticalAlign:`middle`,"@media print":{colorAdjust:`exact`},variants:[{props:{edge:`start`},style:{marginLeft:-8}},{props:{edge:`end`},style:{marginRight:-8}},{props:{size:`small`},style:{width:40,height:24,padding:7,[`& .${k.thumb}`]:{width:16,height:16},[`& .${k.switchBase}`]:{padding:4,[`&.${k.checked}`]:{transform:`translateX(16px)`}}}}]}),M=c(D,{name:`MuiSwitch`,slot:`SwitchBase`,overridesResolver:(e,n)=>{let{ownerState:r}=e;return[n.switchBase,{[`& .${k.input}`]:n.input},r.color!==`default`&&n[`color${t(r.color)}`]]}})(v(({theme:e})=>({position:`absolute`,top:0,left:0,zIndex:1,color:e.vars?e.vars.palette.Switch.defaultColor:`${e.palette.mode===`light`?e.palette.common.white:e.palette.grey[300]}`,transition:e.transitions.create([`left`,`transform`],{duration:e.transitions.duration.shortest}),[`&.${k.checked}`]:{transform:`translateX(20px)`},[`&.${k.disabled}`]:{color:e.vars?e.vars.palette.Switch.defaultDisabledColor:`${e.palette.mode===`light`?e.palette.grey[100]:e.palette.grey[600]}`},[`&.${k.checked} + .${k.track}`]:{opacity:.5},[`&.${k.disabled} + .${k.track}`]:{opacity:e.vars?e.vars.opacity.switchTrackDisabled:`${e.palette.mode===`light`?.12:.2}`},[`& .${k.input}`]:{left:`-100%`,width:`300%`}})),v(({theme:e})=>({"&:hover":{backgroundColor:e.alpha((e.vars||e).palette.action.active,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},variants:[...Object.entries(e.palette).filter(p([`light`])).map(([t])=>({props:{color:t},style:{[`&.${k.checked}`]:{color:(e.vars||e).palette[t].main,"&:hover":{backgroundColor:e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},[`&.${k.disabled}`]:{color:e.vars?e.vars.palette.Switch[`${t}DisabledColor`]:`${e.palette.mode===`light`?e.lighten(e.palette[t].main,.62):e.darken(e.palette[t].main,.55)}`}},[`&.${k.checked} + .${k.track}`]:{backgroundColor:(e.vars||e).palette[t].main}}}))]}))),N=c(`span`,{name:`MuiSwitch`,slot:`Track`})(v(({theme:e})=>({height:`100%`,width:`100%`,borderRadius:14/2,zIndex:-1,transition:e.transitions.create([`opacity`,`background-color`],{duration:e.transitions.duration.shortest}),backgroundColor:e.vars?e.vars.palette.common.onBackground:`${e.palette.mode===`light`?e.palette.common.black:e.palette.common.white}`,opacity:e.vars?e.vars.opacity.switchTrack:`${e.palette.mode===`light`?.38:.3}`}))),P=c(`span`,{name:`MuiSwitch`,slot:`Thumb`})(v(({theme:e})=>({boxShadow:(e.vars||e).shadows[1],backgroundColor:`currentColor`,width:20,height:20,borderRadius:`50%`}))),F=y.forwardRef(function(e,t){let n=r({props:e,name:`MuiSwitch`}),{className:i,color:a=`primary`,edge:s=!1,size:c=`medium`,sx:l,slots:d={},slotProps:f={},...p}=n,m={...n,color:a,edge:s,size:c},h=A(m),g={slots:d,slotProps:f},[_,v]=o(`root`,{className:u(h.root,i),elementType:j,externalForwardedProps:g,ownerState:m,additionalProps:{sx:l}}),[y,b]=o(`thumb`,{className:h.thumb,elementType:P,externalForwardedProps:g,ownerState:m}),x=(0,C.jsx)(y,{...b}),[S,w]=o(`track`,{className:h.track,elementType:N,externalForwardedProps:g,ownerState:m});return(0,C.jsxs)(_,{...v,children:[(0,C.jsx)(M,{type:`checkbox`,icon:x,checkedIcon:x,ref:t,ownerState:m,...p,classes:{...h,root:h.switchBase},slots:{...d.switchBase&&{root:d.switchBase},...d.input&&{input:d.input}},slotProps:{...f.switchBase&&{root:typeof f.switchBase==`function`?f.switchBase(m):f.switchBase},input:{role:`switch`},...f.input&&{input:typeof f.input==`function`?f.input(m):f.input}}}),(0,C.jsx)(S,{...w})]})});function I({enabled:e,onChange:t}){return g?(0,C.jsxs)(n,{sx:{position:`fixed`,bottom:`1rem`,right:`1rem`,zIndex:9999,display:`flex`,alignItems:`center`,gap:`0.5rem`,bgcolor:`background.paper`,border:`1px solid`,borderColor:`divider`,borderRadius:`2rem`,px:`0.75rem`,py:`0.25rem`,boxShadow:3},children:[(0,C.jsx)(m,{variant:`caption`,sx:{userSelect:`none`,fontWeight:600,letterSpacing:`0.05em`},children:`Debug`}),(0,C.jsx)(F,{size:`small`,checked:e,onChange:(e,n)=>t(n)})]}):null}export{I as VitecDebugToggle}; \ No newline at end of file diff --git a/public/_frontend/assets/VitecDebugToggle-C8gYxgVq.js b/public/_frontend/assets/VitecDebugToggle-C8gYxgVq.js deleted file mode 100644 index 3fa9794..0000000 --- a/public/_frontend/assets/VitecDebugToggle-C8gYxgVq.js +++ /dev/null @@ -1 +0,0 @@ -import{B as e,E as t,F as n,I as r,K as i,L as a,M as o,N as s,O as c,P as l,R as u,U as d,V as f,j as p,k as m,r as h,w as g,z as _}from"./index-BXbyImyv.js";var v=i(d());function y(e){let{controlled:t,default:n,name:r,state:i=`value`}=e,{current:a}=v.useRef(t!==void 0),[o,s]=v.useState(n);return[a?t:o,v.useCallback(e=>{a||s(e)},[])]}var b=y,x=v.createContext(void 0);function S(){return v.useContext(x)}function C(e){return _(`PrivateSwitchBase`,e)}u(`PrivateSwitchBase`,[`root`,`checked`,`disabled`,`input`,`edgeStart`,`edgeEnd`]);var w=f(),T=e=>{let{classes:t,checked:n,disabled:r,edge:i}=e;return a({root:[`root`,n&&`checked`,r&&`disabled`,i&&`edge${l(i)}`],input:[`input`]},C,t)},E=n(m,{name:`MuiSwitchBase`})({padding:9,borderRadius:`50%`,variants:[{props:{edge:`start`,size:`small`},style:{marginLeft:-3}},{props:({edge:e,ownerState:t})=>e===`start`&&t.size!==`small`,style:{marginLeft:-12}},{props:{edge:`end`,size:`small`},style:{marginRight:-3}},{props:({edge:e,ownerState:t})=>e===`end`&&t.size!==`small`,style:{marginRight:-12}}]}),D=n(`input`,{name:`MuiSwitchBase`,shouldForwardProp:r})({cursor:`inherit`,position:`absolute`,opacity:0,width:`100%`,height:`100%`,top:0,left:0,margin:0,padding:0,zIndex:1}),O=v.forwardRef(function(e,t){let{autoFocus:n,checked:r,checkedIcon:i,defaultChecked:a,disabled:o,disableFocusRipple:s=!1,edge:c=!1,icon:l,id:u,inputProps:d,inputRef:f,name:m,onBlur:h,onChange:g,onFocus:_,readOnly:v,required:y=!1,tabIndex:x,type:C,value:O,slots:k={},slotProps:A={},...j}=e,[M,N]=b({controlled:r,default:!!a,name:`SwitchBase`,state:`checked`}),P=S(),F=e=>{_&&_(e),P&&P.onFocus&&P.onFocus(e)},I=e=>{h&&h(e),P&&P.onBlur&&P.onBlur(e)},L=e=>{if(e.nativeEvent.defaultPrevented)return;let t=e.target.checked;N(t),g&&g(e,t)},R=o;P&&R===void 0&&(R=P.disabled);let z=C===`checkbox`||C===`radio`,B={...e,checked:M,disabled:R,disableFocusRipple:s,edge:c},V=T(B),H={slots:k,slotProps:{input:d,...A}},[U,W]=p(`root`,{ref:t,elementType:E,className:V.root,shouldForwardComponentProp:!0,externalForwardedProps:{...H,component:`span`,...j},getSlotProps:e=>({...e,onFocus:t=>{e.onFocus?.(t),F(t)},onBlur:t=>{e.onBlur?.(t),I(t)}}),ownerState:B,additionalProps:{centerRipple:!0,focusRipple:!s,disabled:R,role:void 0,tabIndex:null}}),[G,K]=p(`input`,{ref:f,elementType:D,className:V.input,externalForwardedProps:H,getSlotProps:e=>({...e,onChange:t=>{e.onChange?.(t),L(t)}}),ownerState:B,additionalProps:{autoFocus:n,checked:r,defaultChecked:a,disabled:R,id:z?u:void 0,name:m,readOnly:v,required:y,tabIndex:x,type:C,...C===`checkbox`&&O===void 0?{}:{value:O}}});return(0,w.jsxs)(U,{...W,children:[(0,w.jsx)(G,{...K}),M?i:l]})});function k(e){return _(`MuiSwitch`,e)}var A=u(`MuiSwitch`,[`root`,`edgeStart`,`edgeEnd`,`switchBase`,`colorPrimary`,`colorSecondary`,`sizeSmall`,`sizeMedium`,`checked`,`disabled`,`input`,`thumb`,`track`]),j=e=>{let{classes:t,edge:n,size:r,color:i,checked:o,disabled:s}=e,c=a({root:[`root`,n&&`edge${l(n)}`,`size${l(r)}`],switchBase:[`switchBase`,`color${l(i)}`,o&&`checked`,s&&`disabled`],thumb:[`thumb`],track:[`track`],input:[`input`]},k,t);return{...t,...c}},M=n(`span`,{name:`MuiSwitch`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.edge&&t[`edge${l(n.edge)}`],t[`size${l(n.size)}`]]}})({display:`inline-flex`,width:58,height:38,overflow:`hidden`,padding:12,boxSizing:`border-box`,position:`relative`,flexShrink:0,zIndex:0,verticalAlign:`middle`,"@media print":{colorAdjust:`exact`},variants:[{props:{edge:`start`},style:{marginLeft:-8}},{props:{edge:`end`},style:{marginRight:-8}},{props:{size:`small`},style:{width:40,height:24,padding:7,[`& .${A.thumb}`]:{width:16,height:16},[`& .${A.switchBase}`]:{padding:4,[`&.${A.checked}`]:{transform:`translateX(16px)`}}}}]}),N=n(O,{name:`MuiSwitch`,slot:`SwitchBase`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.switchBase,{[`& .${A.input}`]:t.input},n.color!==`default`&&t[`color${l(n.color)}`]]}})(s(({theme:e})=>({position:`absolute`,top:0,left:0,zIndex:1,color:e.vars?e.vars.palette.Switch.defaultColor:`${e.palette.mode===`light`?e.palette.common.white:e.palette.grey[300]}`,transition:e.transitions.create([`left`,`transform`],{duration:e.transitions.duration.shortest}),[`&.${A.checked}`]:{transform:`translateX(20px)`},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch.defaultDisabledColor:`${e.palette.mode===`light`?e.palette.grey[100]:e.palette.grey[600]}`},[`&.${A.checked} + .${A.track}`]:{opacity:.5},[`&.${A.disabled} + .${A.track}`]:{opacity:e.vars?e.vars.opacity.switchTrackDisabled:`${e.palette.mode===`light`?.12:.2}`},[`& .${A.input}`]:{left:`-100%`,width:`300%`}})),s(({theme:e})=>({"&:hover":{backgroundColor:e.alpha((e.vars||e).palette.action.active,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},variants:[...Object.entries(e.palette).filter(c([`light`])).map(([t])=>({props:{color:t},style:{[`&.${A.checked}`]:{color:(e.vars||e).palette[t].main,"&:hover":{backgroundColor:e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch[`${t}DisabledColor`]:`${e.palette.mode===`light`?e.lighten(e.palette[t].main,.62):e.darken(e.palette[t].main,.55)}`}},[`&.${A.checked} + .${A.track}`]:{backgroundColor:(e.vars||e).palette[t].main}}}))]}))),P=n(`span`,{name:`MuiSwitch`,slot:`Track`})(s(({theme:e})=>({height:`100%`,width:`100%`,borderRadius:14/2,zIndex:-1,transition:e.transitions.create([`opacity`,`background-color`],{duration:e.transitions.duration.shortest}),backgroundColor:e.vars?e.vars.palette.common.onBackground:`${e.palette.mode===`light`?e.palette.common.black:e.palette.common.white}`,opacity:e.vars?e.vars.opacity.switchTrack:`${e.palette.mode===`light`?.38:.3}`}))),F=n(`span`,{name:`MuiSwitch`,slot:`Thumb`})(s(({theme:e})=>({boxShadow:(e.vars||e).shadows[1],backgroundColor:`currentColor`,width:20,height:20,borderRadius:`50%`}))),I=v.forwardRef(function(t,n){let r=o({props:t,name:`MuiSwitch`}),{className:i,color:a=`primary`,edge:s=!1,size:c=`medium`,sx:l,slots:u={},slotProps:d={},...f}=r,m={...r,color:a,edge:s,size:c},h=j(m),g={slots:u,slotProps:d},[_,v]=p(`root`,{className:e(h.root,i),elementType:M,externalForwardedProps:g,ownerState:m,additionalProps:{sx:l}}),[y,b]=p(`thumb`,{className:h.thumb,elementType:F,externalForwardedProps:g,ownerState:m}),x=(0,w.jsx)(y,{...b}),[S,C]=p(`track`,{className:h.track,elementType:P,externalForwardedProps:g,ownerState:m});return(0,w.jsxs)(_,{...v,children:[(0,w.jsx)(N,{type:`checkbox`,icon:x,checkedIcon:x,ref:n,ownerState:m,...f,classes:{...h,root:h.switchBase},slots:{...u.switchBase&&{root:u.switchBase},...u.input&&{input:u.input}},slotProps:{...d.switchBase&&{root:typeof d.switchBase==`function`?d.switchBase(m):d.switchBase},input:{role:`switch`},...d.input&&{input:typeof d.input==`function`?d.input(m):d.input}}}),(0,w.jsx)(S,{...C})]})});function L({enabled:e,onChange:n}){return h?(0,w.jsxs)(g,{sx:{position:`fixed`,bottom:`1rem`,right:`1rem`,zIndex:9999,display:`flex`,alignItems:`center`,gap:`0.5rem`,bgcolor:`background.paper`,border:`1px solid`,borderColor:`divider`,borderRadius:`2rem`,px:`0.75rem`,py:`0.25rem`,boxShadow:3},children:[(0,w.jsx)(t,{variant:`caption`,sx:{userSelect:`none`,fontWeight:600,letterSpacing:`0.05em`},children:`Debug`}),(0,w.jsx)(I,{size:`small`,checked:e,onChange:(e,t)=>n(t)})]}):null}export{L as VitecDebugToggle}; \ No newline at end of file diff --git a/public/_frontend/assets/VitecDebugToggle-D50ebvSn.js b/public/_frontend/assets/VitecDebugToggle-D50ebvSn.js deleted file mode 100644 index 91ced12..0000000 --- a/public/_frontend/assets/VitecDebugToggle-D50ebvSn.js +++ /dev/null @@ -1 +0,0 @@ -import{B as e,E as t,F as n,I as r,K as i,L as a,M as o,N as s,O as c,P as l,R as u,U as d,V as f,j as p,k as m,r as h,w as g,z as _}from"./index-Cq4vmvLV.js";var v=i(d());function y(e){let{controlled:t,default:n,name:r,state:i=`value`}=e,{current:a}=v.useRef(t!==void 0),[o,s]=v.useState(n);return[a?t:o,v.useCallback(e=>{a||s(e)},[])]}var b=y,x=v.createContext(void 0);function S(){return v.useContext(x)}function C(e){return _(`PrivateSwitchBase`,e)}u(`PrivateSwitchBase`,[`root`,`checked`,`disabled`,`input`,`edgeStart`,`edgeEnd`]);var w=f(),T=e=>{let{classes:t,checked:n,disabled:r,edge:i}=e;return a({root:[`root`,n&&`checked`,r&&`disabled`,i&&`edge${l(i)}`],input:[`input`]},C,t)},E=n(m,{name:`MuiSwitchBase`})({padding:9,borderRadius:`50%`,variants:[{props:{edge:`start`,size:`small`},style:{marginLeft:-3}},{props:({edge:e,ownerState:t})=>e===`start`&&t.size!==`small`,style:{marginLeft:-12}},{props:{edge:`end`,size:`small`},style:{marginRight:-3}},{props:({edge:e,ownerState:t})=>e===`end`&&t.size!==`small`,style:{marginRight:-12}}]}),D=n(`input`,{name:`MuiSwitchBase`,shouldForwardProp:r})({cursor:`inherit`,position:`absolute`,opacity:0,width:`100%`,height:`100%`,top:0,left:0,margin:0,padding:0,zIndex:1}),O=v.forwardRef(function(e,t){let{autoFocus:n,checked:r,checkedIcon:i,defaultChecked:a,disabled:o,disableFocusRipple:s=!1,edge:c=!1,icon:l,id:u,inputProps:d,inputRef:f,name:m,onBlur:h,onChange:g,onFocus:_,readOnly:v,required:y=!1,tabIndex:x,type:C,value:O,slots:k={},slotProps:A={},...j}=e,[M,N]=b({controlled:r,default:!!a,name:`SwitchBase`,state:`checked`}),P=S(),F=e=>{_&&_(e),P&&P.onFocus&&P.onFocus(e)},I=e=>{h&&h(e),P&&P.onBlur&&P.onBlur(e)},L=e=>{if(e.nativeEvent.defaultPrevented)return;let t=e.target.checked;N(t),g&&g(e,t)},R=o;P&&R===void 0&&(R=P.disabled);let z=C===`checkbox`||C===`radio`,B={...e,checked:M,disabled:R,disableFocusRipple:s,edge:c},V=T(B),H={slots:k,slotProps:{input:d,...A}},[U,W]=p(`root`,{ref:t,elementType:E,className:V.root,shouldForwardComponentProp:!0,externalForwardedProps:{...H,component:`span`,...j},getSlotProps:e=>({...e,onFocus:t=>{e.onFocus?.(t),F(t)},onBlur:t=>{e.onBlur?.(t),I(t)}}),ownerState:B,additionalProps:{centerRipple:!0,focusRipple:!s,disabled:R,role:void 0,tabIndex:null}}),[G,K]=p(`input`,{ref:f,elementType:D,className:V.input,externalForwardedProps:H,getSlotProps:e=>({...e,onChange:t=>{e.onChange?.(t),L(t)}}),ownerState:B,additionalProps:{autoFocus:n,checked:r,defaultChecked:a,disabled:R,id:z?u:void 0,name:m,readOnly:v,required:y,tabIndex:x,type:C,...C===`checkbox`&&O===void 0?{}:{value:O}}});return(0,w.jsxs)(U,{...W,children:[(0,w.jsx)(G,{...K}),M?i:l]})});function k(e){return _(`MuiSwitch`,e)}var A=u(`MuiSwitch`,[`root`,`edgeStart`,`edgeEnd`,`switchBase`,`colorPrimary`,`colorSecondary`,`sizeSmall`,`sizeMedium`,`checked`,`disabled`,`input`,`thumb`,`track`]),j=e=>{let{classes:t,edge:n,size:r,color:i,checked:o,disabled:s}=e,c=a({root:[`root`,n&&`edge${l(n)}`,`size${l(r)}`],switchBase:[`switchBase`,`color${l(i)}`,o&&`checked`,s&&`disabled`],thumb:[`thumb`],track:[`track`],input:[`input`]},k,t);return{...t,...c}},M=n(`span`,{name:`MuiSwitch`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.edge&&t[`edge${l(n.edge)}`],t[`size${l(n.size)}`]]}})({display:`inline-flex`,width:58,height:38,overflow:`hidden`,padding:12,boxSizing:`border-box`,position:`relative`,flexShrink:0,zIndex:0,verticalAlign:`middle`,"@media print":{colorAdjust:`exact`},variants:[{props:{edge:`start`},style:{marginLeft:-8}},{props:{edge:`end`},style:{marginRight:-8}},{props:{size:`small`},style:{width:40,height:24,padding:7,[`& .${A.thumb}`]:{width:16,height:16},[`& .${A.switchBase}`]:{padding:4,[`&.${A.checked}`]:{transform:`translateX(16px)`}}}}]}),N=n(O,{name:`MuiSwitch`,slot:`SwitchBase`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.switchBase,{[`& .${A.input}`]:t.input},n.color!==`default`&&t[`color${l(n.color)}`]]}})(s(({theme:e})=>({position:`absolute`,top:0,left:0,zIndex:1,color:e.vars?e.vars.palette.Switch.defaultColor:`${e.palette.mode===`light`?e.palette.common.white:e.palette.grey[300]}`,transition:e.transitions.create([`left`,`transform`],{duration:e.transitions.duration.shortest}),[`&.${A.checked}`]:{transform:`translateX(20px)`},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch.defaultDisabledColor:`${e.palette.mode===`light`?e.palette.grey[100]:e.palette.grey[600]}`},[`&.${A.checked} + .${A.track}`]:{opacity:.5},[`&.${A.disabled} + .${A.track}`]:{opacity:e.vars?e.vars.opacity.switchTrackDisabled:`${e.palette.mode===`light`?.12:.2}`},[`& .${A.input}`]:{left:`-100%`,width:`300%`}})),s(({theme:e})=>({"&:hover":{backgroundColor:e.alpha((e.vars||e).palette.action.active,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},variants:[...Object.entries(e.palette).filter(c([`light`])).map(([t])=>({props:{color:t},style:{[`&.${A.checked}`]:{color:(e.vars||e).palette[t].main,"&:hover":{backgroundColor:e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:`transparent`}},[`&.${A.disabled}`]:{color:e.vars?e.vars.palette.Switch[`${t}DisabledColor`]:`${e.palette.mode===`light`?e.lighten(e.palette[t].main,.62):e.darken(e.palette[t].main,.55)}`}},[`&.${A.checked} + .${A.track}`]:{backgroundColor:(e.vars||e).palette[t].main}}}))]}))),P=n(`span`,{name:`MuiSwitch`,slot:`Track`})(s(({theme:e})=>({height:`100%`,width:`100%`,borderRadius:14/2,zIndex:-1,transition:e.transitions.create([`opacity`,`background-color`],{duration:e.transitions.duration.shortest}),backgroundColor:e.vars?e.vars.palette.common.onBackground:`${e.palette.mode===`light`?e.palette.common.black:e.palette.common.white}`,opacity:e.vars?e.vars.opacity.switchTrack:`${e.palette.mode===`light`?.38:.3}`}))),F=n(`span`,{name:`MuiSwitch`,slot:`Thumb`})(s(({theme:e})=>({boxShadow:(e.vars||e).shadows[1],backgroundColor:`currentColor`,width:20,height:20,borderRadius:`50%`}))),I=v.forwardRef(function(t,n){let r=o({props:t,name:`MuiSwitch`}),{className:i,color:a=`primary`,edge:s=!1,size:c=`medium`,sx:l,slots:u={},slotProps:d={},...f}=r,m={...r,color:a,edge:s,size:c},h=j(m),g={slots:u,slotProps:d},[_,v]=p(`root`,{className:e(h.root,i),elementType:M,externalForwardedProps:g,ownerState:m,additionalProps:{sx:l}}),[y,b]=p(`thumb`,{className:h.thumb,elementType:F,externalForwardedProps:g,ownerState:m}),x=(0,w.jsx)(y,{...b}),[S,C]=p(`track`,{className:h.track,elementType:P,externalForwardedProps:g,ownerState:m});return(0,w.jsxs)(_,{...v,children:[(0,w.jsx)(N,{type:`checkbox`,icon:x,checkedIcon:x,ref:n,ownerState:m,...f,classes:{...h,root:h.switchBase},slots:{...u.switchBase&&{root:u.switchBase},...u.input&&{input:u.input}},slotProps:{...d.switchBase&&{root:typeof d.switchBase==`function`?d.switchBase(m):d.switchBase},input:{role:`switch`},...d.input&&{input:typeof d.input==`function`?d.input(m):d.input}}}),(0,w.jsx)(S,{...C})]})});function L({enabled:e,onChange:n}){return h?(0,w.jsxs)(g,{sx:{position:`fixed`,bottom:`1rem`,right:`1rem`,zIndex:9999,display:`flex`,alignItems:`center`,gap:`0.5rem`,bgcolor:`background.paper`,border:`1px solid`,borderColor:`divider`,borderRadius:`2rem`,px:`0.75rem`,py:`0.25rem`,boxShadow:3},children:[(0,w.jsx)(t,{variant:`caption`,sx:{userSelect:`none`,fontWeight:600,letterSpacing:`0.05em`},children:`Debug`}),(0,w.jsx)(I,{size:`small`,checked:e,onChange:(e,t)=>n(t)})]}):null}export{L as VitecDebugToggle}; \ No newline at end of file diff --git a/public/_frontend/assets/fa-brands-400-BK5CuonO.woff2 b/public/_frontend/assets/fa-brands-400-BK5CuonO.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..4aa6dea7fd893d4831fdca0cb8033b4c81decc09 GIT binary patch literal 114412 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

tTU14G$|uD>V+&FK^WM!;W4!2yO$p2;>}VFP(? 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 literal 0 HcmV?d00001 diff --git a/public/_frontend/assets/fa-solid-900-Iz_TytpP.woff2 b/public/_frontend/assets/fa-solid-900-Iz_TytpP.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..d7e38a2956dcc8340603416d4bdbd000a8e73900 GIT binary patch literal 119156 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

U+sF;mB=o`u{Kv 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%0Dubs~75obR(Bt zB!e+lZ!m$#>`0U{McNvfp!9V`b{+%cGNI}alCG}j<1oJcI6`8}x-Vs(KX|^X zF7I`9Q1ikde>y0IMG*w!-d6?jQYhKtKm*};R^)XM#ke=aHS(m^Uoa_6G$IRIK`o?7 zhVeqn^Y9RA3q8+n@{kGe8H=Y#i_UP%P&f;MSdx=Kf)V>|{+R;3f*Qq!sczPbTle8) z1GUVU_gVzmni%{Or`byU15jF)U%*rO-$?=BUE>hDb6#56@X(~hVoG<62$bn(@KC3O zZ7x27Sob57^ENPOtdR{rSXF}DW?pWqE`vsNd=pY6|4(s8cO(Z72UjhD(xJexi.map(i=>d[i]); +var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),l=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){if(typeof require<`u`)return require.apply(this,arguments);throw Error('Calling `require` for "'+e+"\" in an environment that doesn't expose the `require` function.")});(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var u=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function ee(e,t){return E(e.type,t,e.props)}function D(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function O(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var te=/\/+/g;function k(e,t){return typeof e==`object`&&e&&e.key!=null?O(``+e.key):t.toString(36)}function A(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function j(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,j(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+k(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(te,`$&/`)+`/`),j(o,r,i,``,function(e){return e})):o!=null&&(D(o)&&(o=ee(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(te,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=u()})),f=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,D());else{var t=n(l);t!==null&&k(x,t.startTime-e)}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&k(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?D():S=!1}}}var D;if(typeof y==`function`)D=function(){y(ee)};else if(typeof MessageChannel<`u`){var O=new MessageChannel,te=O.port2;O.port1.onmessage=ee,D=function(){te.postMessage(null)}}else D=function(){_(ee,0)};function k(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,k(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,D()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),p=o(((e,t)=>{t.exports=f()})),m=o((e=>{var t=d();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=m()})),g=o((e=>{var t=p(),n=d(),r=h();function i(e){var t=`https://react.dev/errors/`+e;if(1ae||(e.current=ie[ae],ie[ae]=null,ae--)}function F(e,t){ae++,ie[ae]=e.current,e.current=t}var ce=oe(null),le=oe(null),ue=oe(null),de=oe(null);function fe(e,t){switch(F(ue,t),F(le,e),F(ce,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Ud(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Ud(t),e=Wd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}se(ce),F(ce,e)}function pe(){se(ce),se(le),se(ue)}function me(e){e.memoizedState!==null&&F(de,e);var t=ce.current,n=Wd(t,e.type);t!==n&&(F(le,e),F(ce,n))}function he(e){le.current===e&&(se(ce),se(le)),de.current===e&&(se(de),$f._currentValue=re)}var ge,_e;function ve(e){if(ge===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);ge=t&&t[1]||``,_e=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{ye=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?ve(n):``}function xe(e,t){switch(e.tag){case 26:case 27:case 5:return ve(e.type);case 16:return ve(`Lazy`);case 13:return e.child!==t&&t!==null?ve(`Suspense Fallback`):ve(`Suspense`);case 19:return ve(`SuspenseList`);case 0:case 15:return be(e.type,!1);case 11:return be(e.type.render,!1);case 1:return be(e.type,!0);case 31:return ve(`Activity`);default:return``}}function Se(e){try{var t=``,n=null;do t+=xe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var Ce=Object.prototype.hasOwnProperty,we=t.unstable_scheduleCallback,Te=t.unstable_cancelCallback,Ee=t.unstable_shouldYield,De=t.unstable_requestPaint,Oe=t.unstable_now,ke=t.unstable_getCurrentPriorityLevel,Ae=t.unstable_ImmediatePriority,je=t.unstable_UserBlockingPriority,Me=t.unstable_NormalPriority,Ne=t.unstable_LowPriority,Pe=t.unstable_IdlePriority,Fe=t.log,Ie=t.unstable_setDisableYieldValue,Le=null,Re=null;function ze(e){if(typeof Fe==`function`&&Ie(e),Re&&typeof Re.setStrictMode==`function`)try{Re.setStrictMode(Le,e)}catch{}}var Be=Math.clz32?Math.clz32:Ue,Ve=Math.log,He=Math.LN2;function Ue(e){return e>>>=0,e===0?32:31-(Ve(e)/He|0)|0}var We=256,Ge=262144,Ke=4194304;function qe(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Je(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=qe(n))):i=qe(o):i=qe(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=qe(n))):i=qe(o)):i=qe(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Ye(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Xe(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Ze(){var e=Ke;return Ke<<=1,!(Ke&62914560)&&(Ke=4194304),e}function Qe(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function $e(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function et(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),pn=!1;if(fn)try{var mn={};Object.defineProperty(mn,`passive`,{get:function(){pn=!0}}),window.addEventListener(`test`,mn,mn),window.removeEventListener(`test`,mn,mn)}catch{pn=!1}var hn=null,gn=null,_n=null;function vn(){if(_n)return _n;var e,t=gn,n=t.length,r,i=`value`in hn?hn.value:hn.textContent,a=i.length;for(e=0;e=Xn),$n=` `,er=!1;function tr(e,t){switch(e){case`keyup`:return Jn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function nr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var rr=!1;function ir(e,t){switch(e){case`compositionend`:return nr(t);case`keypress`:return t.which===32?(er=!0,$n):null;case`textInput`:return e=t.data,e===$n&&er?null:e;default:return null}}function ar(e,t){if(rr)return e===`compositionend`||!Yn&&tr(e,t)?(e=vn(),_n=gn=hn=null,rr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Dr(n)}}function kr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?kr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ar(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=zt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=zt(e.document)}return t}function jr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Mr=fn&&`documentMode`in document&&11>=document.documentMode,Nr=null,Pr=null,Fr=null,Ir=!1;function Lr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Ir||Nr==null||Nr!==zt(r)||(r=Nr,`selectionStart`in r&&jr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Fr&&Er(Fr,r)||(Fr=r,r=Dd(Pr,`onSelect`),0>=o,i-=o,Di=1<<32-Be(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),R&&ki(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),R&&ki(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return R&&ki(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),R&&ki(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===y&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case _:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===y){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===D&&ka(l)===r.type){n(e,r.sibling),c=a(r,o.props),Ia(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===y?(c=mi(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=pi(o.type,o.key,o.props,null,e.mode,c),Ia(c,o),c.return=e,e=c)}return s(e);case v:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=_i(o,e.mode,c),c.return=e,e=c}return s(e);case D:return o=ka(o),b(e,r,o,c)}if(M(o))return h(e,r,o,c);if(A(o)){if(l=A(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,Fa(o),c);if(o.$$typeof===C)return b(e,r,ra(e,o),c);La(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=hi(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Pa=0;var i=b(e,t,n,r);return Na=null,i}catch(t){if(t===Ca||t===Ta)throw t;var a=L(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var za=Ra(!0),Ba=Ra(!1),Va=!1;function Ha(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ua(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Wa(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Ga(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=si(e),oi(e,null,n),t}return ri(e,r,t,n),si(e)}function Ka(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,nt(e,n)}}function qa(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Ja=!1;function Ya(){if(Ja){var e=ma;if(e!==null)throw e}}function Xa(e,t,n,r){Ja=!1;var i=e.updateQueue;Va=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===pa&&(Ja=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,f);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,f=typeof h==`function`?h.call(_,d,f):h,f==null)break a;d=m({},d,f);break a;case 2:Va=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Jl|=o,e.lanes=o,e.memoizedState=d}}function Za(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Qa(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=N.T,s={};N.T=s,Ls(e,!1,t,n);try{var c=i(),l=N.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Is(e,t,_a(c,r),gu(e)):Is(e,t,r,gu(e))}catch(n){Is(e,t,{then:function(){},status:`rejected`,reason:n},gu())}finally{P.p=a,o!==null&&s.types!==null&&(o.types=s.types),N.T=o}}function Es(){}function Ds(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=Os(e).queue;Ts(e,a,t,re,n===null?Es:function(){return ks(e),n(r)})}function Os(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:re,baseState:re,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ro,lastRenderedState:re},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ro,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ks(e){var t=Os(e);t.next===null&&(t=e.alternate.memoizedState),Is(e,t.next.queue,{},gu())}function As(){return na($f)}function js(){return No().memoizedState}function Ms(){return No().memoizedState}function Ns(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=gu();e=Wa(n);var r=Ga(t,e,n);r!==null&&(vu(r,t,n),Ka(r,t,n)),t={cache:la()},e.payload=t;return}t=t.return}}function Ps(e,t,n){var r=gu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Rs(e)?zs(t,n):(n=ii(e,t,n,r),n!==null&&(vu(n,e,r),Bs(n,t,r)))}function Fs(e,t,n){Is(e,t,n,gu())}function Is(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Rs(e))zs(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Tr(s,o))return ri(e,t,i,0),G===null&&ni(),!1}catch{}if(n=ii(e,t,i,r),n!==null)return vu(n,e,r),Bs(n,t,r),!0}return!1}function Ls(e,t,n,r){if(r={lane:2,revertLane:pd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Rs(e)){if(t)throw Error(i(479))}else t=ii(e,n,r,2),t!==null&&vu(t,e,2)}function Rs(e){var t=e.alternate;return e===B||t!==null&&t===B}function zs(e,t){_o=go=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Bs(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,nt(e,n)}}var Vs={readContext:na,use:Io,useCallback:Co,useContext:Co,useEffect:Co,useImperativeHandle:Co,useLayoutEffect:Co,useInsertionEffect:Co,useMemo:Co,useReducer:Co,useRef:Co,useState:Co,useDebugValue:Co,useDeferredValue:Co,useTransition:Co,useSyncExternalStore:Co,useId:Co,useHostTransitionStatus:Co,useFormState:Co,useActionState:Co,useOptimistic:Co,useMemoCache:Co,useCacheRefresh:Co};Vs.useEffectEvent=Co;var Hs={readContext:na,use:Io,useCallback:function(e,t){return Mo().memoizedState=[e,t===void 0?null:t],e},useContext:na,useEffect:fs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),us(4194308,4,vs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return us(4194308,4,e,t)},useInsertionEffect:function(e,t){us(4,2,e,t)},useMemo:function(e,t){var n=Mo();t=t===void 0?null:t;var r=e();if(vo){ze(!0);try{e()}finally{ze(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Mo();if(n!==void 0){var i=n(t);if(vo){ze(!0);try{n(t)}finally{ze(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Ps.bind(null,B,e),[r.memoizedState,e]},useRef:function(e){var t=Mo();return e={current:e},t.memoizedState=e},useState:function(e){e=Jo(e);var t=e.queue,n=Fs.bind(null,B,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:bs,useDeferredValue:function(e,t){return Cs(Mo(),e,t)},useTransition:function(){var e=Jo(!1);return e=Ts.bind(null,B,e.queue,!0,!1),Mo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=B,a=Mo();if(R){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),G===null)throw Error(i(349));q&127||Uo(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,fs(Go.bind(null,r,o,e),[e]),r.flags|=2048,cs(9,{destroy:void 0},Wo.bind(null,r,o,n,t),null),n},useId:function(){var e=Mo(),t=G.identifierPrefix;if(R){var n=Oi,r=Di;n=(r&~(1<<32-Be(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=yo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[lt]=t,o[ut]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Id(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Fc(t)}}return Rc(t),H(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Fc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=ue.current,Hi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Pi,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[lt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Nd(e.nodeValue,n)),e||zi(t,!0)}else e=Hd(e).createTextNode(r),e[lt]=t,t.stateNode=e}return Rc(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Hi(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[lt]=t}else Ui(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Rc(t),e=!1}else n=Wi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(lo(t),t):(lo(t),null);if(t.flags&128)throw Error(i(558))}return Rc(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Hi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[lt]=t}else Ui(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Rc(t),a=!1}else a=Wi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(lo(t),t):(lo(t),null)}return lo(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),U(t,t.updateQueue),Rc(t),null);case 4:return pe(),e===null&&Cd(t.stateNode.containerInfo),Rc(t),null;case 10:return Xi(t.type),Rc(t),null;case 19:if(se(uo),r=t.memoizedState,r===null)return Rc(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)Lc(r,!1);else{if(ql!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=fo(e),o!==null){for(t.flags|=128,Lc(r,!1),e=o.updateQueue,t.updateQueue=e,U(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)fi(n,e),n=n.sibling;return F(uo,uo.current&1|2),R&&ki(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Oe()>iu&&(t.flags|=128,a=!0,Lc(r,!1),t.lanes=4194304)}else{if(!a)if(e=fo(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,U(t,e),Lc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!R)return Rc(t),null}else 2*Oe()-r.renderingStartTime>iu&&n!==536870912&&(t.flags|=128,a=!0,Lc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Rc(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Oe(),e.sibling=null,n=uo.current,F(uo,a?n&1|2:n&1),R&&ki(t,r.treeForkCount),e);case 22:case 23:return lo(t),no(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Rc(t),t.subtreeFlags&6&&(t.flags|=8192)):Rc(t),n=t.updateQueue,n!==null&&U(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&se(ya),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Xi(ca),Rc(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Bc(e,t){switch(Mi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Xi(ca),pe(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return he(t),null;case 31:if(t.memoizedState!==null){if(lo(t),t.alternate===null)throw Error(i(340));Ui()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(lo(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Ui()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return se(uo),null;case 4:return pe(),null;case 10:return Xi(t.type),null;case 22:case 23:return lo(t),no(),e!==null&&se(ya),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Xi(ca),null;case 25:return null;default:return null}}function Vc(e,t){switch(Mi(t),t.tag){case 3:Xi(ca),pe();break;case 26:case 27:case 5:he(t);break;case 4:pe();break;case 31:t.memoizedState!==null&&lo(t);break;case 13:lo(t);break;case 19:se(uo);break;case 10:Xi(t.type);break;case 22:case 23:lo(t),no(),e!==null&&se(ya);break;case 24:Xi(ca)}}function Hc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){J(t,t.return,e)}}function Uc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){J(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){J(t,t.return,e)}}function Wc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Qa(t,n)}catch(t){J(e,e.return,t)}}}function Gc(e,t,n){n.props=Ys(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){J(e,t,n)}}function Kc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){J(e,t,n)}}function qc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){J(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){J(e,t,n)}else n.current=null}function Jc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){J(e,e.return,t)}}function Yc(e,t,n){try{var r=e.stateNode;Ld(r,e.type,n,t),r[ut]=t}catch(t){J(e,e.return,t)}}function Xc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Qd(e.type)||e.tag===4}function Zc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Xc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Qd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Qc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=nn));else if(r!==4&&(r===27&&Qd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(Qc(e,t,n),e=e.sibling;e!==null;)Qc(e,t,n),e=e.sibling}function $c(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Qd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for($c(e,t,n),e=e.sibling;e!==null;)$c(e,t,n),e=e.sibling}function el(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Id(t,r,n),t[lt]=e,t[ut]=n}catch(t){J(e,e.return,t)}}var tl=!1,nl=!1,rl=!1,il=typeof WeakSet==`function`?WeakSet:Set,al=null;function ol(e,t){if(e=e.containerInfo,Bd=cp,e=Ar(e),jr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(Vd={focusedElem:e,selectionRange:n},cp=!1,al=t;al!==null;)if(t=al,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,al=e;else for(;al!==null;){switch(t=al,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Id(o,r,n),o[lt]=e,St(o),r=o;break a;case`link`:var s=Hf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=Or(s,h),v=Or(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,N.T=null,n=fu,fu=null;var o=cu,s=uu;if(su=0,lu=cu=null,uu=0,W&6)throw Error(i(331));var c=W;if(W|=4,Il(o.current),Ol(o,o.current,s,n),W=c,Y(0,!1),Re&&typeof Re.onPostCommitFiberRoot==`function`)try{Re.onPostCommitFiberRoot(Le,o)}catch{}return!0}finally{P.p=a,N.T=r,Wu(e,t)}}function qu(e,t,n){t=yi(n,t),t=ec(e.stateNode,t,2),e=Ga(e,t,2),e!==null&&($e(e,2),od(e))}function J(e,t,n){if(e.tag===3)qu(e,e,n);else for(;t!==null;){if(t.tag===3){qu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(ou===null||!ou.has(r))){e=yi(n,e),n=tc(2),r=Ga(t,n,2),r!==null&&(nc(n,r,t,e),$e(r,2),od(r));break}}t=t.return}}function Ju(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Bl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Gl=!0,i.add(n),e=Yu.bind(null,e,t,n),t.then(e,e))}function Yu(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(ql===4||ql===3&&(q&62914560)===q&&300>Oe()-nu?!(W&2)&&Tu(e,0):Xl|=n,Ql===q&&(Ql=0)),od(e)}function Xu(e,t){t===0&&(t=Ze()),e=ai(e,t),e!==null&&($e(e,t),od(e))}function Zu(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Xu(e,n)}function Qu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),Xu(e,n)}function $u(e,t){return we(e,t)}var ed=null,td=null,nd=!1,rd=!1,id=!1,ad=0;function od(e){e!==td&&e.next===null&&(td===null?ed=td=e:td=td.next=e),rd=!0,nd||(nd=!0,fd())}function Y(e,t){if(!id&&rd){id=!0;do for(var n=!1,r=ed;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Be(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,dd(r,a))}else a=q,a=Je(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Ye(r,a)||(n=!0,dd(r,a));r=r.next}while(n);id=!1}}function sd(){cd()}function cd(){rd=nd=!1;var e=0;ad!==0&&qd()&&(e=ad);for(var t=Oe(),n=null,r=ed;r!==null;){var i=r.next,a=ld(r,t);a===0?(r.next=null,n===null?ed=i:n.next=i,i===null&&(td=n)):(n=r,(e!==0||a&3)&&(rd=!0)),r=i}su!==0&&su!==5||Y(e,!1),ad!==0&&(ad=0)}function ld(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Rd(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function Sf(e,t,n){var r=xf;if(r&&typeof t==`string`&&t){var i=Vt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),gf.has(i)||(gf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Id(t,`link`,e),St(t),r.head.appendChild(t)))}}function Cf(e){vf.D(e),Sf(`dns-prefetch`,e,null)}function wf(e,t){vf.C(e,t),Sf(`preconnect`,e,t)}function Tf(e,t,n){vf.L(e,t,n);var r=xf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Vt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Vt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Vt(n.imageSizes)+`"]`)):i+=`[href="`+Vt(e)+`"]`;var a=i;switch(t){case`style`:a=jf(e);break;case`script`:a=Ff(e)}hf.has(a)||(e=m({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),hf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Mf(a))||t===`script`&&r.querySelector(If(a))||(t=r.createElement(`link`),Id(t,`link`,e),St(t),r.head.appendChild(t)))}}function Ef(e,t){vf.m(e,t);var n=xf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Vt(r)+`"][href="`+Vt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Ff(e)}if(!hf.has(a)&&(e=m({rel:`modulepreload`,href:e},t),hf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(If(a)))return}r=n.createElement(`link`),Id(r,`link`,e),St(r),n.head.appendChild(r)}}}function Df(e,t,n){vf.S(e,t,n);var r=xf;if(r&&e){var i=xt(r).hoistableStyles,a=jf(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Mf(a)))s.loading=5;else{e=m({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=hf.get(a))&&zf(e,n);var c=o=r.createElement(`link`);St(c),Id(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Rf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Of(e,t){vf.X(e,t);var n=xf;if(n&&e){var r=xt(n).hoistableScripts,i=Ff(e),a=r.get(i);a||(a=n.querySelector(If(i)),a||(e=m({src:e,async:!0},t),(t=hf.get(i))&&Bf(e,t),a=n.createElement(`script`),St(a),Id(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t){vf.M(e,t);var n=xf;if(n&&e){var r=xt(n).hoistableScripts,i=Ff(e),a=r.get(i);a||(a=n.querySelector(If(i)),a||(e=m({src:e,async:!0,type:`module`},t),(t=hf.get(i))&&Bf(e,t),a=n.createElement(`script`),St(a),Id(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Af(e,t,n,r){var a=(a=ue.current)?_f(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=jf(n.href),n=xt(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=jf(n.href);var o=xt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Mf(e)))&&!o._p&&(s.instance=o,s.state.loading=5),hf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},hf.set(e,n),o||Pf(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Ff(n),n=xt(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function jf(e){return`href="`+Vt(e)+`"`}function Mf(e){return`link[rel="stylesheet"][`+e+`]`}function Nf(e){return m({},e,{"data-precedence":e.precedence,precedence:null})}function Pf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Id(t,`link`,n),St(t),e.head.appendChild(t))}function Ff(e){return`[src="`+Vt(e)+`"]`}function If(e){return`script[async]`+e}function Lf(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Vt(n.href)+`"]`);if(r)return t.instance=r,St(r),r;var a=m({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),St(r),Id(r,`style`,a),Rf(r,n.precedence,e),t.instance=r;case`stylesheet`:a=jf(n.href);var o=e.querySelector(Mf(a));if(o)return t.state.loading|=4,t.instance=o,St(o),o;r=Nf(n),(a=hf.get(a))&&zf(r,a),o=(e.ownerDocument||e).createElement(`link`),St(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Id(o,`link`,r),t.state.loading|=4,Rf(o,n.precedence,e),t.instance=o;case`script`:return o=Ff(n.src),(a=e.querySelector(If(o)))?(t.instance=a,St(a),a):(r=n,(a=hf.get(o))&&(r=m({},n),Bf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),St(a),Id(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Rf(r,n.precedence,e));return t.instance}function Rf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Wf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Gf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Kf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=jf(r.href),a=t.querySelector(Mf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Yf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,St(a);return}a=t.ownerDocument||t,r=Nf(r),(i=hf.get(i))&&zf(r,i),a=a.createElement(`link`),St(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Id(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Yf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var qf=0;function Jf(e,t){return e.stylesheets&&e.count===0&&Zf(e,e.stylesheets),0qf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Yf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Zf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Xf=null;function Zf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Xf=new Map,t.forEach(Qf,e),Xf=null,Yf.call(e))}function Qf(e,t){if(!(t.state.loading&4)){var n=Xf.get(e);if(n)var r=n.get(null);else{n=new Map,Xf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=g()})),v=o(((e,t)=>{var n=typeof Element<`u`,r=typeof Map==`function`,i=typeof Set==`function`,a=typeof ArrayBuffer==`function`&&!!ArrayBuffer.isView;function o(e,t){if(e===t)return!0;if(e&&t&&typeof e==`object`&&typeof t==`object`){if(e.constructor!==t.constructor)return!1;var s,c,l;if(Array.isArray(e)){if(s=e.length,s!=t.length)return!1;for(c=s;c--!==0;)if(!o(e[c],t[c]))return!1;return!0}var u;if(r&&e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(u=e.entries();!(c=u.next()).done;)if(!t.has(c.value[0]))return!1;for(u=e.entries();!(c=u.next()).done;)if(!o(c.value[1],t.get(c.value[0])))return!1;return!0}if(i&&e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(u=e.entries();!(c=u.next()).done;)if(!t.has(c.value[0]))return!1;return!0}if(a&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(t)){if(s=e.length,s!=t.length)return!1;for(c=s;c--!==0;)if(e[c]!==t[c])return!1;return!0}if(e.constructor===RegExp)return e.source===t.source&&e.flags===t.flags;if(e.valueOf!==Object.prototype.valueOf&&typeof e.valueOf==`function`&&typeof t.valueOf==`function`)return e.valueOf()===t.valueOf();if(e.toString!==Object.prototype.toString&&typeof e.toString==`function`&&typeof t.toString==`function`)return e.toString()===t.toString();if(l=Object.keys(e),s=l.length,s!==Object.keys(t).length)return!1;for(c=s;c--!==0;)if(!Object.prototype.hasOwnProperty.call(t,l[c]))return!1;if(n&&e instanceof Element)return!1;for(c=s;c--!==0;)if(!((l[c]===`_owner`||l[c]===`__v`||l[c]===`__o`)&&e.$$typeof)&&!o(e[l[c]],t[l[c]]))return!1;return!0}return e!==e&&t!==t}t.exports=function(e,t){try{return o(e,t)}catch(e){if((e.message||``).match(/stack|recursion/i))return console.warn(`react-fast-compare cannot handle circular refs`),!1;throw e}}})),y=o(((e,t)=>{t.exports=function(e,t,n,r,i,a,o,s){if(!e){var c;if(t===void 0)c=Error(`Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.`);else{var l=[n,r,i,a,o,s],u=0;c=Error(t.replace(/%s/g,function(){return l[u++]})),c.name=`Invariant Violation`}throw c.framesToPop=1,c}}})),b=o(((e,t)=>{t.exports=function(e,t,n,r){var i=n?n.call(r,e,t):void 0;if(i!==void 0)return!!i;if(e===t)return!0;if(typeof e!=`object`||!e||typeof t!=`object`||!t)return!1;var a=Object.keys(e),o=Object.keys(t);if(a.length!==o.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),c=0;c(e.BASE=`base`,e.BODY=`body`,e.HEAD=`head`,e.HTML=`html`,e.LINK=`link`,e.META=`meta`,e.NOSCRIPT=`noscript`,e.SCRIPT=`script`,e.STYLE=`style`,e.TITLE=`title`,e.FRAGMENT=`Symbol(react.fragment)`,e))(E||{}),ee={link:{rel:[`amphtml`,`canonical`,`alternate`]},script:{type:[`application/ld+json`]},meta:{charset:``,name:[`generator`,`robots`,`description`],property:[`og:type`,`og:title`,`og:url`,`og:image`,`og:image:alt`,`og:description`,`twitter:url`,`twitter:title`,`twitter:description`,`twitter:image`,`twitter:image:alt`,`twitter:card`,`twitter:site`]}},D=Object.values(E),O={accesskey:`accessKey`,charset:`charSet`,class:`className`,contenteditable:`contentEditable`,contextmenu:`contextMenu`,"http-equiv":`httpEquiv`,itemprop:`itemProp`,tabindex:`tabIndex`},te=Object.entries(O).reduce((e,[t,n])=>(e[n]=t,e),{}),k=`data-rh`,A={DEFAULT_TITLE:`defaultTitle`,DEFER:`defer`,ENCODE_SPECIAL_CHARACTERS:`encodeSpecialCharacters`,ON_CHANGE_CLIENT_STATE:`onChangeClientState`,TITLE_TEMPLATE:`titleTemplate`,PRIORITIZE_SEO_TAGS:`prioritizeSeoTags`},j=(e,t)=>{for(let n=e.length-1;n>=0;--n){let r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},ne=e=>{let t=j(e,`title`),n=j(e,A.TITLE_TEMPLATE);if(Array.isArray(t)&&(t=t.join(``)),n&&t)return n.replace(/%s/g,()=>t);let r=j(e,A.DEFAULT_TITLE);return t||r||void 0},M=e=>j(e,A.ON_CHANGE_CLIENT_STATE)||(()=>{}),N=(e,t)=>t.filter(t=>t[e]!==void 0).map(t=>t[e]).reduce((e,t)=>({...e,...t}),{}),P=(e,t)=>t.filter(e=>e.base!==void 0).map(e=>e.base).reverse().reduce((t,n)=>{if(!t.length){let r=Object.keys(n);for(let i=0;iconsole&&typeof console.warn==`function`&&console.warn(e),ie=(e,t,n)=>{let r={};return n.filter(t=>Array.isArray(t[e])?!0:(t[e]!==void 0&&re(`Helmet: ${e} should be of type "Array". Instead found type "${typeof t[e]}"`),!1)).map(t=>t[e]).reverse().reduce((e,n)=>{let i={};n.filter(e=>{let n,a=Object.keys(e);for(let r=0;re.push(t));let a=Object.keys(i);for(let e=0;e{if(Array.isArray(e)&&e.length){for(let n=0;n({baseTag:P([`href`],e),bodyAttributes:N(`bodyAttributes`,e),defer:j(e,A.DEFER),encode:j(e,A.ENCODE_SPECIAL_CHARACTERS),htmlAttributes:N(`htmlAttributes`,e),linkTags:ie(`link`,[`rel`,`href`],e),metaTags:ie(`meta`,[`name`,`charset`,`http-equiv`,`property`,`itemprop`],e),noscriptTags:ie(`noscript`,[`innerHTML`],e),onChangeClientState:M(e),scriptTags:ie(`script`,[`src`,`innerHTML`],e),styleTags:ie(`style`,[`cssText`],e),title:ne(e),titleAttributes:N(`titleAttributes`,e),prioritizeSeoTags:ae(e,A.PRIORITIZE_SEO_TAGS)}),se=e=>Array.isArray(e)?e.join(``):e,F=(e,t)=>{let n=Object.keys(e);for(let r=0;rArray.isArray(e)?e.reduce((e,n)=>(F(n,t)?e.priority.push(n):e.default.push(n),e),{priority:[],default:[]}):{default:e,priority:[]},le=(e,t)=>({...e,[t]:void 0}),ue=[`noscript`,`script`,`style`],de=(e,t=!0)=>t===!1?String(e):String(e).replace(/&/g,`&`).replace(//g,`>`).replace(/"/g,`"`).replace(/'/g,`'`),fe=e=>Object.keys(e).reduce((t,n)=>{let r=e[n]===void 0?`${n}`:`${n}="${e[n]}"`;return t?`${t} ${r}`:r},``),pe=(e,t,n,r)=>{let i=fe(n),a=se(t);return i?`<${e} ${k}="true" ${i}>${de(a,r)}`:`<${e} ${k}="true">${de(a,r)}`},me=(e,t,n=!0)=>t.reduce((t,r)=>{let i=r,a=Object.keys(i).filter(e=>!(e===`innerHTML`||e===`cssText`)).reduce((e,t)=>{let r=i[t]===void 0?t:`${t}="${de(i[t],n)}"`;return e?`${e} ${r}`:r},``),o=i.innerHTML||i.cssText||``;return`${t}<${e} ${k}="true" ${a}${ue.indexOf(e)===-1?`/>`:`>${o}`}`},``),he=(e,t={})=>Object.keys(e).reduce((t,n)=>{let r=O[n];return t[r||n]=e[n],t},t),ge=(e,t,n)=>{let r=he(n,{key:t,[k]:!0});return[S.createElement(`title`,r,t)]},_e=(e,t)=>t.map((t,n)=>{let r={key:n,[k]:!0};return Object.keys(t).forEach(e=>{let n=O[e]||e;n===`innerHTML`||n===`cssText`?r.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:r[n]=t[e]}),S.createElement(e,r)}),ve=(e,t,n=!0)=>{switch(e){case`title`:return{toComponent:()=>ge(e,t.title,t.titleAttributes),toString:()=>pe(e,t.title,t.titleAttributes,n)};case`bodyAttributes`:case`htmlAttributes`:return{toComponent:()=>he(t),toString:()=>fe(t)};default:return{toComponent:()=>_e(e,t),toString:()=>me(e,t,n)}}},ye=({metaTags:e,linkTags:t,scriptTags:n,encode:r})=>{let i=ce(e,ee.meta),a=ce(t,ee.link),o=ce(n,ee.script);return{priorityMethods:{toComponent:()=>[..._e(`meta`,i.priority),..._e(`link`,a.priority),..._e(`script`,o.priority)],toString:()=>`${ve(`meta`,i.priority,r)} ${ve(`link`,a.priority,r)} ${ve(`script`,o.priority,r)}`},metaTags:i.default,linkTags:a.default,scriptTags:o.default}},be=e=>{let{baseTag:t,bodyAttributes:n,encode:r=!0,htmlAttributes:i,noscriptTags:a,styleTags:o,title:s=``,titleAttributes:c,prioritizeSeoTags:l}=e,{linkTags:u,metaTags:d,scriptTags:f}=e,p={toComponent:()=>[],toString:()=>``};return l&&({priorityMethods:p,linkTags:u,metaTags:d,scriptTags:f}=ye(e)),{priority:p,base:ve(`base`,t,r),bodyAttributes:ve(`bodyAttributes`,n,r),htmlAttributes:ve(`htmlAttributes`,i,r),link:ve(`link`,u,r),meta:ve(`meta`,d,r),noscript:ve(`noscript`,a,r),script:ve(`script`,f,r),style:ve(`style`,o,r),title:ve(`title`,{title:s,titleAttributes:c},r)}},xe=[],Se=!!(typeof window<`u`&&window.document&&window.document.createElement),Ce=class{instances=[];canUseDOM=Se;context;value={setHelmet:e=>{this.context.helmet=e},helmetInstances:{get:()=>this.canUseDOM?xe:this.instances,add:e=>{(this.canUseDOM?xe:this.instances).push(e)},remove:e=>{let t=(this.canUseDOM?xe:this.instances).indexOf(e);(this.canUseDOM?xe:this.instances).splice(t,1)}}};constructor(e,t){this.context=e,this.canUseDOM=t||!1,t||(e.helmet=be({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:``,titleAttributes:{}}))}},we=parseInt(`19.2.0`.split(`.`)[0],10)>=19,Te=S.createContext({}),Ee=class e extends S.Component{static canUseDOM=Se;helmetData;constructor(t){super(t),we?this.helmetData=null:this.helmetData=new Ce(this.props.context||{},e.canUseDOM)}render(){return we?S.createElement(S.Fragment,null,this.props.children):S.createElement(Te.Provider,{value:this.helmetData.value},this.props.children)}},De=(e,t)=>{let n=document.head||document.querySelector(`head`),r=n.querySelectorAll(`${e}[${k}]`),i=[].slice.call(r),a=[],o;return t&&t.length&&t.forEach(t=>{let n=document.createElement(e);for(let e in t)if(Object.prototype.hasOwnProperty.call(t,e))if(e===`innerHTML`)n.innerHTML=t.innerHTML;else if(e===`cssText`){let e=t.cssText;n.appendChild(document.createTextNode(e))}else{let r=e,i=t[r]===void 0?``:t[r];n.setAttribute(e,i)}n.setAttribute(k,`true`),i.some((e,t)=>(o=t,n.isEqualNode(e)))?i.splice(o,1):a.push(n)}),i.forEach(e=>e.parentNode?.removeChild(e)),a.forEach(e=>n.appendChild(e)),{oldTags:i,newTags:a}},Oe=(e,t)=>{let n=document.getElementsByTagName(e)[0];if(!n)return;let r=n.getAttribute(k),i=r?r.split(`,`):[],a=[...i],o=Object.keys(t);for(let e of o){let r=t[e]||``;n.getAttribute(e)!==r&&n.setAttribute(e,r),i.indexOf(e)===-1&&i.push(e);let o=a.indexOf(e);o!==-1&&a.splice(o,1)}for(let e=a.length-1;e>=0;--e)n.removeAttribute(a[e]);i.length===a.length?n.removeAttribute(k):n.getAttribute(k)!==o.join(`,`)&&n.setAttribute(k,o.join(`,`))},ke=(e,t)=>{e!==void 0&&document.title!==e&&(document.title=se(e)),Oe(`title`,t)},Ae=(e,t)=>{let{baseTag:n,bodyAttributes:r,htmlAttributes:i,linkTags:a,metaTags:o,noscriptTags:s,onChangeClientState:c,scriptTags:l,styleTags:u,title:d,titleAttributes:f}=e;Oe(`body`,r),Oe(`html`,i),ke(d,f);let p={baseTag:De(`base`,n),linkTags:De(`link`,a),metaTags:De(`meta`,o),noscriptTags:De(`noscript`,s),scriptTags:De(`script`,l),styleTags:De(`style`,u)},m={},h={};Object.keys(p).forEach(e=>{let{newTags:t,oldTags:n}=p[e];t.length&&(m[e]=t),n.length&&(h[e]=p[e].oldTags)}),t&&t(),c(e,m,h)},je=null,Me=e=>{je&&cancelAnimationFrame(je),e.defer?je=requestAnimationFrame(()=>{Ae(e,()=>{je=null})}):(Ae(e),je=null)},Ne=class extends S.Component{rendered=!1;shouldComponentUpdate(e){return!(0,T.default)(e,this.props)}componentDidUpdate(){this.emitChange()}componentWillUnmount(){let{helmetInstances:e}=this.props.context;e.remove(this),this.emitChange()}emitChange(){let{helmetInstances:e,setHelmet:t}=this.props.context,n=null,r=oe(e.get().map(e=>{let{context:t,...n}=e.props;return n}));Ee.canUseDOM?Me(r):be&&(n=be(r)),t(n)}init(){if(this.rendered)return;this.rendered=!0;let{helmetInstances:e}=this.props.context;e.add(this),this.emitChange()}render(){return this.init(),null}},Pe=[],Fe=e=>{let t={};for(let n of Object.keys(e))t[te[n]||n]=e[n];return t},Ie=e=>{let t={};for(let n of Object.keys(e)){let r=O[n];t[r||n]=e[n]}return t},Le=(e,t)=>{if(!Se)return;let n=document.getElementsByTagName(e)[0];if(!n)return;let r=`data-rh-managed`,i=n.getAttribute(r),a=i?i.split(`,`):[],o=Object.keys(t);for(let e of a)o.includes(e)||n.removeAttribute(e);for(let e of o){let r=t[e];r==null||r===!1?n.removeAttribute(e):r===!0?n.setAttribute(e,``):n.setAttribute(e,String(r))}o.length>0?n.setAttribute(r,o.join(`,`)):n.removeAttribute(r)},Re=()=>{let e={},t={};for(let n of Pe){let{htmlAttributes:r,bodyAttributes:i}=n.props;r&&Object.assign(e,Fe(r)),i&&Object.assign(t,Fe(i))}Le(`html`,e),Le(`body`,t)},ze=class extends S.Component{componentDidMount(){Pe.push(this),Re()}componentDidUpdate(){Re()}componentWillUnmount(){let e=Pe.indexOf(this);e!==-1&&Pe.splice(e,1),Re()}resolveTitle(){let{title:e,titleTemplate:t,defaultTitle:n}=this.props;return e&&t?t.replace(/%s/g,()=>Array.isArray(e)?e.join(``):e):e||n||void 0}renderTitle(){let e=this.resolveTitle();if(e===void 0)return null;let t=this.props.titleAttributes||{};return S.createElement(`title`,Ie(t),e)}renderBase(){let{base:e}=this.props;return e?S.createElement(`base`,Ie(e)):null}renderMeta(){let{meta:e}=this.props;return!e||!Array.isArray(e)?null:e.map((e,t)=>S.createElement(`meta`,{key:t,...Ie(e)}))}renderLink(){let{link:e}=this.props;return!e||!Array.isArray(e)?null:e.map((e,t)=>S.createElement(`link`,{key:t,...Ie(e)}))}renderScript(){let{script:e}=this.props;return!e||!Array.isArray(e)?null:e.map((e,t)=>{let{innerHTML:n,...r}=e,i=Ie(r);return n&&(i.dangerouslySetInnerHTML={__html:n}),S.createElement(`script`,{key:t,...i})})}renderStyle(){let{style:e}=this.props;return!e||!Array.isArray(e)?null:e.map((e,t)=>{let{cssText:n,...r}=e,i=Ie(r);return n&&(i.dangerouslySetInnerHTML={__html:n}),S.createElement(`style`,{key:t,...i})})}renderNoscript(){let{noscript:e}=this.props;return!e||!Array.isArray(e)?null:e.map((e,t)=>{let{innerHTML:n,...r}=e,i=Ie(r);return n&&(i.dangerouslySetInnerHTML={__html:n}),S.createElement(`noscript`,{key:t,...i})})}render(){return S.createElement(S.Fragment,null,this.renderTitle(),this.renderBase(),this.renderMeta(),this.renderLink(),this.renderScript(),this.renderStyle(),this.renderNoscript())}},Be=class extends S.Component{static defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1};shouldComponentUpdate(e){return!(0,C.default)(le(this.props,`helmetData`),le(e,`helmetData`))}mapNestedChildrenToProps(e,t){if(!t)return null;switch(e.type){case`script`:case`noscript`:return{innerHTML:t};case`style`:return{cssText:t};default:throw Error(`<${e.type} /> elements are self-closing and can not contain children. Refer to our API for more information.`)}}flattenArrayTypeChildren(e,t,n,r){return{...t,[e.type]:[...t[e.type]||[],{...n,...this.mapNestedChildrenToProps(e,r)}]}}mapObjectTypeChildren(e,t,n,r){switch(e.type){case`title`:return{...t,[e.type]:r,titleAttributes:{...n}};case`body`:return{...t,bodyAttributes:{...n}};case`html`:return{...t,htmlAttributes:{...n}};default:return{...t,[e.type]:{...n}}}}mapArrayTypeChildrenToProps(e,t){let n={...t};return Object.keys(e).forEach(t=>{n={...n,[t]:e[t]}}),n}warnOnInvalidChildren(e,t){return(0,w.default)(D.some(t=>e.type===t),typeof e.type==`function`?`You may be attempting to nest components within each other, which is not allowed. Refer to our API for more information.`:`Only elements types ${D.join(`, `)} are allowed. Helmet does not support rendering <${e.type}> elements. Refer to our API for more information.`),(0,w.default)(!t||typeof t==`string`||Array.isArray(t)&&!t.some(e=>typeof e!=`string`),`Helmet expects a string as a child of <${e.type}>. Did you forget to wrap your children in braces? ( <${e.type}>{\`\`} ) Refer to our API for more information.`),!0}mapChildrenToProps(e,t){let n={};return S.Children.forEach(e,e=>{if(!e||!e.props)return;let{children:r,...i}=e.props,a=Object.keys(i).reduce((e,t)=>(e[te[t]||t]=i[t],e),{}),{type:o}=e;switch(typeof o==`symbol`?o=o.toString():this.warnOnInvalidChildren(e,r),o){case`Symbol(react.fragment)`:t=this.mapChildrenToProps(r,t);break;case`link`:case`meta`:case`noscript`:case`script`:case`style`:n=this.flattenArrayTypeChildren(e,n,a,r);break;default:t=this.mapObjectTypeChildren(e,t,a,r);break}}),this.mapArrayTypeChildrenToProps(n,t)}render(){let{children:e,...t}=this.props,n={...t},{helmetData:r}=t;return e&&(n=this.mapChildrenToProps(e,n)),r&&!(r instanceof Ce)&&(r=new Ce(r.context,!0),delete n.helmetData),we?S.createElement(ze,{...n}):r?S.createElement(Ne,{...n,context:r.value}):S.createElement(Te.Consumer,null,e=>S.createElement(Ne,{...n,context:e}))}},Ve=`modulepreload`,He=function(e){return`/_frontend/`+e},Ue={};const We=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=He(t,n),t in Ue)return;Ue[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:Ve,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};var Ge=`popstate`;function Ke(e){return typeof e==`object`&&!!e&&`pathname`in e&&`search`in e&&`hash`in e&&`state`in e&&`key`in e}function qe(e={}){function t(e,t){let n=t.state?.masked,{pathname:r,search:i,hash:a}=n||e.location;return $e(``,{pathname:r,search:i,hash:a},t.state&&t.state.usr||null,t.state&&t.state.key||`default`,n?{pathname:e.location.pathname,search:e.location.search,hash:e.location.hash}:void 0)}function n(e,t){return typeof t==`string`?t:et(t)}return nt(t,n,null,e)}function Je(e={}){function t(e,t){let{pathname:n=`/`,search:r=``,hash:i=``}=tt(e.location.hash.substring(1));return!n.startsWith(`/`)&&!n.startsWith(`.`)&&(n=`/`+n),$e(``,{pathname:n,search:r,hash:i},t.state&&t.state.usr||null,t.state&&t.state.key||`default`)}function n(e,t){let n=e.document.querySelector(`base`),r=``;if(n&&n.getAttribute(`href`)){let t=e.location.href,n=t.indexOf(`#`);r=n===-1?t:t.slice(0,n)}return r+`#`+(typeof t==`string`?t:et(t))}function r(e,t){Xe(e.pathname.charAt(0)===`/`,`relative pathnames are not supported in hash history.push(${JSON.stringify(t)})`)}return nt(t,n,r,e)}function Ye(e,t){if(e===!1||e==null)throw Error(t)}function Xe(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function Ze(){return Math.random().toString(36).substring(2,10)}function Qe(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function $e(e,t,n=null,r,i){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?tt(t):t,state:n,key:t&&t.key||r||Ze(),mask:i}}function et({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function tt(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function nt(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=Ke(e)?e:$e(h.location,e,t);n&&n(r,e),l=u()+1;let d=Qe(r,l),f=h.createHref(r.mask||r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=Ke(e)?e:$e(h.location,e,t);n&&n(r,e),l=u();let i=Qe(r,l),d=h.createHref(r.mask||r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return rt(e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(Ge,d),c=e,()=>{i.removeEventListener(Ge,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function rt(e,t=!1){let n=`http://localhost`;typeof window<`u`&&(n=window.location.origin===`null`?window.location.href:window.location.origin),Ye(n,`No window.location.(origin|href) available to create URL`);let r=typeof e==`string`?e:et(e);return r=r.replace(/ $/,`%20`),!t&&r.startsWith(`//`)&&(r=n+r),new URL(r,n)}function it(e,t,n=`/`){return at(e,t,n,!1)}function at(e,t,n,r,i){let a=wt((typeof t==`string`?tt(t):t).pathname||`/`,n);if(a==null)return null;let o=i??st(e),s=null,c=Ct(a);for(let e=0;s==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;Ye(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=Nt([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(Ye(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),ct(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:vt(l,e.index),routesMeta:u})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of lt(e.path))a(e,t,!0,n)}),t}function lt(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=lt(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function ut(e){e.sort((e,t)=>e.score===t.score?yt(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var dt=/^:[\w-]+$/,ft=3,pt=2,mt=1,ht=10,gt=-2,_t=e=>e===`*`;function vt(e,t){let n=e.split(`/`),r=n.length;return n.some(_t)&&(r+=gt),t&&(r+=pt),n.filter(e=>!_t(e)).reduce((e,t)=>e+(dt.test(t)?ft:t===``?mt:ht),r)}function yt(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function bt(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function St(e,t=!1,n=!0){Xe(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n,i,a)=>{if(r.push({paramName:t,isOptional:n!=null}),n){let t=a.charAt(i+e.length);return t&&t!==`/`?`/([^\\/]*)`:`(?:/([^\\/]*))?`}return`/([^\\/]+)`}).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function Ct(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return Xe(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function wt(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}var Tt=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function Et(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?tt(e):e,a;return n?(n=Mt(n),a=n.startsWith(`/`)?Dt(n.substring(1),`/`):Dt(n,t)):a=t,{pathname:a,search:It(r),hash:Lt(i)}}function Dt(e,t){let n=Pt(t).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function Ot(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function kt(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function At(e){let t=kt(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function jt(e,t,n,r=!1){let i;typeof e==`string`?i=tt(e):(i={...e},Ye(!i.pathname||!i.pathname.includes(`?`),Ot(`?`,`pathname`,`search`,i)),Ye(!i.pathname||!i.pathname.includes(`#`),Ot(`#`,`pathname`,`hash`,i)),Ye(!i.search||!i.search.includes(`#`),Ot(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=Et(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var Mt=e=>e.replace(/\/\/+/g,`/`),Nt=e=>Mt(e.join(`/`)),Pt=e=>e.replace(/\/+$/,``),Ft=e=>Pt(e).replace(/^\/*/,`/`),It=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,Lt=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,Rt=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function zt(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function Bt(e){return Nt(e.map(e=>e.route.path).filter(Boolean))||`/`}var Vt=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function Ht(e,t){let n=e;if(typeof n!=`string`||!Tt.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(Vt)try{let e=new URL(window.location.href),r=n.startsWith(`//`)?new URL(e.protocol+n):new URL(n),a=wt(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{Xe(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var Ut=S.createContext(null);Ut.displayName=`DataRouter`;var Wt=S.createContext(null);Wt.displayName=`DataRouterState`;var Gt=S.createContext(!1);function Kt(){return S.useContext(Gt)}var qt=S.createContext({isTransitioning:!1});qt.displayName=`ViewTransition`;var Jt=S.createContext(new Map);Jt.displayName=`Fetchers`;var Yt=S.createContext(null);Yt.displayName=`Await`;var Xt=S.createContext(null);Xt.displayName=`Navigation`;var Zt=S.createContext(null);Zt.displayName=`Location`;var Qt=S.createContext({outlet:null,matches:[],isDataRoute:!1});Qt.displayName=`Route`;var $t=S.createContext(null);$t.displayName=`RouteError`;var en=`REACT_ROUTER_ERROR`,tn=`REDIRECT`,nn=`ROUTE_ERROR_RESPONSE`;function rn(e){if(e.startsWith(`${en}:${tn}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function an(e){if(e.startsWith(`${en}:${nn}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new Rt(t.status,t.statusText,t.data)}catch{}}function on(e,{relative:t}={}){Ye(sn(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=S.useContext(Xt),{hash:i,pathname:a,search:o}=pn(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:Nt([n,a])),r.createHref({pathname:s,search:o,hash:i})}function sn(){return S.useContext(Zt)!=null}function cn(){return Ye(sn(),`useLocation() may be used only in the context of a component.`),S.useContext(Zt).location}var ln=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function un(e){S.useContext(Xt).static||S.useLayoutEffect(e)}function dn(){let{isDataRoute:e}=S.useContext(Qt);return e?jn():fn()}function fn(){Ye(sn(),`useNavigate() may be used only in the context of a component.`);let e=S.useContext(Ut),{basename:t,navigator:n}=S.useContext(Xt),{matches:r}=S.useContext(Qt),{pathname:i}=cn(),a=JSON.stringify(At(r)),o=S.useRef(!1);return un(()=>{o.current=!0}),S.useCallback((r,s={})=>{if(Xe(o.current,ln),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=jt(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:Nt([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}S.createContext(null);function pn(e,{relative:t}={}){let{matches:n}=S.useContext(Qt),{pathname:r}=cn(),i=JSON.stringify(At(n));return S.useMemo(()=>jt(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function mn(e,t,n){Ye(sn(),`useRoutes() may be used only in the context of a component.`);let{navigator:r}=S.useContext(Xt),{matches:i}=S.useContext(Qt),a=i[i.length-1],o=a?a.params:{},s=a?a.pathname:`/`,c=a?a.pathnameBase:`/`,l=a&&a.route;{let e=l&&l.path||``;Nn(s,!l||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${s}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let u=cn(),d;if(t){let e=typeof t==`string`?tt(t):t;Ye(c===`/`||e.pathname?.startsWith(c),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${c}" but pathname "${e.pathname}" was given in the \`location\` prop.`),d=e}else d=u;let f=d.pathname||`/`,p=f;if(c!==`/`){let e=c.replace(/^\//,``).split(`/`);p=`/`+f.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let m=n&&n.state.matches.length?n.state.matches.map(e=>Object.assign(e,{route:n.manifest[e.route.id]||e.route})):it(e,{pathname:p});Xe(l||m!=null,`No routes matched location "${d.pathname}${d.search}${d.hash}" `),Xe(m==null||m[m.length-1].route.element!==void 0||m[m.length-1].route.Component!==void 0||m[m.length-1].route.lazy!==void 0,`Matched leaf route at location "${d.pathname}${d.search}${d.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let h=xn(m&&m.map(e=>Object.assign({},e,{params:Object.assign({},o,e.params),pathname:Nt([c,r.encodeLocation?r.encodeLocation(e.pathname.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?c:Nt([c,r.encodeLocation?r.encodeLocation(e.pathnameBase.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),i,n);return t&&h?S.createElement(Zt.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,mask:void 0,...d},navigationType:`POP`}},h):h}function hn(){let e=An(),t=zt(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r=`rgba(200,200,200, 0.5)`,i={padding:`0.5rem`,backgroundColor:r},a={padding:`2px 4px`,backgroundColor:r},o=null;return console.error(`Error handled by React Router default ErrorBoundary:`,e),o=S.createElement(S.Fragment,null,S.createElement(`p`,null,`💿 Hey developer 👋`),S.createElement(`p`,null,`You can provide a way better UX than this when your app throws errors by providing your own `,S.createElement(`code`,{style:a},`ErrorBoundary`),` or`,` `,S.createElement(`code`,{style:a},`errorElement`),` prop on your route.`)),S.createElement(S.Fragment,null,S.createElement(`h2`,null,`Unexpected Application Error!`),S.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?S.createElement(`pre`,{style:i},n):null,o)}var gn=S.createElement(hn,null),_n=class extends S.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=an(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:S.createElement(Qt.Provider,{value:this.props.routeContext},S.createElement($t.Provider,{value:e,children:this.props.component}));return this.context?S.createElement(yn,{error:e},t):t}};_n.contextType=Gt;var vn=new WeakMap;function yn({children:e,error:t}){let{basename:n}=S.useContext(Xt);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=rn(t.digest);if(e){let r=vn.get(t);if(r)throw r;let i=Ht(e.location,n);if(Vt&&!vn.get(t))if(i.isExternal||e.reloadDocument)window.location.href=i.absoluteURL||i.to;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw vn.set(t,n),n}return S.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${i.absoluteURL||i.to}`})}}return e}function bn({routeContext:e,match:t,children:n}){let r=S.useContext(Ut);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),S.createElement(Qt.Provider,{value:e},n)}function xn(e,t=[],n){let r=n?.state;if(e==null){if(!r)return null;if(r.errors)e=r.matches;else if(t.length===0&&!r.initialized&&r.matches.length>0)e=r.matches;else return null}let i=e,a=r?.errors;if(a!=null){let e=i.findIndex(e=>e.route.id&&a?.[e.route.id]!==void 0);Ye(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(a).join(`,`)}`),i=i.slice(0,Math.min(i.length,e+1))}let o=!1,s=-1;if(n&&r){o=r.renderFallback;for(let e=0;e=0?i.slice(0,s+1):[i[0]];break}}}}let c=n?.onError,l=r&&c?(e,t)=>{c(e,{location:r.location,params:r.matches?.[0]?.params??{},pattern:Bt(r.matches),errorInfo:t})}:void 0;return i.reduceRight((e,n,c)=>{let u,d=!1,f=null,p=null;r&&(u=a&&n.route.id?a[n.route.id]:void 0,f=n.route.errorElement||gn,o&&(s<0&&c===0?(Nn(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,p=null):s===c&&(d=!0,p=n.route.hydrateFallbackElement||null)));let m=t.concat(i.slice(0,c+1)),h=()=>{let t;return t=u?f:d?p:n.route.Component?S.createElement(n.route.Component,null):n.route.element?n.route.element:e,S.createElement(bn,{match:n,routeContext:{outlet:e,matches:m,isDataRoute:r!=null},children:t})};return r&&(n.route.ErrorBoundary||n.route.errorElement||c===0)?S.createElement(_n,{location:r.location,revalidation:r.revalidation,component:f,error:u,children:h(),routeContext:{outlet:null,matches:m,isDataRoute:!0},onError:l}):h()},null)}function Sn(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Cn(e){let t=S.useContext(Ut);return Ye(t,Sn(e)),t}function wn(e){let t=S.useContext(Wt);return Ye(t,Sn(e)),t}function Tn(e){let t=S.useContext(Qt);return Ye(t,Sn(e)),t}function En(e){let t=Tn(e),n=t.matches[t.matches.length-1];return Ye(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function Dn(){return En(`useRouteId`)}function On(){return wn(`useNavigation`).navigation}function kn(){let{matches:e,loaderData:t}=wn(`useMatches`);return S.useMemo(()=>e.map(e=>ot(e,t)),[e,t])}function An(){let e=S.useContext($t),t=wn(`useRouteError`),n=En(`useRouteError`);return e===void 0?t.errors?.[n]:e}function jn(){let{router:e}=Cn(`useNavigate`),t=En(`useNavigate`),n=S.useRef(!1);return un(()=>{n.current=!0}),S.useCallback(async(r,i={})=>{Xe(n.current,ln),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var Mn={};function Nn(e,t,n){!t&&!Mn[e]&&(Mn[e]=!0,Xe(!1,n))}S.useOptimistic,S.memo(Pn);function Pn({routes:e,manifest:t,future:n,state:r,isStatic:i,onError:a}){return mn(e,void 0,{manifest:t,state:r,isStatic:i,onError:a,future:n})}function Fn({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,useTransitions:o}){Ye(!sn(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=S.useMemo(()=>({basename:s,navigator:i,static:a,useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=tt(n));let{pathname:l=`/`,search:u=``,hash:d=``,state:f=null,key:p=`default`,mask:m}=n,h=S.useMemo(()=>{let e=wt(l,s);return e==null?null:{location:{pathname:e,search:u,hash:d,state:f,key:p,mask:m},navigationType:r}},[s,l,u,d,f,p,r,m]);return Xe(h!=null,` is not able to match the URL "${l}${u}${d}" because it does not start with the basename, so the won't render anything.`),h==null?null:S.createElement(Xt.Provider,{value:c},S.createElement(Zt.Provider,{children:t,value:h}))}var In=`get`,Ln=`application/x-www-form-urlencoded`;function Rn(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function zn(e){return Rn(e)&&e.tagName.toLowerCase()===`button`}function Bn(e){return Rn(e)&&e.tagName.toLowerCase()===`form`}function Vn(e){return Rn(e)&&e.tagName.toLowerCase()===`input`}function Hn(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Un(e,t){return e.button===0&&(!t||t===`_self`)&&!Hn(e)}var Wn=null;function Gn(){if(Wn===null)try{new FormData(document.createElement(`form`),0),Wn=!1}catch{Wn=!0}return Wn}var Kn=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function qn(e){return e!=null&&!Kn.has(e)?(Xe(!1,`"${e}" is not a valid \`encType\` for \`

\`/\`\` and will default to "${Ln}"`),null):e}function Jn(e,t){let n,r,i,a,o;if(Bn(e)){let o=e.getAttribute(`action`);r=o?wt(o,t):null,n=e.getAttribute(`method`)||In,i=qn(e.getAttribute(`enctype`))||Ln,a=new FormData(e)}else if(zn(e)||Vn(e)&&(e.type===`submit`||e.type===`image`)){let o=e.form;if(o==null)throw Error(`Cannot submit a