From 7c84ef8c2d61869b7a6b9670b4409128e62994a5 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Thu, 2 Mar 2023 18:39:38 +0000 Subject: [PATCH] Wired up click-to-refresh upgrade banner closes https://github.com/TryGhost/Team/issues/2400 - used semver comparison to detect when the app version is less than the content-version header in any API response to toggle `upgradeStatus.requiresRefresh` that is used to conditionally show the upgrade banner - only works on minors as we don't store the full Ghost patch version in `config.APP.version` --- ghost/admin/app/controllers/application.js | 1 + ghost/admin/app/services/ajax.js | 12 ++++++++++++ ghost/admin/app/services/upgrade-status.js | 3 +++ ghost/admin/app/templates/application.hbs | 11 +++++++---- ghost/admin/package.json | 3 ++- yarn.lock | 1 - 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ghost/admin/app/controllers/application.js b/ghost/admin/app/controllers/application.js index f1d29be663..7601459cc0 100644 --- a/ghost/admin/app/controllers/application.js +++ b/ghost/admin/app/controllers/application.js @@ -9,6 +9,7 @@ export default class ApplicationController extends Controller { @service session; @service settings; @service ui; + @service upgradeStatus; @inject config; diff --git a/ghost/admin/app/services/ajax.js b/ghost/admin/app/services/ajax.js index 058565fde4..aec7a81c48 100644 --- a/ghost/admin/app/services/ajax.js +++ b/ghost/admin/app/services/ajax.js @@ -2,6 +2,8 @@ import AjaxService from 'ember-ajax/services/ajax'; import classic from 'ember-classic-decorator'; import config from 'ghost-admin/config/environment'; import moment from 'moment-timezone'; +import semverCoerce from 'semver/functions/coerce'; +import semverLt from 'semver/functions/lt'; import {AjaxError, isAjaxError, isForbiddenError} from 'ember-ajax/errors'; import {captureMessage} from '@sentry/ember'; import {get} from '@ember/object'; @@ -194,6 +196,7 @@ export function isAcceptedResponse(errorOrStatus) { @classic class ajaxService extends AjaxService { @service session; + @service upgradeStatus; @inject config; @@ -296,6 +299,15 @@ class ajaxService extends AjaxService { } handleResponse(status, headers, payload, request) { + if (headers['content-version']) { + const contentVersion = semverCoerce(headers['content-version']); + const appVersion = semverCoerce(config.APP.version); + + if (semverLt(appVersion, contentVersion)) { + this.upgradeStatus.refreshRequired = true; + } + } + if (this.isVersionMismatchError(status, headers, payload)) { return new VersionMismatchError(payload); } else if (this.isServerUnreachableError(status, headers, payload)) { diff --git a/ghost/admin/app/services/upgrade-status.js b/ghost/admin/app/services/upgrade-status.js index 9cec969136..c7b2e0eac5 100644 --- a/ghost/admin/app/services/upgrade-status.js +++ b/ghost/admin/app/services/upgrade-status.js @@ -2,11 +2,14 @@ import Service, {inject as service} from '@ember/service'; import classic from 'ember-classic-decorator'; import {get, set} from '@ember/object'; import {htmlSafe} from '@ember/template'; +import {tracked} from '@glimmer/tracking'; @classic export default class UpgradeStatusService extends Service { @service notifications; + @tracked refreshRequired = false; + isRequired = false; message = ''; diff --git a/ghost/admin/app/templates/application.hbs b/ghost/admin/app/templates/application.hbs index d2b4d98f18..245a27953c 100644 --- a/ghost/admin/app/templates/application.hbs +++ b/ghost/admin/app/templates/application.hbs @@ -1,10 +1,13 @@ Skip to main content - {{!--
- Ghost has been updated! To get access to the latest features, refresh or click here. -
--}} - + {{#if this.upgradeStatus.refreshRequired}} +
+ {{!-- template-lint-disable no-invalid-link-text --}} + Ghost has been updated! To get access to the latest features, refresh or click here. +
+ {{/if}} +
diff --git a/ghost/admin/package.json b/ghost/admin/package.json index f305072fd1..4b024a2931 100644 --- a/ghost/admin/package.json +++ b/ghost/admin/package.json @@ -150,6 +150,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "reframe.js": "4.0.1", + "semver": "7.3.8", "testem": "3.10.1", "top-gh-contribs": "2.0.4", "tracked-built-ins": "3.1.1", @@ -182,4 +183,4 @@ "path-browserify": "1.0.1", "webpack": "5.75.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index f7e9edf63e..2876d1fd2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19917,7 +19917,6 @@ mocha@^2.5.3: mock-knex@TryGhost/mock-knex#d8b93b1c20d4820323477f2c60db016ab3e73192: version "0.4.12" - uid d8b93b1c20d4820323477f2c60db016ab3e73192 resolved "https://codeload.github.com/TryGhost/mock-knex/tar.gz/d8b93b1c20d4820323477f2c60db016ab3e73192" dependencies: bluebird "^3.4.1"