289 lines
15 KiB
HTML
289 lines
15 KiB
HTML
<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>
|