imaging: add visual feedback to device-id copy button

Click effect: button flashes green with "copied!" text and 1.15x
scale pulse, reverts after 1.2s. Failure case (clipboard API blocked
or HTTP context) shows red "failed" for 1.5s. Handler moved out of
inline onclick into a single delegated click listener at the doc
level so future copy buttons just need the .copy-btn class +
data-copy-text attribute.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-05-13 18:29:00 -04:00
parent 59dbd64e37
commit 6275a6a2b3

View File

@@ -45,9 +45,9 @@
{% if s.pctype %}<span class="badge bg-info text-dark ms-2">{{ s.pctype }}</span>{% endif %} {% if s.pctype %}<span class="badge bg-info text-dark ms-2">{{ s.pctype }}</span>{% endif %}
{% if s.machinenumber %}<span class="badge bg-secondary ms-1">#{{ s.machinenumber }}</span>{% endif %} {% if s.machinenumber %}<span class="badge bg-secondary ms-1">#{{ s.machinenumber }}</span>{% endif %}
{% if s.intune_device_id %}<div class="small text-muted mt-1">Intune: <code>{{ s.intune_device_id }}</code> {% if s.intune_device_id %}<div class="small text-muted mt-1">Intune: <code>{{ s.intune_device_id }}</code>
<button type="button" class="btn btn-sm btn-outline-secondary py-0 px-1 ms-1" <button type="button" class="btn btn-sm btn-outline-secondary py-0 px-1 ms-1 copy-btn"
style="font-size:0.7rem; line-height:1;" style="font-size:0.7rem; line-height:1; transition: all 0.2s;"
onclick="navigator.clipboard.writeText('{{ s.intune_device_id }}').then(()=>{this.textContent='copied';setTimeout(()=>{this.textContent='copy'},1500)});">copy</button> data-copy-text="{{ s.intune_device_id }}">copy</button>
</div>{% endif %} </div>{% endif %}
</div> </div>
</div> </div>
@@ -135,3 +135,37 @@ Content-Type: application/json
</div> </div>
{% endblock %} {% endblock %}
{% block extra_scripts %}
<script>
document.addEventListener('click', function(e) {
var btn = e.target.closest('.copy-btn');
if (!btn) return;
var text = btn.getAttribute('data-copy-text');
if (!text) return;
navigator.clipboard.writeText(text).then(function() {
var origText = btn.dataset.origText || btn.textContent;
btn.dataset.origText = origText;
btn.textContent = 'copied!';
btn.classList.remove('btn-outline-secondary');
btn.classList.add('btn-success');
btn.style.transform = 'scale(1.15)';
setTimeout(function() {
btn.textContent = origText;
btn.classList.remove('btn-success');
btn.classList.add('btn-outline-secondary');
btn.style.transform = 'scale(1)';
}, 1200);
}).catch(function(err) {
btn.textContent = 'failed';
btn.classList.remove('btn-outline-secondary');
btn.classList.add('btn-danger');
setTimeout(function() {
btn.textContent = btn.dataset.origText || 'copy';
btn.classList.remove('btn-danger');
btn.classList.add('btn-outline-secondary');
}, 1500);
});
});
</script>
{% endblock %}