mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-07-07 05:15:22 +02:00
Merge pull request #331
feat(export): improve export flow by using HTMX
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container p-3">
|
<div class="container p-3">
|
||||||
<form method="post" action="{% url 'export_form' %}" id="export-form" class="show-loading px-1" _="on submit trigger hide_offcanvas" target="_blank">
|
<form hx-post="{% url 'export_form' %}" hx-ext="htmx-download" hx-swap="none" id="export-form" class="show-loading px-1" target="_blank">
|
||||||
{% crispy form %}
|
{% crispy form %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -261,7 +261,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="btn-group w-100" role="group">
|
<div class="btn-group w-100 sidebar-item" role="group">
|
||||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-toggle="tooltip"
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-toggle="tooltip"
|
||||||
data-bs-title="{% trans "Calculator" %}"
|
data-bs-title="{% trans "Calculator" %}"
|
||||||
_="on click trigger show on #calculator">
|
_="on click trigger show on #calculator">
|
||||||
|
|||||||
@@ -1,2 +1,66 @@
|
|||||||
import htmx from "htmx.org";
|
import htmx from "htmx.org";
|
||||||
|
|
||||||
window.htmx = htmx;
|
window.htmx = htmx;
|
||||||
|
|
||||||
|
htmx.defineExtension('htmx-download', {
|
||||||
|
onEvent: function (name, evt) {
|
||||||
|
|
||||||
|
if (name === 'htmx:beforeRequest') {
|
||||||
|
// Set the responseType to 'arraybuffer' to handle binary data
|
||||||
|
evt.detail.xhr.responseType = 'arraybuffer';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'htmx:beforeSwap') {
|
||||||
|
const xhr = evt.detail.xhr;
|
||||||
|
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
// Parse headers
|
||||||
|
const headers = {};
|
||||||
|
const headerStr = xhr.getAllResponseHeaders();
|
||||||
|
const headerArr = headerStr.trim().split(/[\r\n]+/);
|
||||||
|
headerArr.forEach((line) => {
|
||||||
|
const parts = line.split(": ");
|
||||||
|
const header = parts.shift().toLowerCase();
|
||||||
|
const value = parts.join(": ");
|
||||||
|
headers[header] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract filename
|
||||||
|
let filename = 'downloaded_file.xlsx';
|
||||||
|
if (headers['content-disposition']) {
|
||||||
|
const filenameMatch = headers['content-disposition'].match(/filename\*?=(?:UTF-8'')?"?([^;\n"]+)/i);
|
||||||
|
if (filenameMatch && filenameMatch[1]) {
|
||||||
|
filename = decodeURIComponent(filenameMatch[1].replace(/['"]/g, ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine MIME type
|
||||||
|
const mimetype = headers['content-type'] || 'application/octet-stream';
|
||||||
|
|
||||||
|
// Create Blob
|
||||||
|
const blob = new Blob([xhr.response], {type: mimetype});
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
// Trigger download
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.style.display = "none";
|
||||||
|
link.href = url;
|
||||||
|
link.download = filename;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
setTimeout(() => {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
link.remove();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.warn(`[htmx-download] Unexpected response status: ${xhr.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent htmx from swapping content
|
||||||
|
evt.detail.shouldSwap = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user