Merge pull request 'feat(ui): unify backup/restore progress modals with the runbackup theme' (#281) from feat/unified-progress-theme into dev
This commit was merged in pull request #281.
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
### Fixed
|
||||
- Database view "One Problem" on MokoSuiteBackup: reconciled the `#__mokosuitebackup_profiles` schema-checker output with the update-file history. Corrected the stale `TINYINT` definition in `01.01.01.sql` to the final `VARCHAR(20)` type, fixed the `MODIFY COLUMN` parser trip-up in `01.39.00.sql`, and rewrote the retired `sftp_*` `ADD COLUMN` statements in `01.35.00.sql`/`01.36.00.sql` as bare `ADD` so Joomla's checker no longer demands columns that `02.52.25` and the postflight purge deliberately remove. Joomla's schema checker now reports no problems.
|
||||
|
||||
### Changed
|
||||
- Backup/restore progress modals in the backups view now use the same full-screen black, big-text, animated Atum-coloured progress-bar theme as the `runbackup` screen, so all backup progress surfaces match. New `media/css/backup-progress.css` scopes the black to the modal (the list page is unaffected until a modal opens).
|
||||
|
||||
## [02.64.00] --- 2026-07-14
|
||||
|
||||
## [02.64.00] --- 2026-07-14
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* @package MokoSuiteBackup
|
||||
* @subpackage com_mokosuitebackup
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*
|
||||
* Full-screen backup/restore progress modals (backups view). Gives the stepped
|
||||
* backup and restore modals the same full-black, big-text, Atum-coloured
|
||||
* progress-bar treatment as the runbackup screen (media/css/runbackup.css), so
|
||||
* all backup progress surfaces share one look. The black is scoped to the modal
|
||||
* (via .msb-progress-modal) rather than html/body, so the list page behind it is
|
||||
* unaffected until the modal opens.
|
||||
*/
|
||||
|
||||
/* Accent colours pulled from the Atum admin template's own custom properties,
|
||||
with Bootstrap and then a literal as progressive fallbacks — identical to the
|
||||
runbackup screen so the two match whatever theme the site runs. */
|
||||
.msb-progress-modal {
|
||||
--msb-accent: var(--template-link-color, var(--bs-link-color, #2a69b8));
|
||||
--msb-accent2: var(--template-special-color, var(--msb-accent));
|
||||
--msb-success: var(--template-success-color, var(--bs-success, #2f7d32));
|
||||
--msb-danger: var(--template-danger-color, var(--bs-danger, #c52128));
|
||||
--msb-track: var(--template-bg-light, var(--bs-gray-200, #edf0f5));
|
||||
}
|
||||
|
||||
/* Full-screen black takeover, mirroring the runbackup page. */
|
||||
.msb-progress-modal .modal-dialog {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.msb-progress-modal .modal-content {
|
||||
min-height: 100vh;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.msb-progress-modal .modal-header {
|
||||
border: 0;
|
||||
padding: 0 0 1.5rem;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Big heading, like the runbackup title. */
|
||||
.msb-progress-modal .modal-title {
|
||||
color: #fff;
|
||||
font-size: clamp(1.75rem, 4vw, 2.75rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: .01em;
|
||||
}
|
||||
|
||||
.msb-progress-modal .modal-body {
|
||||
width: 100%;
|
||||
max-width: 680px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.msb-progress-modal .msb-pm-status {
|
||||
color: #fff;
|
||||
font-size: 1.25rem;
|
||||
margin: 1rem 0 .25rem;
|
||||
}
|
||||
|
||||
.msb-progress-modal .msb-pm-phase {
|
||||
color: rgba(255, 255, 255, .6);
|
||||
font-size: .95rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.msb-progress-modal .msb-pm-warn {
|
||||
color: #ffd23f;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
/* Progress bar — mirrors runbackup.css .msb-rb-progress/.msb-rb-bar. */
|
||||
.msb-progress-modal .msb-rb-progress {
|
||||
height: 2.75rem;
|
||||
background: var(--msb-track);
|
||||
border-radius: .35rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.msb-progress-modal .msb-rb-bar {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
white-space: nowrap;
|
||||
background-color: var(--msb-accent);
|
||||
background-image: linear-gradient(90deg, var(--msb-accent), var(--msb-accent2));
|
||||
transition: width .35s ease;
|
||||
}
|
||||
|
||||
.msb-progress-modal .msb-rb-bar.is-animated::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: linear-gradient(45deg, rgba(255, 255, 255, .18) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .18) 50%, rgba(255, 255, 255, .18) 75%, transparent 75%, transparent);
|
||||
background-size: 1rem 1rem;
|
||||
animation: msb-pm-stripes 1s linear infinite;
|
||||
}
|
||||
|
||||
.msb-progress-modal .msb-rb-bar.is-success {
|
||||
background-image: none;
|
||||
background-color: var(--msb-success);
|
||||
}
|
||||
|
||||
.msb-progress-modal .msb-rb-bar.is-danger {
|
||||
background-image: none;
|
||||
background-color: var(--msb-danger);
|
||||
}
|
||||
|
||||
@keyframes msb-pm-stripes {
|
||||
from {
|
||||
background-position: 1rem 0;
|
||||
}
|
||||
|
||||
to {
|
||||
background-position: 0 0;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,11 @@
|
||||
"name": "com_mokosuitebackup.runbackup",
|
||||
"type": "style",
|
||||
"uri": "com_mokosuitebackup/css/runbackup.css"
|
||||
},
|
||||
{
|
||||
"name": "com_mokosuitebackup.backup-progress",
|
||||
"type": "style",
|
||||
"uri": "com_mokosuitebackup/css/backup-progress.css"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -16,8 +16,14 @@ use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
HTMLHelper::_('behavior.multiselect');
|
||||
|
||||
// Full-black progress theme for the backup/restore modals (matches view=runbackup).
|
||||
// Loaded directly rather than via useStyle(), which does not emit a link for this
|
||||
// component (same pattern as the runbackup screen).
|
||||
$this->getDocument()->addStyleSheet(Uri::root(true) . '/media/com_mokosuitebackup/css/backup-progress.css');
|
||||
$user = Factory::getApplication()->getIdentity();
|
||||
$canDownload = $user->authorise('mokosuitebackup.backup.download', 'com_mokosuitebackup');
|
||||
|
||||
@@ -135,22 +141,25 @@ $listDirn = $this->escape($this->state->get('list.direction'));
|
||||
</form>
|
||||
|
||||
<!-- Stepped Backup Modal (for shared hosting) -->
|
||||
<div class="modal fade" id="mokosuitebackup-modal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
||||
<div class="modal fade msb-progress-modal" id="mokosuitebackup-modal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mb-modal-title">Backup in Progress</h5>
|
||||
<h2 class="modal-title" id="mb-modal-title">
|
||||
<span class="icon-archive" aria-hidden="true"></span>
|
||||
Backup in Progress
|
||||
</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning py-1 px-2 mb-2" style="font-size:0.85rem;">
|
||||
<p class="msb-pm-warn">
|
||||
<span class="icon-warning-circle" aria-hidden="true"></span>
|
||||
<strong>Do not navigate away or close this window</strong> while the backup is running.
|
||||
Do not navigate away or close this window while the backup is running.
|
||||
</p>
|
||||
<div class="msb-rb-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
|
||||
<div id="mb-progress-bar" class="msb-rb-bar is-animated" style="width:0%;">0%</div>
|
||||
</div>
|
||||
<div class="progress mb-2" style="height:24px;">
|
||||
<div id="mb-progress-bar" class="progress-bar" role="progressbar" style="width:0%;">0%</div>
|
||||
</div>
|
||||
<p id="mb-status" class="text-muted mb-1" style="font-size:0.9rem;">Initializing...</p>
|
||||
<p id="mb-phase" class="text-muted mb-0" style="font-size:0.8rem;">Phase: init</p>
|
||||
<p id="mb-status" class="msb-pm-status">Initializing...</p>
|
||||
<p id="mb-phase" class="msb-pm-phase">Phase: init</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -183,12 +192,29 @@ $listDirn = $this->escape($this->state->get('list.direction'));
|
||||
bootstrap.Modal.getInstance(document.getElementById('mokosuitebackup-modal'))?.hide();
|
||||
}
|
||||
|
||||
// Shared bar-state styling for both the backup and restore progress bars,
|
||||
// matching the runbackup screen: animated stripes while running, solid green
|
||||
// on completion, solid red on failure.
|
||||
function setBarState(bar, phase, progress) {
|
||||
if (phase === 'failed') {
|
||||
bar.classList.remove('is-animated', 'is-success');
|
||||
bar.classList.add('is-danger');
|
||||
} else if (progress >= 100 || phase === 'complete') {
|
||||
bar.classList.remove('is-animated', 'is-danger');
|
||||
bar.classList.add('is-success');
|
||||
}
|
||||
if (bar.parentElement) {
|
||||
bar.parentElement.setAttribute('aria-valuenow', progress);
|
||||
}
|
||||
}
|
||||
|
||||
function updateProgress(progress, message, phase) {
|
||||
const bar = document.getElementById('mb-progress-bar');
|
||||
bar.style.width = progress + '%';
|
||||
bar.textContent = progress + '%';
|
||||
document.getElementById('mb-status').textContent = message;
|
||||
document.getElementById('mb-phase').textContent = 'Phase: ' + phase;
|
||||
setBarState(bar, phase, progress);
|
||||
}
|
||||
|
||||
async function postAjax(params) {
|
||||
@@ -229,7 +255,7 @@ $listDirn = $this->escape($this->state->get('list.direction'));
|
||||
if (initResult.warnings && initResult.warnings.length > 0) {
|
||||
var warningEl = document.getElementById('mb-phase');
|
||||
warningEl.textContent = 'Warnings: ' + initResult.warnings.join('; ');
|
||||
warningEl.style.color = '#856404';
|
||||
warningEl.style.color = '#ffd23f';
|
||||
}
|
||||
|
||||
const sessionId = initResult.session_id;
|
||||
@@ -312,6 +338,7 @@ $listDirn = $this->escape($this->state->get('list.direction'));
|
||||
bar.textContent = progress + '%';
|
||||
document.getElementById('mb-restore-status').textContent = message;
|
||||
document.getElementById('mb-restore-phase').textContent = 'Phase: ' + phase;
|
||||
setBarState(bar, phase, progress);
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', function(e) {
|
||||
@@ -452,18 +479,25 @@ $listDirn = $this->escape($this->state->get('list.direction'));
|
||||
</div>
|
||||
|
||||
<!-- Restore Progress Modal -->
|
||||
<div class="modal fade" id="mb-restore-progress-modal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
||||
<div class="modal fade msb-progress-modal" id="mb-restore-progress-modal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mb-restore-title">Restore in Progress</h5>
|
||||
<h2 class="modal-title" id="mb-restore-title">
|
||||
<span class="icon-refresh" aria-hidden="true"></span>
|
||||
Restore in Progress
|
||||
</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="progress mb-2" style="height:24px;">
|
||||
<div id="mb-restore-progress-bar" class="progress-bar bg-danger" role="progressbar" style="width:0%;">0%</div>
|
||||
<p class="msb-pm-warn">
|
||||
<span class="icon-warning-circle" aria-hidden="true"></span>
|
||||
Do not navigate away or close this window while the restore is running.
|
||||
</p>
|
||||
<div class="msb-rb-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
|
||||
<div id="mb-restore-progress-bar" class="msb-rb-bar is-animated is-danger" style="width:0%;">0%</div>
|
||||
</div>
|
||||
<p id="mb-restore-status" class="text-muted mb-1" style="font-size:0.9rem;">Initializing...</p>
|
||||
<p id="mb-restore-phase" class="text-muted mb-0" style="font-size:0.8rem;">Phase: init</p>
|
||||
<p id="mb-restore-status" class="msb-pm-status">Initializing...</p>
|
||||
<p id="mb-restore-phase" class="msb-pm-phase">Phase: init</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user