Commit e37a9a8d authored by Stefy Lanza (nextime / spora )'s avatar Stefy Lanza (nextime / spora )

Merge remote-tracking branch 'refs/remotes/origin/master'

parents 607e46d6 4a984e2d
...@@ -528,78 +528,114 @@ ...@@ -528,78 +528,114 @@
</div> </div>
<script> <script>
const CHUNK_SIZE = 1024 * 1024; // 1MB chunks
let activeUploads = new Map(); let activeUploads = new Map();
function startUpload(matchId) { function uploadFileInChunks(file, matchId) {
const fileInput = document.getElementById(`zip_file_${matchId}`); const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
const file = fileInput.files[0]; const uploadId = Date.now() + '_' + Math.random().toString(36).substr(2, 9);
if (!file) { let currentChunk = 0;
return;
}
// Show progress bar and hide upload form // Show progress bar and hide upload form
const uploadForm = document.getElementById(`upload_form_${matchId}`); const uploadForm = document.getElementById(`upload_form_${matchId}`);
const progressContainer = document.getElementById(`progress_${matchId}`); const progressContainer = document.getElementById(`progress_${matchId}`);
const statusDiv = document.getElementById(`status_${matchId}`); const statusDiv = document.getElementById(`status_${matchId}`);
uploadForm.style.display = 'none'; uploadForm.style.display = 'none';
progressContainer.style.display = 'block'; progressContainer.style.display = 'block';
statusDiv.style.display = 'block'; statusDiv.style.display = 'block';
statusDiv.className = 'upload-status uploading'; statusDiv.className = 'upload-status uploading';
statusDiv.textContent = 'Uploading...'; statusDiv.textContent = 'Uploading... 0%';
// Create FormData function uploadChunk() {
const formData = new FormData(); if (currentChunk >= totalChunks) {
formData.append('zip_file', file); // All chunks uploaded, finalize
formData.append('match_id', matchId); finalizeUpload(uploadId, file.name, matchId);
return;
// Create XMLHttpRequest for progress tracking
const xhr = new XMLHttpRequest();
activeUploads.set(matchId, xhr);
// Progress event handler
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
const percentComplete = Math.round((e.loaded / e.total) * 100);
updateProgress(matchId, percentComplete);
} }
});
// Load event handler (upload complete) const start = currentChunk * CHUNK_SIZE;
xhr.addEventListener('load', function() { const end = Math.min(start + CHUNK_SIZE, file.size);
if (xhr.status === 200) { const chunk = file.slice(start, end);
// Success
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('chunkIndex', currentChunk);
formData.append('totalChunks', totalChunks);
formData.append('uploadId', uploadId);
formData.append('fileName', file.name);
formData.append('matchId', matchId);
fetch('/upload/chunk', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
currentChunk++;
const progress = (currentChunk / totalChunks) * 100;
updateProgress(matchId, Math.round(progress));
statusDiv.textContent = `Uploading... ${Math.round(progress)}%`;
uploadChunk();
} else {
throw new Error(data.error || 'Upload failed');
}
})
.catch(error => {
statusDiv.className = 'upload-status error';
statusDiv.textContent = 'Upload failed: ' + error.message;
});
}
uploadChunk();
}
function finalizeUpload(uploadId, fileName, matchId) {
const statusDiv = document.getElementById(`status_${matchId}`);
fetch('/upload/finalize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
uploadId: uploadId,
fileName: fileName,
matchId: matchId
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
updateProgress(matchId, 100); updateProgress(matchId, 100);
statusDiv.className = 'upload-status success'; statusDiv.className = 'upload-status success';
statusDiv.textContent = 'Upload successful!'; statusDiv.textContent = 'Upload successful!';
// Reload page after a short delay to show updated status // Reload page after a short delay to show updated status
setTimeout(() => { setTimeout(() => {
window.location.reload(); window.location.reload();
}, 1500); }, 1500);
} else { } else {
// Error statusDiv.className = 'upload-status error';
handleUploadError(matchId, 'Upload failed'); statusDiv.textContent = 'Finalization failed: ' + (data.error || 'Unknown error');
} }
activeUploads.delete(matchId); })
.catch(error => {
statusDiv.className = 'upload-status error';
statusDiv.textContent = 'Finalization failed: ' + error.message;
}); });
}
// Error event handler function startUpload(matchId) {
xhr.addEventListener('error', function() { const fileInput = document.getElementById(`zip_file_${matchId}`);
handleUploadError(matchId, 'Network error'); const file = fileInput.files[0];
activeUploads.delete(matchId);
});
// Abort event handler if (!file) {
xhr.addEventListener('abort', function() { return;
handleUploadError(matchId, 'Upload cancelled'); }
activeUploads.delete(matchId);
});
// Start upload uploadFileInChunks(file, matchId);
xhr.open('POST', '{{ url_for("upload.upload_zip") }}', true);
xhr.send(formData);
} }
function updateProgress(matchId, percent) { function updateProgress(matchId, percent) {
...@@ -651,80 +687,117 @@ ...@@ -651,80 +687,117 @@
// Fixture-level upload functionality // Fixture-level upload functionality
let fixtureUploadActive = false; let fixtureUploadActive = false;
function startFixtureUpload() { function uploadFixtureFileInChunks(file) {
const fileInput = document.getElementById('fixture_zip_file'); const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
const file = fileInput.files[0]; const uploadId = Date.now() + '_' + Math.random().toString(36).substr(2, 9);
if (!file) {
return;
}
if (fixtureUploadActive) { let currentChunk = 0;
return; // Prevent multiple uploads
}
fixtureUploadActive = true;
// Show progress bar and hide upload form // Show progress bar and hide upload form
const uploadForm = document.getElementById('fixture_upload_form'); const uploadForm = document.getElementById('fixture_upload_form');
const progressContainer = document.getElementById('fixture_progress_container'); const progressContainer = document.getElementById('fixture_progress_container');
const statusDiv = document.getElementById('fixture_upload_status'); const statusDiv = document.getElementById('fixture_upload_status');
uploadForm.style.display = 'none'; uploadForm.style.display = 'none';
progressContainer.style.display = 'block'; progressContainer.style.display = 'block';
statusDiv.style.display = 'block'; statusDiv.style.display = 'block';
statusDiv.className = 'upload-status uploading'; statusDiv.className = 'upload-status uploading';
statusDiv.textContent = 'Uploading to all matches...'; statusDiv.textContent = 'Uploading to all matches... 0%';
function uploadChunk() {
if (currentChunk >= totalChunks) {
// All chunks uploaded, finalize
finalizeFixtureUpload(uploadId, file.name);
return;
}
// Create FormData const start = currentChunk * CHUNK_SIZE;
const formData = new FormData(); const end = Math.min(start + CHUNK_SIZE, file.size);
formData.append('zip_file', file); const chunk = file.slice(start, end);
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('chunkIndex', currentChunk);
formData.append('totalChunks', totalChunks);
formData.append('uploadId', uploadId);
formData.append('fileName', file.name);
fetch('/upload/chunk', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
currentChunk++;
const progress = (currentChunk / totalChunks) * 100;
updateFixtureProgress(Math.round(progress));
statusDiv.textContent = `Uploading to all matches... ${Math.round(progress)}%`;
uploadChunk();
} else {
throw new Error(data.error || 'Upload failed');
}
})
.catch(error => {
statusDiv.className = 'upload-status error';
statusDiv.textContent = 'Upload failed: ' + error.message;
fixtureUploadActive = false;
});
}
// Create XMLHttpRequest for progress tracking uploadChunk();
const xhr = new XMLHttpRequest(); }
// Progress event handler function finalizeFixtureUpload(uploadId, fileName) {
xhr.upload.addEventListener('progress', function(e) { const statusDiv = document.getElementById('fixture_upload_status');
if (e.lengthComputable) {
const percentComplete = Math.round((e.loaded / e.total) * 100);
updateFixtureProgress(percentComplete);
}
});
// Load event handler (upload complete) fetch('/upload/finalize', {
xhr.addEventListener('load', function() { method: 'POST',
if (xhr.status === 200) { headers: {
// Success 'Content-Type': 'application/json',
},
body: JSON.stringify({
uploadId: uploadId,
fileName: fileName
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
updateFixtureProgress(100); updateFixtureProgress(100);
statusDiv.className = 'upload-status success'; statusDiv.className = 'upload-status success';
statusDiv.textContent = 'Upload successful! All matches are now active.'; statusDiv.textContent = 'Upload successful! All matches are now active.';
// Reload page after a short delay to show updated status // Reload page after a short delay to show updated status
setTimeout(() => { setTimeout(() => {
window.location.reload(); window.location.reload();
}, 2000); }, 2000);
} else { } else {
// Error statusDiv.className = 'upload-status error';
handleFixtureUploadError('Upload failed'); statusDiv.textContent = 'Finalization failed: ' + (data.error || 'Unknown error');
} }
fixtureUploadActive = false; fixtureUploadActive = false;
}); })
.catch(error => {
// Error event handler statusDiv.className = 'upload-status error';
xhr.addEventListener('error', function() { statusDiv.textContent = 'Finalization failed: ' + error.message;
handleFixtureUploadError('Network error');
fixtureUploadActive = false; fixtureUploadActive = false;
}); });
}
// Abort event handler function startFixtureUpload() {
xhr.addEventListener('abort', function() { const fileInput = document.getElementById('fixture_zip_file');
handleFixtureUploadError('Upload cancelled'); const file = fileInput.files[0];
fixtureUploadActive = false;
});
// Start upload if (!file) {
xhr.open('POST', uploadForm.action, true); return;
xhr.send(formData); }
if (fixtureUploadActive) {
return; // Prevent multiple uploads
}
fixtureUploadActive = true;
uploadFixtureFileInChunks(file);
} }
function updateFixtureProgress(percent) { function updateFixtureProgress(percent) {
......
...@@ -761,76 +761,113 @@ ...@@ -761,76 +761,113 @@
} }
// ZIP Upload Functions // ZIP Upload Functions
function startUpload(matchId) { const CHUNK_SIZE = 1024 * 1024; // 1MB chunks
const fileInput = document.getElementById(`zip_file_${matchId}`);
const file = fileInput.files[0]; function uploadFileInChunks(file, matchId) {
const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
if (!file) { const uploadId = Date.now() + '_' + Math.random().toString(36).substr(2, 9);
return;
} let currentChunk = 0;
// Show progress bar and hide upload form // Show progress bar and hide upload form
const uploadForm = document.getElementById(`upload_form_${matchId}`); const uploadForm = document.getElementById(`upload_form_${matchId}`);
const progressContainer = document.getElementById(`progress_${matchId}`); const progressContainer = document.getElementById(`progress_${matchId}`);
const statusDiv = document.getElementById(`status_${matchId}`); const statusDiv = document.getElementById(`status_${matchId}`);
uploadForm.style.display = 'none'; uploadForm.style.display = 'none';
progressContainer.style.display = 'block'; progressContainer.style.display = 'block';
statusDiv.style.display = 'block'; statusDiv.style.display = 'block';
statusDiv.className = 'upload-status uploading'; statusDiv.className = 'upload-status uploading';
statusDiv.textContent = 'Uploading...'; statusDiv.textContent = 'Uploading... 0%';
// Create FormData function uploadChunk() {
const formData = new FormData(); if (currentChunk >= totalChunks) {
formData.append('zip_file', file); // All chunks uploaded, finalize
formData.append('match_id', matchId); finalizeUpload(uploadId, file.name, matchId);
return;
}
// Create XMLHttpRequest for progress tracking const start = currentChunk * CHUNK_SIZE;
const xhr = new XMLHttpRequest(); const end = Math.min(start + CHUNK_SIZE, file.size);
activeUploads.set(matchId, xhr); const chunk = file.slice(start, end);
// Progress event handler const formData = new FormData();
xhr.upload.addEventListener('progress', function(e) { formData.append('chunk', chunk);
if (e.lengthComputable) { formData.append('chunkIndex', currentChunk);
const percentComplete = Math.round((e.loaded / e.total) * 100); formData.append('totalChunks', totalChunks);
updateProgress(matchId, percentComplete); formData.append('uploadId', uploadId);
} formData.append('fileName', file.name);
}); formData.append('matchId', matchId);
fetch('/upload/chunk', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
currentChunk++;
const progress = (currentChunk / totalChunks) * 100;
updateProgress(matchId, Math.round(progress));
statusDiv.textContent = `Uploading... ${Math.round(progress)}%`;
uploadChunk();
} else {
throw new Error(data.error || 'Upload failed');
}
})
.catch(error => {
statusDiv.className = 'upload-status error';
statusDiv.textContent = 'Upload failed: ' + error.message;
});
}
// Load event handler (upload complete) uploadChunk();
xhr.addEventListener('load', function() { }
if (xhr.status === 200) {
// Success function finalizeUpload(uploadId, fileName, matchId) {
const statusDiv = document.getElementById(`status_${matchId}`);
fetch('/upload/finalize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
uploadId: uploadId,
fileName: fileName,
matchId: matchId
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
updateProgress(matchId, 100); updateProgress(matchId, 100);
statusDiv.className = 'upload-status success'; statusDiv.className = 'upload-status success';
statusDiv.textContent = 'Upload successful!'; statusDiv.textContent = 'Upload successful!';
// Reload page after a short delay to show updated status // Reload page after a short delay to show updated status
setTimeout(() => { setTimeout(() => {
window.location.reload(); window.location.reload();
}, 1500); }, 1500);
} else { } else {
// Error statusDiv.className = 'upload-status error';
handleUploadError(matchId, 'Upload failed'); statusDiv.textContent = 'Finalization failed: ' + (data.error || 'Unknown error');
} }
activeUploads.delete(matchId); })
.catch(error => {
statusDiv.className = 'upload-status error';
statusDiv.textContent = 'Finalization failed: ' + error.message;
}); });
}
// Error event handler function startUpload(matchId) {
xhr.addEventListener('error', function() { const fileInput = document.getElementById(`zip_file_${matchId}`);
handleUploadError(matchId, 'Network error'); const file = fileInput.files[0];
activeUploads.delete(matchId);
});
// Abort event handler if (!file) {
xhr.addEventListener('abort', function() { return;
handleUploadError(matchId, 'Upload cancelled'); }
activeUploads.delete(matchId);
});
// Start upload uploadFileInChunks(file, matchId);
xhr.open('POST', '{{ url_for("upload.upload_zip") }}', true);
xhr.send(formData);
} }
function updateProgress(matchId, percent) { function updateProgress(matchId, percent) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment