migration banner logic

Signed-off-by: Andy Miller <rhuk@mac.com>
This commit is contained in:
Andy Miller
2026-04-16 18:24:06 +01:00
parent 30a90cc69b
commit 38efb7d892
4 changed files with 169 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ use Grav\Common\Cache;
use Grav\Common\Data\Data;
use Grav\Common\Debugger;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\GPM\Upgrader;
use Grav\Common\Grav;
use Grav\Common\Helpers\LogViewer;
use Grav\Common\Inflector;
@@ -743,6 +744,21 @@ class AdminPlugin extends Plugin
switch ($this->template) {
case 'dashboard':
$twig->twig_vars['popularity'] = $this->popularity;
// Cross-family migration notice: when the remote advertises a new major,
// surface a one-time banner on the dashboard. Uses cached GPM data; failures
// must not break the dashboard.
try {
$upgrader = new Upgrader();
if (method_exists($upgrader, 'isNextMajorAvailable') && $upgrader->isNextMajorAvailable()) {
$twig->twig_vars['grav_next_major'] = [
'version' => $upgrader->getNextMajorVersion(),
'migration_url' => $upgrader->getMigrationUrl(),
];
}
} catch (\Throwable $e) {
// Swallow — notice is informational only.
}
break;
}

View File

@@ -498,6 +498,10 @@ PLUGIN_ADMIN:
MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_DESC: "Are you sure you want to delete this page and all its children? If the page is translated in other languages, those translations will be kept and must be deleted separately. Otherwise the page folder will be deleted along with its subpages. This action cannot be undone."
AND: "and"
UPDATE_AVAILABLE: "Update available"
GRAV_NEXT_MAJOR_AVAILABLE: "Grav %s is available"
GRAV_NEXT_MAJOR_DESCRIPTION: "A new major version of Grav is now available. This is not an automatic upgrade — moving from 1.x to 2.x is a migration. Follow the guide for details on what's new and how to import your existing site."
GRAV_NEXT_MAJOR_LEARN_MORE: "Learn how to migrate"
GRAV_NEXT_MAJOR_START_MIGRATION: "Start migration"
METADATA_KEY: "Key (e.g. 'Keywords')"
METADATA_VALUE: "Value (e.g. 'Blog, Grav')"
USERNAME_HELP: "Username should be between 3 and 16 characters, including lowercase letters, numbers, underscores, and hyphens. Uppercase letters, spaces, and special characters are not allowed"

View File

@@ -35,6 +35,7 @@
{% endif %}
{# System notifications, cannot be turned off #}
{% include 'partials/dashboard-migration-notice.html.twig' %}
{% include 'partials/dashboard-problems.html.twig' %}
<div id="admin-dashboard">

View File

@@ -0,0 +1,148 @@
{% if grav_next_major and grav_next_major.migration_url %}
<style>
.grav-migration-callout {
position: relative;
overflow: hidden;
margin: 0 0 20px;
padding: 22px 28px;
border-radius: 6px;
background: linear-gradient(135deg, #5b3ea8 0%, #7b2ff7 55%, #ff4d8f 100%);
color: #fff;
box-shadow: 0 6px 24px -8px rgba(91, 62, 168, 0.55), 0 2px 4px rgba(0, 0, 0, 0.08);
}
.grav-migration-callout::before {
content: "";
position: absolute;
top: -60px; right: -60px;
width: 220px; height: 220px;
background: radial-gradient(circle, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0) 70%);
pointer-events: none;
}
.grav-migration-callout .gmc-body {
position: relative;
display: flex;
align-items: center;
gap: 22px;
flex-wrap: wrap;
}
.grav-migration-callout .gmc-badge {
flex: 0 0 auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 72px; height: 72px;
border-radius: 12px;
background: rgba(255, 255, 255, 0.14);
backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.22);
}
.grav-migration-callout .gmc-badge .gmc-badge-label {
font-size: 9px;
letter-spacing: 1.4px;
text-transform: uppercase;
opacity: 0.8;
margin-top: 2px;
}
.grav-migration-callout .gmc-badge .gmc-badge-version {
font-size: 22px;
font-weight: 700;
line-height: 1;
letter-spacing: -0.5px;
}
.grav-migration-callout .gmc-text { flex: 1 1 280px; min-width: 0; }
.grav-migration-callout .gmc-text h3 {
margin: 0 0 4px;
font-size: 18px;
font-weight: 600;
color: #fff;
letter-spacing: -0.2px;
}
.grav-migration-callout .gmc-text h3 .gmc-tag {
display: inline-block;
margin-left: 8px;
padding: 2px 8px;
font-size: 10px;
font-weight: 700;
letter-spacing: 1px;
text-transform: uppercase;
background: rgba(255, 255, 255, 0.22);
border-radius: 3px;
vertical-align: 2px;
}
.grav-migration-callout .gmc-text p {
margin: 0;
font-size: 13px;
line-height: 1.5;
color: rgba(255, 255, 255, 0.88);
}
.grav-migration-callout .gmc-actions {
flex: 0 0 auto;
display: inline-flex;
gap: 8px;
flex-wrap: wrap;
}
.grav-migration-callout .gmc-cta {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 18px;
margin: 0;
font-weight: 600;
font-size: 13px;
border-radius: 4px;
text-decoration: none;
transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
line-height: 1;
}
.grav-migration-callout .gmc-cta-primary {
background: #fff;
color: #5b3ea8 !important;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}
.grav-migration-callout .gmc-cta-primary:hover {
transform: translateY(-1px);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18);
color: #5b3ea8 !important;
}
.grav-migration-callout .gmc-cta-secondary {
background: rgba(255, 255, 255, 0.12);
color: #fff !important;
border: 1px solid rgba(255, 255, 255, 0.45);
}
.grav-migration-callout .gmc-cta-secondary:hover {
background: rgba(255, 255, 255, 0.22);
color: #fff !important;
}
.grav-migration-callout .gmc-cta .fa { font-size: 12px; }
</style>
<div class="grav-migration-callout">
<div class="gmc-body">
<div class="gmc-badge">
<span class="gmc-badge-version">{{ grav_next_major.version|split('.')|slice(0,2)|join('.') }}</span>
<span class="gmc-badge-label">Grav</span>
</div>
<div class="gmc-text">
<h3>
{{ "PLUGIN_ADMIN.GRAV_NEXT_MAJOR_AVAILABLE"|t(grav_next_major.version) }}
<span class="gmc-tag">New</span>
</h3>
<p>{{ "PLUGIN_ADMIN.GRAV_NEXT_MAJOR_DESCRIPTION"|t }}</p>
</div>
<div class="gmc-actions">
{% if config.plugins['migrate-grav'].enabled %}
<a class="gmc-cta gmc-cta-primary" href="{{ base_url_relative }}/migrate-grav">
<i class="fa fa-rocket"></i> {{ "PLUGIN_ADMIN.GRAV_NEXT_MAJOR_START_MIGRATION"|t }}
</a>
<a class="gmc-cta gmc-cta-secondary" href="{{ grav_next_major.migration_url }}" target="_blank" rel="noopener">
{{ "PLUGIN_ADMIN.GRAV_NEXT_MAJOR_LEARN_MORE"|t }} <i class="fa fa-external-link"></i>
</a>
{% else %}
<a class="gmc-cta gmc-cta-primary" href="{{ grav_next_major.migration_url }}" target="_blank" rel="noopener">
{{ "PLUGIN_ADMIN.GRAV_NEXT_MAJOR_LEARN_MORE"|t }} <i class="fa fa-arrow-right"></i>
</a>
{% endif %}
</div>
</div>
</div>
{% endif %}