[Perl] DAQ system for the FAPG.
fix preserve selected download format
Show a spinner and disable the selected download button while its file is prepared. Use the clicked button action so XLSX downloads do not fall back to CSV.
Changed files
roles/dashboard/public/js/downloads.js
@@ -4,6 +4,7 @@
4
4
const downloadTo = document.querySelector("#download-to");
5
5
const errorBanner = document.querySelector("[data-downloads-error]");
6
6
const form = document.querySelector("form.downloads-form");
7
Added:
let submittedButton = null;
7
8
8
9
downloadRangeButtons.forEach(option => {
9
10
option.addEventListener("change", () => {
@@ -57,13 +58,31 @@
57
58
return match ? match[1] : "readings.csv";
58
59
}
59
60
61
Added:
function setDownloadPending(button, pending) {
62
Added:
if (!button) return;
63
Added:
64
Added:
button.disabled = pending;
65
Added:
button.setAttribute("aria-busy", pending ? "true" : "false");
66
Added:
button.querySelector("[data-download-spinner]")?.classList.toggle("d-none", !pending);
67
Added:
}
68
Added:
60
69
if (form) {
70
Added:
form.querySelectorAll("[data-download-button]").forEach(button => {
71
Added:
button.addEventListener("click", () => {
72
Added:
submittedButton = button;
73
Added:
});
74
Added:
});
75
Added:
61
76
form.addEventListener("submit", async event => {
62
77
event.preventDefault();
63
78
clearError();
64
79
80
Added:
const button = event.submitter || submittedButton || form.querySelector("[data-download-button]");
65
81
const params = new URLSearchParams(new FormData(form));
66
Removed:
const url = `${form.action}?${params}`;
82
Added:
const action = button?.getAttribute("formaction") || form.action;
83
Added:
const url = new URL(action, window.location.origin);
84
Added:
url.search = params;
85
Added:
setDownloadPending(button, true);
67
86
68
87
try {
69
88
const response = await fetch(url);
@@ -78,6 +97,9 @@
78
97
triggerDownload(blob, filenameFromResponse(response));
79
98
} catch (err) {
80
99
showError("Could not reach the server. Check your connection and try again.");
100
Added:
} finally {
101
Added:
setDownloadPending(button, false);
102
Added:
submittedButton = null;
81
103
}
82
104
});
83
105
}
roles/dashboard/t/06-downloads.t
@@ -29,10 +29,15 @@
29
29
'[data-custom-date-fields][hidden] input[name="from"][type="date"]')
30
30
->element_exists(
31
31
'[data-custom-date-fields][hidden] input[name="to"][type="date"]')
32
Removed:
->text_is( 'button.downloads-button[type="submit"]', 'Download CSV' )
33
Removed:
->text_is(
32
Added:
->text_like( 'button.downloads-button[type="submit"]', qr/Download CSV/ )
33
Added:
->element_exists(
34
Added:
'button.downloads-button[type="submit"][data-download-button] [data-download-spinner].d-none')
35
Added:
->text_like(
34
36
'button.downloads-button[type="submit"][formaction="/downloads/readings.xlsx"]',
35
Removed:
'Download .xlsx' );
37
Added:
qr/Download \.xlsx/ )
38
Added:
->element_exists(
39
Added:
'button.downloads-button[type="submit"][formaction="/downloads/readings.xlsx"][data-download-button] [data-download-spinner].d-none'
40
Added:
);
36
41
37
42
for my $probe (qw(ph do orp ec)) {
38
43
$t->element_exists(qq{select#download-probe option[value="$probe"]});
roles/dashboard/templates/dashboard/downloads.html.ep
@@ -55,8 +55,14 @@
55
55
</fieldset>
56
56
57
57
<div>
58
Removed:
<button class="btn btn-success downloads-button" type="submit">Download CSV</button>
59
Removed:
<button class="btn btn-outline-success downloads-button" type="submit" formaction="/downloads/readings.xlsx">Download .xlsx</button>
58
Added:
<button class="btn btn-success downloads-button" type="submit" data-download-button>
59
Added:
<span class="spinner-border spinner-border-sm d-none" aria-hidden="true" data-download-spinner></span>
60
Added:
Download CSV
61
Added:
</button>
62
Added:
<button class="btn btn-outline-success downloads-button" type="submit" formaction="/downloads/readings.xlsx" data-download-button>
63
Added:
<span class="spinner-border spinner-border-sm d-none" aria-hidden="true" data-download-spinner></span>
64
Added:
Download .xlsx
65
Added:
</button>
60
66
</div>
61
67
62
68
</form>