-
Notifications
You must be signed in to change notification settings - Fork 0
Dataset download zip email #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
gateway/sds_gateway/api_methods/management/commands/test_celery.py
Outdated
Show resolved
Hide resolved
to=[user_email], | ||
) | ||
|
||
email.attach(zip_filename, zip_buffer.getvalue(), "application/zip") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's provide a temporary download link instead, this can be GBs of data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's what I do on REDI-NET for several things. So maybe the process is actually save the zip file on the server so they can download it? what does temporary mean? As in, the link only exists for a period of time and disappears when they use it? should the zip file be cleaned out once it's downloaded or remain on the server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the link only exists for a period of time and disappears when they use it?
we can allow multiple uses (e.g. download failure), but let's make it expire in e.g. 24h and clean up the zip.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's also a case to be made about not recreating the zip if it already exists for a given dataset, but this could be a future PR. For example, multiple "download" clicks while the link is still valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document.addEventListener('DOMContentLoaded', function() { | ||
console.log('DOM loaded, looking for download buttons...'); | ||
|
||
// Handle download button clicks | ||
document.querySelectorAll('.download-dataset-btn').forEach(function(button) { | ||
console.log('Found download button:', button); | ||
button.addEventListener('click', function() { | ||
const datasetUuid = this.getAttribute('data-dataset-uuid'); | ||
const datasetName = this.getAttribute('data-dataset-name'); | ||
|
||
console.log('Download button clicked for dataset:', datasetUuid, datasetName); | ||
|
||
// Disable button and show loading state | ||
const originalText = this.innerHTML; | ||
this.innerHTML = '<i class="bi bi-hourglass-split"></i> Processing...'; | ||
this.disabled = true; | ||
|
||
// Make API request | ||
console.log('Making request to:', `/users/dataset-download/${datasetUuid}/`); | ||
fetch(`/users/dataset-download/${datasetUuid}/`, { | ||
method: 'POST', | ||
headers: { | ||
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, | ||
'Content-Type': 'application/json', | ||
}, | ||
}) | ||
.then(response => { | ||
console.log('Response status:', response.status); | ||
if (response.ok) { | ||
return response.json().then(data => { | ||
console.log('Success response:', data); | ||
// Show success message | ||
showAlert('success', `Download request sent for "${datasetName}". You will receive an email with the files shortly.`); | ||
this.innerHTML = '<i class="bi bi-check-circle"></i> Sent!'; | ||
this.classList.remove('btn-success'); | ||
this.classList.add('btn-secondary'); | ||
}); | ||
} else { | ||
return response.json().then(data => { | ||
console.log('Error response:', data); | ||
// Show error message | ||
const errorMessage = data.detail || data.message || 'Failed to send download request'; | ||
showAlert('danger', `Error: ${errorMessage}`); | ||
this.innerHTML = originalText; | ||
this.disabled = false; | ||
}); | ||
} | ||
}) | ||
.catch(error => { | ||
console.error('Network error:', error); | ||
showAlert('danger', 'Network error. Please try again.'); | ||
this.innerHTML = originalText; | ||
this.disabled = false; | ||
}); | ||
}); | ||
}); | ||
|
||
// Function to show alerts | ||
function showAlert(type, message) { | ||
const alertDiv = document.createElement('div'); | ||
alertDiv.className = `alert alert-${type} alert-dismissible fade show`; | ||
alertDiv.innerHTML = ` | ||
${message} | ||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> | ||
`; | ||
|
||
// Insert at the top of the content area | ||
const contentArea = document.querySelector('.main-content-area'); | ||
contentArea.insertBefore(alertDiv, contentArea.firstChild); | ||
|
||
// Auto-dismiss after 5 seconds | ||
setTimeout(() => { | ||
if (alertDiv.parentNode) { | ||
alertDiv.remove(); | ||
} | ||
}, 5000); | ||
} | ||
}); | ||
</script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove most (all?) console.log
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a usability improvement here, since downloads are async.
We should probably communicate these things to the user before starting the task, not verbatim:
- Expect an email with the download link sent to <email-address>;
- Ask for confirmation to proceed with download.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm doing soft deletion of the DB object but delete the actual files, this is a management command, maybe run this at some regular interval, probably not super often. I'm open to suggestions on how to handle the zip files when they expire. |
maybe running a celery's periodic task once or twice a day? |
SFDS-186
make test
,make test-integration
, andmake pre-commit
pass locally