Zwischenstand vom 29.05.2026

This commit is contained in:
khaccount committed 2026-05-29 11:14:02 +02:00
1 parent b6d2142214
commit dba154e572
36 files changed
+5113 -649

No files matched your search

@@ -0,0 +1,288 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true">
<f:layout name="Backend/Default" />
<f:section name="main">
<div class="module-docheader-bar module-docheader-bar-navigation">
<div class="module-docheader-bar-column-left">
<h2 class="t3js-title-inlineedit">OG Image Generator</h2>
</div>
</div>
<div class="row" id="vitec-ogimage-wrap">
<!-- ══════════════════════════════════════════════════════
LEFT: FORM
═══════════════════════════════════════════════════════ -->
<div class="col-md-7">
<f:flashMessages queueIdentifier="core.template.flashMessages" />
<form action="{f:be.uri(route: 'web_vitecogimage.generate')}" method="post" id="vitecOgForm" data-preview-url="{f:be.uri(route: 'web_vitecogimage.preview')}">
<!-- Preset quick-picks -->
<div class="card mb-3">
<div class="card-header"><strong>Quick Presets</strong></div>
<div class="card-body d-flex gap-2 flex-wrap">
<f:for each="{presets}" as="preset" key="key">
<button type="button" class="btn btn-outline-secondary btn-sm js-preset"
data-preset="{key}"
data-bg="{preset.bg_color}"
data-title-color="{preset.title_color}"
data-subtitle-color="{preset.subtitle_color}">
{preset.label}
</button>
</f:for>
</div>
</div>
<!-- Background -->
<div class="card mb-3">
<div class="card-header"><strong>Background</strong></div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Type</label>
<div class="d-flex gap-3">
<label class="form-check-label">
<input class="form-check-input me-1 js-bg-type" type="radio"
name="ogimage[bg_type]" value="color"
<f:if condition="{formData.bg_type} == 'color'">checked</f:if>/>
Solid colour
</label>
<label class="form-check-label">
<input class="form-check-input me-1 js-bg-type" type="radio"
name="ogimage[bg_type]" value="image"
<f:if condition="{formData.bg_type} == 'image'">checked</f:if>/>
Image
</label>
</div>
</div>
<div id="bg-color-wrap" class="mb-3">
<label class="form-label">Background Colour</label>
<div class="d-flex align-items-center gap-2">
<input type="color" class="form-control form-control-color js-live"
name="ogimage[bg_color]" id="bgColor"
value="{formData.bg_color}" />
<input type="text" class="form-control js-hex-sync" style="max-width:120px"
data-target="bgColor" value="{formData.bg_color}" />
</div>
</div>
<div id="bg-image-wrap" class="mb-3" style="display:none">
<label class="form-label">Background Image</label>
<f:if condition="{backgroundImages}">
<f:then>
<select class="form-select js-live" name="ogimage[bg_image]">
<option value="">— none —</option>
<f:for each="{backgroundImages}" as="img">
<option value="{img.path}"
<f:if condition="{formData.bg_image} == {img.path}">selected</f:if>>{img.label}</option>
</f:for>
</select>
<small class="text-muted">Upload images to <code>fileadmin/og-backgrounds/</code> to list them here.</small>
</f:then>
<f:else>
<input type="text" class="form-control js-live"
name="ogimage[bg_image]"
placeholder="/fileadmin/og-backgrounds/my-bg.jpg"
value="{formData.bg_image}" />
<small class="text-muted">No images found in <code>fileadmin/og-backgrounds/</code>. Enter a path manually, or upload files there.</small>
</f:else>
</f:if>
<div class="mt-2">
<label class="form-label">Dark overlay opacity: <span id="overlayLabel">{formData.overlay_opacity}</span>%</label>
<input type="range" class="form-range js-live" min="0" max="90" step="5"
name="ogimage[overlay_opacity]" value="{formData.overlay_opacity}"
oninput="document.getElementById('overlayLabel').textContent=this.value"/>
</div>
</div>
</div>
</div>
<!-- Text -->
<div class="card mb-3">
<div class="card-header"><strong>Text</strong></div>
<div class="card-body">
<div class="row mb-3">
<div class="col-8">
<label class="form-label">Title</label>
<input type="text" class="form-control js-live"
name="ogimage[title]" value="{formData.title}"
placeholder="Your headline" />
</div>
<div class="col-2">
<label class="form-label">Size</label>
<input type="number" class="form-control js-live"
name="ogimage[title_size]" value="{formData.title_size}"
min="20" max="120" />
</div>
<div class="col-2">
<label class="form-label">Colour</label>
<input type="color" class="form-control form-control-color js-live"
name="ogimage[title_color]" id="titleColor"
value="{formData.title_color}" />
</div>
</div>
<div class="row mb-2">
<div class="col-8">
<label class="form-label">Subtitle / Description</label>
<input type="text" class="form-control js-live"
name="ogimage[subtitle]" value="{formData.subtitle}"
placeholder="Short description" />
</div>
<div class="col-2">
<label class="form-label">Size</label>
<input type="number" class="form-control js-live"
name="ogimage[subtitle_size]" value="{formData.subtitle_size}"
min="14" max="80" />
</div>
<div class="col-2">
<label class="form-label">Colour</label>
<input type="color" class="form-control form-control-color js-live"
name="ogimage[subtitle_color]" id="subtitleColor"
value="{formData.subtitle_color}" />
</div>
</div>
</div>
</div>
<!-- Label / Badge -->
<div class="card mb-3">
<div class="card-header"><strong>Label / Badge</strong></div>
<div class="card-body">
<div class="row mb-3">
<div class="col-6">
<label class="form-label">Label text (leave blank to hide)</label>
<input type="text" class="form-control js-live"
name="ogimage[label_text]" value="{formData.label_text}"
placeholder="e.g. VITEC" />
</div>
<div class="col-3">
<label class="form-label">Background</label>
<input type="color" class="form-control form-control-color js-live"
name="ogimage[label_bg_color]" id="labelBg"
value="{formData.label_bg_color}" />
</div>
<div class="col-3">
<label class="form-label">Text colour</label>
<input type="color" class="form-control form-control-color js-live"
name="ogimage[label_text_color]" id="labelText"
value="{formData.label_text_color}" />
</div>
</div>
<div class="mb-2">
<label class="form-label">Position</label>
<select class="form-select js-live" name="ogimage[label_position]">
<option value="top-left" <f:if condition="{formData.label_position} == 'top-left'">selected</f:if>>Top Left</option>
<option value="top-right" <f:if condition="{formData.label_position} == 'top-right'">selected</f:if>>Top Right</option>
<option value="bottom-left" <f:if condition="{formData.label_position} == 'bottom-left'">selected</f:if>>Bottom Left</option>
<option value="bottom-right"<f:if condition="{formData.label_position} == 'bottom-right'">selected</f:if>>Bottom Right</option>
</select>
</div>
</div>
</div>
<!-- Output -->
<div class="card mb-3">
<div class="card-header"><strong>Output</strong></div>
<div class="card-body row">
<div class="col-4">
<label class="form-label">Format</label>
<select class="form-select" name="ogimage[output_format]">
<option value="jpg" <f:if condition="{formData.output_format} == 'jpg'">selected</f:if>>JPG</option>
<option value="png" <f:if condition="{formData.output_format} == 'png'">selected</f:if>>PNG</option>
</select>
</div>
<div class="col-4">
<label class="form-label">Quality (JPG): <span id="qualLabel">{formData.output_quality}</span></label>
<input type="range" class="form-range" min="50" max="100" step="5"
name="ogimage[output_quality]" value="{formData.output_quality}"
oninput="document.getElementById('qualLabel').textContent=this.value"/>
</div>
</div>
</div>
<div class="d-flex gap-2 mb-4">
<button type="button" class="btn btn-secondary" id="btnPreview">
Preview
</button>
<button type="submit" class="btn btn-primary">
Save Image to fileadmin
</button>
</div>
</form>
</div><!-- /col form -->
<!-- ══════════════════════════════════════════════════════
RIGHT: PREVIEW + SAVED IMAGES
═══════════════════════════════════════════════════════ -->
<div class="col-md-5">
<div class="card mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<strong>Preview <small class="text-muted">(1200 × 630)</small></strong>
<span id="previewSpinner" class="spinner-border spinner-border-sm text-secondary d-none" role="status"></span>
</div>
<div class="card-body p-2 bg-secondary">
<div style="position:relative; padding-top: 52.5%;"><!-- 630/1200 -->
<img id="ogPreviewImg" src="" alt="preview"
style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;display:none;" />
<div id="ogPreviewPlaceholder"
style="position:absolute;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:#aaa;">
Click "Preview" to render
</div>
</div>
</div>
<div class="card-footer text-end">
<a id="previewDownload" href="#" download="og-preview.png"
class="btn btn-sm btn-outline-secondary d-none">
Download preview
</a>
</div>
</div>
<f:if condition="{savedImages}">
<div class="card">
<div class="card-header"><strong>Recent saved images</strong></div>
<div class="card-body p-0">
<table class="table table-sm table-hover mb-0">
<thead><tr><th>File</th><th>Created</th><th></th></tr></thead>
<tbody>
<f:for each="{savedImages}" as="img">
<tr>
<td class="text-truncate" style="max-width:140px">{img.name}</td>
<td><small>{img.created}</small></td>
<td>
<a href="{img.path}" target="_blank" class="btn btn-xs btn-outline-primary p-1 lh-1">
View
</a>
</td>
</tr>
</f:for>
</tbody>
</table>
</div>
</div>
</f:if>
</div><!-- /col preview -->
</div><!-- /row -->
</f:section>
</html>