Use toast notifications over JavaScript alerts (#37)
Implement UI toast notifications
This commit is contained in:
committed by
GitHub
parent
99b4a3152d
commit
1b9b7e203e
@@ -268,9 +268,9 @@
|
|||||||
|
|
||||||
if (!response.ok) throw new Error(await response.text());
|
if (!response.ok) throw new Error(await response.text());
|
||||||
|
|
||||||
alert('Configuration saved successfully!');
|
createToast('Configuration saved successfully!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(`Error saving configuration: ${error.message}`);
|
createToast(`Error saving configuration: ${error.message}`, 'error');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -68,11 +68,11 @@
|
|||||||
.filter(url => url.length > 0);
|
.filter(url => url.length > 0);
|
||||||
|
|
||||||
if (urls.length === 0) {
|
if (urls.length === 0) {
|
||||||
alert('Please submit at least one torrent');
|
createToast('Please submit at least one torrent', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (urls.length >= 100) {
|
if (urls.length >= 100) {
|
||||||
alert('Please submit less than 100 torrents at a time');
|
createToast('Please submit less than 100 torrents at a time', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,12 +92,16 @@
|
|||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (!response.ok) throw new Error(result.error || 'Unknown error');
|
if (!response.ok) throw new Error(result.error || 'Unknown error');
|
||||||
if (result.errors && result.errors.length > 0) {
|
if (result.errors && result.errors.length > 0) {
|
||||||
alert(`Added ${result.results.length} torrents with ${result.errors.length} errors:\n${result.errors.join('\n')}`);
|
if (result.results.length > 0) {
|
||||||
|
createToast(`Added ${result.results.length} torrents with ${result.errors.length} errors:\n${result.errors.join('\n')}`, 'warning');
|
||||||
|
} else {
|
||||||
|
createToast(`Failed to add torrents:\n${result.errors.join('\n')}`, 'error');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
alert(`Successfully added ${result.results.length} torrents!`);
|
createToast(`Successfully added ${result.results.length} torrents!`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(`Error adding downloads: ${error.message}`);
|
createToast(`Error adding downloads: ${error.message}`, 'error');
|
||||||
} finally {
|
} finally {
|
||||||
submitBtn.disabled = false;
|
submitBtn.disabled = false;
|
||||||
submitBtn.innerHTML = originalText;
|
submitBtn.innerHTML = originalText;
|
||||||
|
|||||||
@@ -170,9 +170,10 @@
|
|||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
});
|
});
|
||||||
await loadTorrents();
|
await loadTorrents();
|
||||||
|
createToast('Torrent deleted successfully');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting torrent:', error);
|
console.error('Error deleting torrent:', error);
|
||||||
alert('Failed to delete torrent');
|
createToast('Failed to delete torrent', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +186,10 @@
|
|||||||
);
|
);
|
||||||
await Promise.all(deletePromises);
|
await Promise.all(deletePromises);
|
||||||
await loadTorrents();
|
await loadTorrents();
|
||||||
|
createToast('Selected torrents deleted successfully');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting torrents:', error);
|
console.error('Error deleting torrents:', error);
|
||||||
alert('Failed to delete some torrents');
|
createToast('Failed to delete some torrents' , 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||||
|
<!-- Toast messages will be created dynamically here -->
|
||||||
|
</div>
|
||||||
<nav class="navbar navbar-expand-lg navbar-light mb-4">
|
<nav class="navbar navbar-expand-lg navbar-light mb-4">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="/">
|
<a class="navbar-brand" href="/">
|
||||||
@@ -115,6 +118,52 @@
|
|||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
/**
|
||||||
|
* Create a toast message
|
||||||
|
* @param {string} message - The message to display
|
||||||
|
* @param {string} [type='success'] - The type of toast (success, warning, error)
|
||||||
|
*/
|
||||||
|
const createToast = (message, type = 'success') => {
|
||||||
|
type = ['success', 'warning', 'error'].includes(type) ? type : 'success';
|
||||||
|
|
||||||
|
const toastTimeouts = {
|
||||||
|
success: 5000,
|
||||||
|
warning: 10000,
|
||||||
|
error: 15000
|
||||||
|
}
|
||||||
|
|
||||||
|
const toastContainer = document.querySelector('.toast-container');
|
||||||
|
const toastId = `toast-${Date.now()}`;
|
||||||
|
|
||||||
|
const toastHtml = `
|
||||||
|
<div id="${toastId}" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||||
|
<div class="toast-header ${type === 'error' ? 'bg-danger text-white' : type === 'warning' ? 'bg-warning text-dark' : 'bg-success text-white'}">
|
||||||
|
<strong class="me-auto">
|
||||||
|
${type === 'error' ? 'Error' : type === 'warning' ? 'Warning' : 'Success'}
|
||||||
|
</strong>
|
||||||
|
<button type="button" class="btn-close ${type === 'warning' ? '' : 'btn-close-white'}" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="toast-body">
|
||||||
|
${message.replace(/\n/g, '<br>')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
toastContainer.insertAdjacentHTML('beforeend', toastHtml);
|
||||||
|
|
||||||
|
const toastElement = document.getElementById(toastId);
|
||||||
|
const toast = new bootstrap.Toast(toastElement, {
|
||||||
|
autohide: true,
|
||||||
|
delay: toastTimeouts[type]
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.show();
|
||||||
|
|
||||||
|
toastElement.addEventListener('hidden.bs.toast', () => {
|
||||||
|
toastElement.remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
fetch('/internal/version')
|
fetch('/internal/version')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
let mediaIds = document.getElementById('mediaIds').value.split(',').map(id => id.trim());
|
let mediaIds = document.getElementById('mediaIds').value.split(',').map(id => id.trim());
|
||||||
let arr = document.getElementById('arrSelect').value;
|
let arr = document.getElementById('arrSelect').value;
|
||||||
if (!arr) {
|
if (!arr) {
|
||||||
alert('Please select an Arr instance');
|
createToast('Please select an Arr instance', 'warning');
|
||||||
submitBtn.disabled = false;
|
submitBtn.disabled = false;
|
||||||
submitBtn.innerHTML = originalText;
|
submitBtn.innerHTML = originalText;
|
||||||
return;
|
return;
|
||||||
@@ -81,9 +81,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) throw new Error(await response.text());
|
if (!response.ok) throw new Error(await response.text());
|
||||||
alert('Repair process initiated successfully!');
|
createToast('Repair process initiated successfully!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(`Error starting repair: ${error.message}`);
|
createToast(`Error starting repair: ${error.message}`, 'error');
|
||||||
} finally {
|
} finally {
|
||||||
submitBtn.disabled = false;
|
submitBtn.disabled = false;
|
||||||
submitBtn.innerHTML = originalText;
|
submitBtn.innerHTML = originalText;
|
||||||
|
|||||||
Reference in New Issue
Block a user