DEV CommiDEV Committ
This commit is contained in:
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>
|
||||
+39
@@ -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>
|
||||
+38
@@ -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>
|
||||
Regular → Executable
+4
-2
@@ -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);
|
||||
Reference in new issue
Block a user