diff --git a/gateway/sds_gateway/static/js/actions/DownloadActionManager.js b/gateway/sds_gateway/static/js/actions/DownloadActionManager.js index 370112f00..ca33ca45d 100644 --- a/gateway/sds_gateway/static/js/actions/DownloadActionManager.js +++ b/gateway/sds_gateway/static/js/actions/DownloadActionManager.js @@ -80,7 +80,6 @@ class DownloadActionManager { e.stopPropagation(); const captureUuid = button.getAttribute("data-capture-uuid"); - const captureName = button.getAttribute("data-capture-name"); if (!this.permissions.canDownload()) { this.showToast( @@ -90,7 +89,7 @@ class DownloadActionManager { return; } - this.handleCaptureDownload(captureUuid, captureName, button); + this.handleCaptureDownload(captureUuid, button); }); } } @@ -181,60 +180,101 @@ class DownloadActionManager { } /** - * Handle capture download + * Handle capture download (modal copy comes from web_download_modal.html) * @param {string} captureUuid - Capture UUID - * @param {string} captureName - Capture name + * @param {Element} [button] - Optional row action button for loading state */ - async handleCaptureDownload(captureUuid, captureName) { - // Update modal content for capture - const modalTitleElement = document.getElementById("webDownloadModalLabel"); - const modalNameElement = document.getElementById("webDownloadDatasetName"); - const confirmBtn = document.getElementById("confirmWebDownloadBtn"); - - if (modalTitleElement) { - await window.DOMUtils.renderContent(modalTitleElement, { - icon: "download", - text: "Download Capture", - }); + async handleCaptureDownload(captureUuid, button) { + const modalId = `webDownloadModal-${captureUuid}`; + const modal = document.getElementById(modalId); + if (!modal) { + console.warn(`Web download modal not found for capture ${captureUuid}`); + return; } - if (modalNameElement) { - modalNameElement.textContent = captureName || "Unnamed Capture"; + const confirmBtn = document.getElementById( + `confirmWebDownloadBtn-${captureUuid}`, + ); + + if (!confirmBtn) { + console.warn( + `Web download confirm button not found for capture ${captureUuid}`, + ); + return; } - if (confirmBtn) { - // Update button text for capture - await window.DOMUtils.renderContent(confirmBtn, { - icon: "download", - text: "Yes, Download Capture", - }); + const newConfirmBtn = confirmBtn.cloneNode(true); + confirmBtn.parentNode.replaceChild(newConfirmBtn, confirmBtn); - // Update the dataset UUID to capture UUID for the API call - confirmBtn.dataset.datasetUuid = captureUuid; - confirmBtn.dataset.datasetName = captureName; - - // Override the API endpoint for captures by temporarily modifying the fetch URL - const originalFetch = window.fetch; - window.fetch = (url, options) => { - const modifiedUrl = url.includes( - `/users/download-item/dataset/${captureUuid}/`, - ) - ? `/users/download-item/capture/${captureUuid}/` - : url; - return originalFetch(modifiedUrl, options); - }; - - // Restore fetch after modal is hidden - const modal = document.getElementById("webDownloadModal"); - const restoreFetch = () => { - window.fetch = originalFetch; - modal.removeEventListener("hidden.bs.modal", restoreFetch); - }; - modal.addEventListener("hidden.bs.modal", restoreFetch); - } + const originalRowButtonContent = button?.innerHTML; - // Show the modal - window.DOMUtils.openModal("webDownloadModal"); + newConfirmBtn.onclick = async () => { + window.DOMUtils.closeModal(modalId); + + if (button) { + await window.DOMUtils.renderLoading(button, "Processing...", { + format: "spinner", + size: "sm", + }); + button.disabled = true; + } + + try { + const response = await window.APIClient.post( + `/users/download-item/capture/${captureUuid}/`, + {}, + ); + + if (response.success === true) { + if (button) { + await window.DOMUtils.renderContent(button, { + icon: "check-circle", + color: "success", + text: "Download Requested", + }); + } + this.showToast( + response.message || + "Download request submitted successfully! You will receive an email when ready.", + "success", + ); + } else { + if (button) { + await window.DOMUtils.renderContent(button, { + icon: "exclamation-triangle", + color: "danger", + text: "Request Failed", + }); + } + this.showToast( + response.message || "Download request failed. Please try again.", + "danger", + ); + } + } catch (error) { + console.error("Download error:", error); + if (button) { + await window.DOMUtils.renderContent(button, { + icon: "exclamation-triangle", + color: "danger", + text: "Request Failed", + }); + } + this.showToast( + error.message || "An error occurred while processing your request.", + "danger", + ); + } finally { + if (button && originalRowButtonContent !== undefined) { + setTimeout(() => { + button.innerHTML = originalRowButtonContent; + button.disabled = false; + }, 3000); + } + } + }; + + window.DOMUtils.openModal(modalId); } /** @@ -258,14 +298,13 @@ class DownloadActionManager { e.stopPropagation(); const datasetUuid = button.getAttribute("data-dataset-uuid"); - const datasetName = button.getAttribute("data-dataset-name"); if (!datasetUuid) { console.warn("Web download button missing dataset-uuid attribute"); return; } - this.openWebDownloadModal(datasetUuid, datasetName); + this.openWebDownloadModal(datasetUuid); }); } } @@ -303,11 +342,10 @@ class DownloadActionManager { } /** - * Open web download modal for a specific dataset + * Open web download modal for a specific dataset (labels from web_download_modal.html) * @param {string} datasetUuid - Dataset UUID - * @param {string} datasetName - Dataset name */ - openWebDownloadModal(datasetUuid, datasetName) { + openWebDownloadModal(datasetUuid) { const modalId = `webDownloadModal-${datasetUuid}`; const modal = document.getElementById(modalId); if (!modal) { @@ -315,23 +353,15 @@ class DownloadActionManager { return; } - // Set the dataset name in the modal (find within this specific modal) - const nameElement = modal.querySelector("#webDownloadDatasetName"); - if (nameElement) { - nameElement.textContent = datasetName || "this dataset"; - } - - // Store dataset info in the download button (find within this specific modal) - const confirmBtn = modal.querySelector("#confirmWebDownloadBtn"); + const confirmBtn = document.getElementById( + `confirmWebDownloadBtn-${datasetUuid}`, + ); if (!confirmBtn) { console.warn(`Confirm button not found for dataset ${datasetUuid}`); return; } - confirmBtn.dataset.datasetUuid = datasetUuid; - confirmBtn.dataset.datasetName = datasetName; - // Remove any existing event listeners by cloning const newConfirmBtn = confirmBtn.cloneNode(true); confirmBtn.parentNode.replaceChild(newConfirmBtn, confirmBtn); @@ -490,7 +520,6 @@ class DownloadActionManager { e.stopPropagation(); const captureUuid = button.getAttribute("data-capture-uuid"); - const captureName = button.getAttribute("data-capture-name"); if (!this.permissions.canDownload()) { this.showToast( @@ -500,7 +529,7 @@ class DownloadActionManager { return; } - this.handleCaptureDownload(captureUuid, captureName, button); + this.handleCaptureDownload(captureUuid, button); }); } } diff --git a/gateway/sds_gateway/static/js/actions/__tests__/DownloadActionManager.test.js b/gateway/sds_gateway/static/js/actions/__tests__/DownloadActionManager.test.js index 7a6546bf0..8db67530c 100644 --- a/gateway/sds_gateway/static/js/actions/__tests__/DownloadActionManager.test.js +++ b/gateway/sds_gateway/static/js/actions/__tests__/DownloadActionManager.test.js @@ -66,10 +66,10 @@ describe("DownloadActionManager", () => { if (id === "downloadModal") return mockModal; if (id === "downloadDatasetName") return { textContent: "" }; if (id === "confirmDownloadBtn") return mockButton; - if (id === "webDownloadModal") return mockModal; - if (id === "webDownloadModalLabel") return { innerHTML: "" }; - if (id === "webDownloadDatasetName") return { textContent: "" }; - if (id === "confirmWebDownloadBtn") return mockButton; + if (id.startsWith("webDownloadModal-")) return mockModal; + if (id.startsWith("webDownloadModalLabel-")) return { innerHTML: "" }; + if (id.startsWith("webDownloadDatasetName-")) return { textContent: "" }; + if (id.startsWith("confirmWebDownloadBtn-")) return mockButton; return null; }); @@ -102,7 +102,6 @@ describe("DownloadActionManager", () => { Promise.resolve({ success: true, message: "Download requested" }), }), ); - global.window.showWebDownloadModal = jest.fn(); global.window.showAlert = jest.fn(); // Mock bootstrap globally @@ -319,18 +318,13 @@ describe("DownloadActionManager", () => { test("should handle capture download click with permissions", async () => { const captureUuid = "test-capture-uuid"; - const captureName = "Test Capture"; // Ensure window.DOMUtils is properly set up window.DOMUtils = global.window.DOMUtils; // Test that the method exists and can be called without throwing await expect( - downloadManager.handleCaptureDownload( - captureUuid, - captureName, - mockButton, - ), + downloadManager.handleCaptureDownload(captureUuid, mockButton), ).resolves.not.toThrow(); }); @@ -385,15 +379,20 @@ describe("DownloadActionManager", () => { innerHTML: "", disabled: false, }; - document.getElementById = jest.fn(() => ({ - id: modalId, - querySelector: jest.fn((sel) => - sel === "#confirmWebDownloadBtn" ? confirmBtn : { textContent: "" }, - ), - addEventListener: jest.fn(), - })); + document.getElementById = jest.fn((id) => { + if (id === modalId) { + return { id: modalId, addEventListener: jest.fn() }; + } + if (id === "webDownloadDatasetName-test-uuid") { + return { textContent: "" }; + } + if (id === "confirmWebDownloadBtn-test-uuid") { + return confirmBtn; + } + return null; + }); - downloadManager.openWebDownloadModal("test-uuid", "Test Dataset"); + downloadManager.openWebDownloadModal("test-uuid"); expect(global.window.DOMUtils.openModal).toHaveBeenCalledWith(modalId); }); diff --git a/gateway/sds_gateway/static/js/file-list.js b/gateway/sds_gateway/static/js/file-list.js index 9997466cd..aba3069c9 100644 --- a/gateway/sds_gateway/static/js/file-list.js +++ b/gateway/sds_gateway/static/js/file-list.js @@ -824,7 +824,7 @@ class FileListCapturesTableManager extends CapturesTableManager { diff --git a/gateway/sds_gateway/templates/pages/home.html b/gateway/sds_gateway/templates/pages/home.html index e7e16ecc8..3b5a825fa 100644 --- a/gateway/sds_gateway/templates/pages/home.html +++ b/gateway/sds_gateway/templates/pages/home.html @@ -59,7 +59,7 @@
{{ dataset.name }} {% if dataset.is_public %}{% endif %}
@@ -161,8 +161,10 @@

SpectrumX Website

- - {% include "users/partials/dataset_details_modal.html" %} + + {% for dataset in latest_datasets %} + {% include "users/partials/dataset_details_modal.html" with dataset=dataset %} + {% endfor %} {% endblock body %} {% block javascript %} {{ block.super }} diff --git a/gateway/sds_gateway/templates/users/components/dataset_list_modals.html b/gateway/sds_gateway/templates/users/components/dataset_list_modals.html index f76f21e1a..d9475ea8f 100644 --- a/gateway/sds_gateway/templates/users/components/dataset_list_modals.html +++ b/gateway/sds_gateway/templates/users/components/dataset_list_modals.html @@ -5,7 +5,7 @@ {% endcomment %} {% for dataset in page_obj %} {% include "users/partials/dataset_details_modal.html" with dataset=dataset %} - {% include "users/partials/web_download_modal.html" with dataset=dataset %} + {% include "users/partials/web_download_modal.html" with item=dataset item_type="dataset" %} {% include "users/partials/share_modal.html" with item=dataset item_type="dataset" %} {% include "users/partials/sdk_download_modal.html" with dataset=dataset %} {% if dataset.is_owner or dataset.permission_level == 'co-owner' %} diff --git a/gateway/sds_gateway/templates/users/components/dataset_list_table.html b/gateway/sds_gateway/templates/users/components/dataset_list_table.html index 6ea2aae98..ad45ff497 100644 --- a/gateway/sds_gateway/templates/users/components/dataset_list_table.html +++ b/gateway/sds_gateway/templates/users/components/dataset_list_table.html @@ -1,17 +1,13 @@ {% comment %} -Dataset List Table Component -Renders the dataset table, results count, and pagination for AJAX updates +Single source for the dataset list table (full page + AJAX refresh). Context: -{ - "page_obj": Page object with datasets, - "sort_by": "name" | "created_at" | "updated_at" | "authors", - "sort_order": "asc" | "desc" -} +- page_obj, sort_by, sort_order (required) +- ajax_fragment: True for AJAX partial (omit outer #dataset-list-ajax-wrapper) {% endcomment %} {% load tz %} -{# Wrapper for list refresh; omitted in AJAX response to avoid nested IDs and duplicate count #} +{# Wrapper for ListRefreshManager; omitted when injecting into existing wrapper #} {% if not ajax_fragment %}
{% endif %} {% if page_obj.object_list %} @@ -70,21 +66,23 @@

No datasets yet

{% for dataset in page_obj %} - {% if dataset.is_public %} - + {% if dataset.is_owner %} + {{ dataset.name }} {% else %} - + {{ dataset.name }} {% endif %} - {{ dataset.name }} - {% if dataset.version > 1 %}v{{ dataset.version }}{% endif %} {% if dataset.status == 'draft' %} {{ dataset.status_display }} {% endif %} + {% if dataset.is_public %}{% endif %} {% if dataset.is_shared_with_me %} No datasets yet
- -{% if page_obj.object_list %} +{% if page_obj and page_obj.has_other_pages %} diff --git a/gateway/sds_gateway/templates/users/dataset_list.html b/gateway/sds_gateway/templates/users/dataset_list.html index 553f3bb79..baf0de549 100644 --- a/gateway/sds_gateway/templates/users/dataset_list.html +++ b/gateway/sds_gateway/templates/users/dataset_list.html @@ -26,7 +26,7 @@

Datasets


- {% include "users/partials/my_datasets_tab.html" %} + {% include "users/components/dataset_list_table.html" %} @@ -34,7 +34,7 @@

Datasets

{% for dataset in page_obj %} {% include "users/partials/dataset_details_modal.html" with dataset=dataset %} - {% include "users/partials/web_download_modal.html" with dataset=dataset %} + {% include "users/partials/web_download_modal.html" with item=dataset item_type="dataset" %} {% include "users/partials/share_modal.html" with item=dataset item_type="dataset" %} {% include "users/partials/sdk_download_modal.html" with dataset=dataset %} {% if dataset.is_owner or dataset.permission_level == 'co-owner' %} diff --git a/gateway/sds_gateway/templates/users/file_list.html b/gateway/sds_gateway/templates/users/file_list.html index 4a5884a96..105b75442 100644 --- a/gateway/sds_gateway/templates/users/file_list.html +++ b/gateway/sds_gateway/templates/users/file_list.html @@ -232,6 +232,17 @@

+ +
+ {% if captures %} + {% for cap in captures %} + {% include "users/partials/web_download_modal.html" with item=cap item_type="capture" %} + {% if cap.is_owner %} + {% include "users/partials/share_modal.html" with item=cap item_type="capture" %} + {% endif %} + {% endfor %} + {% endif %} +

- -
-
-
-
-
-
Download Capture
- -
-
-

Are you sure you want to download this capture?

-

- Capture: -

-
- -
-
-
- -{% for cap in captures %} - {% if cap.is_owner %} - {% include "users/partials/share_modal.html" with item=cap item_type="capture" %} - {% endif %} -{% endfor %} diff --git a/gateway/sds_gateway/templates/users/partials/my_datasets_tab.html b/gateway/sds_gateway/templates/users/partials/my_datasets_tab.html deleted file mode 100644 index f53155a90..000000000 --- a/gateway/sds_gateway/templates/users/partials/my_datasets_tab.html +++ /dev/null @@ -1,241 +0,0 @@ -{% load tz %} - - - -{% if page_obj.object_list %} -
- - {{ page_obj.paginator.count }} dataset{{ page_obj.paginator.count|pluralize }} found - -
-{% endif %} - -
-
-
- {% if not page_obj %} - - - - - - - - - - -
Your datasets list
- Dataset Name - - Author - - Created At - Actions
- - {% else %} - - - - - - - - - - - - {% for dataset in page_obj %} - - - - - - - {% endfor %} - -
Your datasets list
- Dataset Name - - Author - - Created At - Actions
- {% if dataset.is_owner %} - {{ dataset.name }} - {% else %} - {{ dataset.name }} - {% endif %} - {% if dataset.status == 'draft' %} - {{ dataset.status_display }} - {% endif %} - {% if dataset.is_public %}{% endif %} - {% if dataset.is_shared_with_me %} - - - - {% endif %} - - {% if dataset.authors %} - {% for author in dataset.authors %} - {% if forloop.counter <= 2 %} - {% if author.name %} - {% if author.orcid_id %} - - {{ author.name }} - - - {% else %} - {{ author.name }} - {% endif %} - {% if not forloop.last and forloop.counter < 2 and dataset.authors|length > 1 %},{% endif %} - {% else %} - {{ author }} - {% if not forloop.last and forloop.counter < 2 and dataset.authors|length > 1 %},{% endif %} - {% endif %} - {% endif %} - {% endfor %} - {% if dataset.authors|length > 2 %}...{% endif %} - {% else %} - - - {% endif %} - - {% if dataset.dataset.created_at %} - {% localtime on %} -
- {{ dataset.dataset.created_at|date:"Y-m-d" }} - {{ dataset.dataset.created_at|date:"H:i:s T" }} -
- {% endlocaltime %} - {% else %} - - - {% endif %} -
- -
- {% endif %} -
-
-
- -{% if page_obj and page_obj.has_other_pages %} - -{% endif %} diff --git a/gateway/sds_gateway/templates/users/partials/search_published_datasets_tab.html b/gateway/sds_gateway/templates/users/partials/search_published_datasets_tab.html index 20ec0ffd2..4556109ad 100644 --- a/gateway/sds_gateway/templates/users/partials/search_published_datasets_tab.html +++ b/gateway/sds_gateway/templates/users/partials/search_published_datasets_tab.html @@ -45,7 +45,7 @@

No datasets found

{{ dataset.name }} {% if dataset.is_public %}{% endif %} @@ -113,16 +113,17 @@

No datasets found