brewlog/templates/partials/image_upload.html
Jon Seager 920931ba17
refactor: fix template review findings (security, macros, tokens)
Address findings from the templates code review:

- Fix XSS in admin.html onclick handlers via data attributes
- Fix XSS in 5 edit page signal initializations via JSON serialization
- Fix register.html token exposure by moving to data attribute
- Add entity_icon, quick_notes_toggles, add_form_submit macros
- Replace hardcoded colors with design tokens (warning, error, success)
- Add warning design tokens to CSS theme
- Scope MutationObserver to main element
- Add defer to webauthn.js script tags
- Refactor login/register JS to arrow functions
- Guard lightbox script behind image_url check
- Fix else-if to elif in 5 templates
2026-02-13 16:20:30 +00:00

52 lines
2.2 KiB
HTML

<div id="entity-image">
{% if let Some(url) = image_url %}
<div class="relative rounded-lg border bg-surface overflow-hidden">
<div
class="h-48 w-full bg-cover bg-center"
style="background-image: url('{{ url }}')"
role="img"
aria-label="{{ entity_type }} image"
></div>
{% if is_authenticated %}
<div class="absolute top-2 right-2 flex gap-1">
<image-upload
entity-type="{{ entity_type }}"
entity-id="{{ entity_id }}"
mode="replace"
class="inline-flex items-center gap-1 rounded border bg-surface/90 px-2 py-1 text-xs font-medium text-accent hover:bg-surface cursor-pointer backdrop-blur-sm"
>
Replace
</image-upload>
<button
onclick="if(confirm('Remove this image?')){fetch('/api/v1/{{ entity_type }}/{{ entity_id }}/image',{method:'DELETE',headers:{'datastar-request':'true'}}).then(r=>r.text()).then(h=>{document.getElementById('entity-image').outerHTML=h})}"
class="inline-flex items-center gap-1 rounded border bg-surface/90 px-2 py-1 text-xs font-medium text-error hover:bg-surface cursor-pointer backdrop-blur-sm"
>
Remove
</button>
</div>
{% endif %}
</div>
{% elif is_authenticated %}
<image-upload
entity-type="{{ entity_type }}"
entity-id="{{ entity_id }}"
mode="upload"
class="flex flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed border-text-muted/30 bg-surface p-6 text-center text-text-muted cursor-pointer hover:border-accent/40 hover:text-text-secondary transition"
>
<svg
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="1.5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 21h16.5A2.25 2.25 0 0022.5 18.75V5.25A2.25 2.25 0 0020.25 3H3.75A2.25 2.25 0 001.5 5.25v13.5A2.25 2.25 0 003.75 21z"
/>
</svg>
<span class="text-sm">Drop image, browse, or take a photo</span>
</image-upload>
{% endif %}
</div>