Add global loader overlay and progress feedback for imports
This commit is contained in:
parent
fa4423acfe
commit
4ff7708f76
|
|
@ -540,6 +540,44 @@ main.container {
|
|||
color: #ff8a8a;
|
||||
}
|
||||
|
||||
.global-loader {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
backdrop-filter: blur(2px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.global-loader .loader-content {
|
||||
background: var(--color-bg-card);
|
||||
padding: 1.5rem 2rem;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--color-border);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
color: var(--color-text-primary);
|
||||
min-width: 280px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.global-loader .spinner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.2);
|
||||
border-top-color: var(--color-brand);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Detail views */
|
||||
.breadcrumb {
|
||||
margin-bottom: 1.5rem;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ function displayGlobalSearchResults(data) {
|
|||
|
||||
// Bulk Import Functions
|
||||
async function bulkImportAll() {
|
||||
showLoader('Importing all data from TPDB...');
|
||||
if (!confirm('This will import ALL data from TPDB. This may take several hours. Continue?')) {
|
||||
hideLoader();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -127,11 +129,15 @@ async function bulkImportAll() {
|
|||
}
|
||||
} catch (error) {
|
||||
setImportStatus('import-all', 'Error: ' + error.message, false);
|
||||
} finally {
|
||||
hideLoader();
|
||||
}
|
||||
}
|
||||
|
||||
async function bulkImportPerformers() {
|
||||
showLoader('Importing performers from TPDB...');
|
||||
if (!confirm('This will import ALL performers from TPDB. Continue?')) {
|
||||
hideLoader();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -165,11 +171,14 @@ async function bulkImportPerformers() {
|
|||
eventSource.onerror = function() {
|
||||
updateProgress('performers', 0, 0, 'Connection error', true);
|
||||
eventSource.close();
|
||||
hideLoader();
|
||||
};
|
||||
}
|
||||
|
||||
async function bulkImportStudios() {
|
||||
showLoader('Importing studios from TPDB...');
|
||||
if (!confirm('This will import ALL studios from TPDB. Continue?')) {
|
||||
hideLoader();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -203,11 +212,14 @@ async function bulkImportStudios() {
|
|||
eventSource.onerror = function() {
|
||||
updateProgress('studios', 0, 0, 'Connection error', true);
|
||||
eventSource.close();
|
||||
hideLoader();
|
||||
};
|
||||
}
|
||||
|
||||
async function bulkImportScenes() {
|
||||
showLoader('Importing scenes from TPDB...');
|
||||
if (!confirm('This will import ALL scenes from TPDB. Continue?')) {
|
||||
hideLoader();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -241,6 +253,7 @@ async function bulkImportScenes() {
|
|||
eventSource.onerror = function() {
|
||||
updateProgress('scenes', 0, 0, 'Connection error', true);
|
||||
eventSource.close();
|
||||
hideLoader();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -291,6 +304,7 @@ async function aeImportPerformerByName() {
|
|||
const name = prompt('Import performer by name (Adult Empire):');
|
||||
if (!name) return;
|
||||
setAEStatus(`Searching Adult Empire for "${name}"...`);
|
||||
showLoader(`Importing performer "${name}" from Adult Empire...`);
|
||||
try {
|
||||
const res = await fetch('/api/ae/import/performer', {
|
||||
method: 'POST',
|
||||
|
|
@ -306,6 +320,8 @@ async function aeImportPerformerByName() {
|
|||
}
|
||||
} catch (err) {
|
||||
setAEStatus(`Error: ${err.message}`, true);
|
||||
} finally {
|
||||
hideLoader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,6 +329,7 @@ async function aeImportPerformerByURL() {
|
|||
const url = prompt('Paste Adult Empire performer URL:');
|
||||
if (!url) return;
|
||||
setAEStatus('Importing performer from Adult Empire URL...');
|
||||
showLoader('Importing performer from Adult Empire URL...');
|
||||
try {
|
||||
const res = await fetch('/api/ae/import/performer-by-url', {
|
||||
method: 'POST',
|
||||
|
|
@ -328,6 +345,8 @@ async function aeImportPerformerByURL() {
|
|||
}
|
||||
} catch (err) {
|
||||
setAEStatus(`Error: ${err.message}`, true);
|
||||
} finally {
|
||||
hideLoader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,6 +354,7 @@ async function aeImportSceneByName() {
|
|||
const title = prompt('Import scene by title (Adult Empire):');
|
||||
if (!title) return;
|
||||
setAEStatus(`Searching Adult Empire for "${title}"...`);
|
||||
showLoader(`Importing scene "${title}" from Adult Empire...`);
|
||||
try {
|
||||
const res = await fetch('/api/ae/import/scene', {
|
||||
method: 'POST',
|
||||
|
|
@ -350,6 +370,8 @@ async function aeImportSceneByName() {
|
|||
}
|
||||
} catch (err) {
|
||||
setAEStatus(`Error: ${err.message}`, true);
|
||||
} finally {
|
||||
hideLoader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -357,6 +379,7 @@ async function aeImportSceneByURL() {
|
|||
const url = prompt('Paste Adult Empire scene URL:');
|
||||
if (!url) return;
|
||||
setAEStatus('Importing scene from Adult Empire URL...');
|
||||
showLoader('Importing scene from Adult Empire URL...');
|
||||
try {
|
||||
const res = await fetch('/api/ae/import/scene-by-url', {
|
||||
method: 'POST',
|
||||
|
|
@ -372,6 +395,8 @@ async function aeImportSceneByURL() {
|
|||
}
|
||||
} catch (err) {
|
||||
setAEStatus(`Error: ${err.message}`, true);
|
||||
} finally {
|
||||
hideLoader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -539,6 +564,23 @@ function setImportStatus(type, message, success) {
|
|||
}
|
||||
|
||||
// Close modals when clicking outside
|
||||
|
||||
// Global loader helpers
|
||||
function showLoader(msg) {
|
||||
const overlay = document.getElementById('global-loader');
|
||||
const text = document.getElementById('global-loader-text');
|
||||
if (overlay) {
|
||||
overlay.style.display = 'flex';
|
||||
}
|
||||
if (text && msg) {
|
||||
text.textContent = msg;
|
||||
}
|
||||
}
|
||||
|
||||
function hideLoader() {
|
||||
const overlay = document.getElementById('global-loader');
|
||||
if (overlay) overlay.style.display = 'none';
|
||||
}
|
||||
window.onclick = function(event) {
|
||||
if (event.target.classList.contains('modal')) {
|
||||
event.target.classList.remove('active');
|
||||
|
|
|
|||
|
|
@ -57,4 +57,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="global-loader" class="global-loader" style="display:none;">
|
||||
<div class="loader-content">
|
||||
<div class="spinner"></div>
|
||||
<div id="global-loader-text">Working...</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user