DEV CommiDEV Committ

This commit is contained in:
khaccount committed 2026-07-01 10:34:48 +02:00
1 parent 4541c58fe7
commit c6759186cb
145 files changed
+2742 -579

No files matched your search

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<xliff version="1.0">
<file source-language="en" datatype="plaintext" original="EXT:vitec/Resources/Private/Language/locallang_buttons.xlf" product-name="vitec">
<header/>
<body>
<!-- Primary / single button -->
<trans-unit id="button_style.label" resname="button_style.label">
<source>Button Style</source>
</trans-unit>
<trans-unit id="button_style.items.orange.label" resname="button_style.items.orange.label">
<source>Orange</source>
</trans-unit>
<trans-unit id="button_style.items.blue.label" resname="button_style.items.blue.label">
<source>Blue</source>
</trans-unit>
<trans-unit id="button_style.items.graphite.label" resname="button_style.items.graphite.label">
<source>Graphite</source>
</trans-unit>
<trans-unit id="button_style.items.midnight.label" resname="button_style.items.midnight.label">
<source>Midnight</source>
</trans-unit>
<trans-unit id="button_style.items.light.label" resname="button_style.items.light.label">
<source>Light</source>
</trans-unit>
<trans-unit id="button_style.items.dark.label" resname="button_style.items.dark.label">
<source>Dark</source>
</trans-unit>
<trans-unit id="button_style.items.text_only.label" resname="button_style.items.text_only.label">
<source>Only Text (no button background)</source>
</trans-unit>
<!-- Secondary button -->
<trans-unit id="secondary_button_style.label" resname="secondary_button_style.label">
<source>Secondary Button Style</source>
</trans-unit>
<trans-unit id="secondary_button_style.items.orange.label" resname="secondary_button_style.items.orange.label">
<source>Orange</source>
</trans-unit>
<trans-unit id="secondary_button_style.items.blue.label" resname="secondary_button_style.items.blue.label">
<source>Blue</source>
</trans-unit>
<trans-unit id="secondary_button_style.items.graphite.label" resname="secondary_button_style.items.graphite.label">
<source>Graphite</source>
</trans-unit>
<trans-unit id="secondary_button_style.items.midnight.label" resname="secondary_button_style.items.midnight.label">
<source>Midnight</source>
</trans-unit>
<trans-unit id="secondary_button_style.items.light.label" resname="secondary_button_style.items.light.label">
<source>Light</source>
</trans-unit>
<trans-unit id="secondary_button_style.items.dark.label" resname="secondary_button_style.items.dark.label">
<source>Dark</source>
</trans-unit>
<trans-unit id="secondary_button_style.items.text_only.label" resname="secondary_button_style.items.text_only.label">
<source>Only Text (no button background)</source>
</trans-unit>
</body>
</file>
</xliff>
@@ -6,6 +6,9 @@
<trans-unit id="group.header" resname="group.header">
<source>VITEC</source>
</trans-unit>
<trans-unit id="group.custom_components.header" resname="group.custom_components.header">
<source>Custom Components</source>
</trans-unit>
<trans-unit id="section.heading" resname="section.heading">
<source>Section Heading</source>
@@ -1,25 +0,0 @@
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "Product",
"name": "Executive Anvil",
"description": "Sleeker than ACME's Classic Anvil, the Executive Anvil is perfect for the business traveler looking for something to drop from a height.",
"review": {
"@type": "Review",
"reviewRating": {
"@type": "Rating",
"ratingValue": 4,
"bestRating": 5
},
"author": {
"@type": "Person",
"name": "Fred Benson"
}
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.4,
"reviewCount": 89
}
}
</script>
@@ -0,0 +1,39 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:asset.css identifier="vitec-backend-preview" href="EXT:vitec/Resources/Public/Css/backend-preview.css"/>
<div class="vitec-preview">
<div class="vitec-preview__thumb-placeholder">⬇</div>
<div class="vitec-preview__body">
<div class="vitec-preview__label">VITEC · Download Card</div>
<h3 class="vitec-preview__headline">
<f:if condition="{data.header}">
<f:then>{data.header}</f:then>
<f:else>
<em style="color:#888;">Download Card (kein Header)</em>
</f:else>
</f:if>
</h3>
<div class="vitec-preview__body-text">
<small>
Konfiguration im FlexForm:
<strong>Produkt</strong> oder <strong>Download</strong> wählen,
Layout-Variante setzen.
</small>
</div>
</div>
<div class="vitec-preview__settings">
<span class="vitec-badge">⬇ Single Download / Product</span>
<f:if condition="{data.pi_flexform}">
<span class="vitec-badge">⚙ FlexForm configured</span>
</f:if>
</div>
</div>
</html>
@@ -0,0 +1,38 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:asset.css identifier="vitec-backend-preview" href="EXT:vitec/Resources/Public/Css/backend-preview.css"/>
<div class="vitec-preview">
<div class="vitec-preview__thumb-placeholder">⬇⬇</div>
<div class="vitec-preview__body">
<div class="vitec-preview__label">VITEC · Download Card Collection</div>
<h3 class="vitec-preview__headline">
<f:if condition="{data.header}">
<f:then>{data.header}</f:then>
<f:else>
<em style="color:#888;">Download Card Collection (kein Header)</em>
</f:else>
</f:if>
</h3>
<div class="vitec-preview__body-text">
<small>
Multi-Download-Auswahl mit optionalem Header-Image.
Konfiguration im FlexForm.
</small>
</div>
</div>
<div class="vitec-preview__settings">
<span class="vitec-badge">⬇⬇ Multi-Download</span>
<f:if condition="{data.pi_flexform}">
<span class="vitec-badge">⚙ FlexForm configured</span>
</f:if>
</div>
</div>
</html>
+4 -2
View File
@@ -56,6 +56,8 @@
/* Content-Slot */
.vitec-preview__body {
min-width: 0;
overflow-wrap: anywhere;
word-break: break-word;
}
.vitec-preview__label {
@@ -106,7 +108,7 @@
flex-direction: column;
gap: 0.25rem;
align-items: flex-end;
min-width: 120px;
min-width: 80px;
}
.vitec-badge {
@@ -193,7 +195,7 @@
}
/* Responsive Fallback */
@media (max-width: 680px) {
@media (max-width: 900px) {
.vitec-preview {
grid-template-columns: 1fr;
}
@@ -0,0 +1,91 @@
/**
* VITEC – Structured Data generator button (FormEngine fieldWizard).
* EXT:vitec/Resources/Public/Javascript/structured-data-generator.js
*
* Self-initializing: on load it installs a single delegated click handler for
* any button matching [data-vitec-sd-generate]. This avoids relying on the
* JavaScriptModuleInstruction ->instance() payload (which is unreliable for
* fieldWizards) and also works for fields added to the DOM later.
*
* On click it calls the backend AJAX endpoint for the product uid and writes
* the returned JSON-LD string into the associated `structureddata` textarea.
* The textarea is resolved by its form name (data-field-name) with a fallback
* to the surrounding FormEngine field-item container.
*/
import DocumentService from "@typo3/core/document-service.js";
import AjaxRequest from "@typo3/core/ajax/ajax-request.js";
import Notification from "@typo3/backend/notification.js";
const SELECTOR = "[data-vitec-sd-generate]";
function findField(button) {
const name = button.dataset.fieldName;
if (name) {
const byName = document.querySelector('[name="' + name + '"]');
if (byName !== null) {
return byName;
}
}
const item = button.closest(".t3js-formengine-field-item");
if (item !== null) {
return item.querySelector("textarea, input[type=text], input:not([type])");
}
return null;
}
async function generate(button) {
const field = findField(button);
if (!field) {
Notification.error("Fehler", "Das Structured-Data-Feld wurde nicht gefunden.");
return;
}
const ajaxUrl = TYPO3.settings.ajaxUrls["vitec_structureddata_generate"];
if (!ajaxUrl) {
Notification.error("Fehler", "AJAX-Route nicht registriert.");
return;
}
button.disabled = true;
try {
const response = await new AjaxRequest(ajaxUrl)
.withQueryArguments({ uid: button.dataset.uid })
.get();
const data = await response.resolve();
if (data.success) {
field.value = data.jsonLd;
field.dispatchEvent(new Event("change", { bubbles: true }));
Notification.success(
"Structured Data",
"JSON-LD wurde generiert und in das Feld geschrieben."
);
} else {
Notification.warning("Hinweis", data.message || "Generierung nicht möglich.");
}
} catch (error) {
Notification.error("Fehler", "Die Generierung ist fehlgeschlagen.");
} finally {
button.disabled = false;
}
}
function init() {
// Guard against binding more than once (the module instruction may be
// emitted per field instance, but the module itself is a singleton).
if (document.body.dataset.vitecSdBound === "1") {
return;
}
document.body.dataset.vitecSdBound = "1";
document.addEventListener("click", (event) => {
const button = event.target.closest(SELECTOR);
if (button === null) {
return;
}
event.preventDefault();
generate(button);
});
}
DocumentService.ready().then(init);