This repository has been archived by the owner on Nov 28, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Added "What's new" indicator and modal to highlight recent updates (#…
…1292) no issue - adds `whats-new` service that fetches the changelog from ghost.org and exposes the latest changelog entries - trigger a background fetch of the changelog from ghost.org when first loading the admin when logged in, or after signing in - adds a "What's new" menu item next to the user popup menu - adds an indicator to the user menu button and what's new menu item if there are unseen changelog entries - closing the changelog modal will update the "last seen date", clearing both indicators
- Loading branch information
1 parent
c3804fc
commit a63943e
Showing
18 changed files
with
322 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import Component from '@ember/component'; | ||
import {inject as service} from '@ember/service'; | ||
|
||
export default Component.extend({ | ||
whatsNew: service() | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import ModalComponent from 'ghost-admin/components/modal-base'; | ||
import {inject as service} from '@ember/service'; | ||
|
||
export default ModalComponent.extend({ | ||
whatsNew: service(), | ||
|
||
confirm() {} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import Service from '@ember/service'; | ||
import fetch from 'fetch'; | ||
import moment from 'moment'; | ||
import {action} from '@ember/object'; | ||
import {computed} from '@ember/object'; | ||
import {isEmpty} from '@ember/utils'; | ||
import {inject as service} from '@ember/service'; | ||
import {task} from 'ember-concurrency'; | ||
|
||
export default Service.extend({ | ||
session: service(), | ||
|
||
entries: null, | ||
changelogUrl: 'https://ghost.org/blog/', | ||
isShowingModal: false, | ||
|
||
_user: null, | ||
|
||
init() { | ||
this._super(...arguments); | ||
this.entries = []; | ||
}, | ||
|
||
whatsNewSettings: computed('_user.accessibility', function () { | ||
let settingsJson = this.get('_user.accessibility') || '{}'; | ||
let settings = JSON.parse(settingsJson); | ||
return settings.whatsNew; | ||
}), | ||
|
||
hasNew: computed('whatsNewSettings.lastSeenDate', 'entries.[]', function () { | ||
if (isEmpty(this.entries)) { | ||
return false; | ||
} | ||
|
||
let [latestEntry] = this.entries; | ||
|
||
let lastSeenDate = this.get('whatsNewSettings.lastSeenDate') || '2019-01-01 00:00:00'; | ||
let lastSeenMoment = moment(lastSeenDate); | ||
let latestDate = latestEntry.published_at; | ||
let latestMoment = moment(latestDate || lastSeenDate); | ||
return latestMoment.isAfter(lastSeenMoment); | ||
}), | ||
|
||
showModal: action(function () { | ||
this.set('isShowingModal', true); | ||
}), | ||
|
||
closeModal: action(function () { | ||
this.set('isShowingModal', false); | ||
this.updateLastSeen.perform(); | ||
}), | ||
|
||
fetchLatest: task(function* () { | ||
try { | ||
// we should already be logged in at this point so lets grab the user | ||
// record and store it locally so that we don't have to deal with | ||
// session.user being a promise and causing issues with CPs | ||
let user = yield this.session.user; | ||
this.set('_user', user); | ||
|
||
let response = yield fetch('https://ghost.org/changelog.json'); | ||
if (!response.ok) { | ||
// eslint-disable-next-line | ||
return console.error('Failed to fetch changelog', {response}); | ||
} | ||
|
||
let result = yield response.json(); | ||
this.set('entries', result.posts || []); | ||
this.set('changelogUrl', result.changelogUrl); | ||
} catch (e) { | ||
console.error(e); // eslint-disable-line | ||
} | ||
}), | ||
|
||
updateLastSeen: task(function* () { | ||
let settingsJson = this._user.accessibility || '{}'; | ||
let settings = JSON.parse(settingsJson); | ||
let [latestEntry] = this.entries; | ||
|
||
if (!latestEntry) { | ||
return; | ||
} | ||
|
||
if (!settings.whatsNew) { | ||
settings.whatsNew = {}; | ||
} | ||
|
||
settings.whatsNew.lastSeenDate = latestEntry.published_at; | ||
|
||
this._user.set('accessibility', JSON.stringify(settings)); | ||
yield this._user.save(); | ||
}) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
.gh-wn-header { | ||
position: relative; | ||
display: flex; | ||
align-items: center; | ||
margin: -32px -32px 0; | ||
border-top-left-radius: 6px; | ||
border-top-right-radius: 6px; | ||
overflow: hidden; | ||
background-position: center; | ||
background-repeat: no-repeat; | ||
background-size: cover; | ||
background: var(--purple); | ||
background: linear-gradient(135deg, color-mod(var(--purple) h(-10) s(+5%) l(-10%)) 0%, rgba(173,38,180,1) 100%); | ||
padding: 18px 32px 12px; | ||
} | ||
|
||
.gh-wn-header .background-img { | ||
position: absolute; | ||
top: -30px; | ||
left: 0; | ||
} | ||
|
||
.gh-wn-header h2 { | ||
font-size: 1.3rem; | ||
font-weight: 600; | ||
text-transform: uppercase; | ||
color: #FFF; | ||
margin: 0 8px 4px; | ||
} | ||
|
||
.gh-wn-content { | ||
margin: 0px -32px; | ||
padding: 0px 32px; | ||
max-height: calc(100vh - 170px); | ||
overflow-y: scroll; | ||
} | ||
|
||
.gh-wn-close { | ||
stroke: #FFF; | ||
opacity: 0.6; | ||
transition: all 0.2s ease-in-out; | ||
} | ||
|
||
.gh-wn-close:hover { | ||
opacity: 1.0; | ||
} | ||
|
||
.gh-wn-entry { | ||
margin: 0 -32px; | ||
padding: 0 32px; | ||
border-bottom: 1px solid var(--whitegrey); | ||
} | ||
|
||
.gh-wn-entry:last-of-type { | ||
margin-bottom: 0px; | ||
border-bottom: none; | ||
padding-bottom: 0px; | ||
} | ||
|
||
.gh-wn-entry h4 { | ||
font-size: 1.2rem; | ||
font-weight: 500; | ||
letter-spacing: 0.3px; | ||
text-transform: uppercase; | ||
margin: 24px 0 4px; | ||
color: var(--midlightgrey); | ||
} | ||
|
||
.gh-wn-entry p { | ||
margin: 0 0 20px; | ||
padding: 0; | ||
} | ||
|
||
.gh-wn-footer { | ||
margin: 0 -32px -32px; | ||
padding: 14px 32px 16px; | ||
border-top: 1px solid var(--whitegrey); | ||
justify-content: space-between; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,8 @@ | |
{{gh-content-cover}} | ||
|
||
{{gh-mobile-nav-bar}} | ||
|
||
<GhWhatsNew /> | ||
</div>{{!gh-viewport}} | ||
{{/gh-app}} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{{#if this.whatsNew.isShowingModal}} | ||
<GhFullscreenModal | ||
@modal="whats-new" | ||
@modifier="wide" | ||
@close={{fn this.whatsNew.closeModal}} | ||
/> | ||
{{/if}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<header class="modal-header gh-wn-header" data-test-modal="whats-new"> | ||
<img src="assets/img/whats-new-header-bg.svg" class="background-img" /> | ||
<span>{{svg-jar "gift" class="w5 h5 fill-white"}}</span> | ||
<h2>What's new?</h2> | ||
</header> | ||
|
||
<button class="close gh-wn-close" href="" title="Close" {{on "click" this.closeModal}}> | ||
{{svg-jar "close"}} | ||
</button> | ||
|
||
<div class="modal-body gh-wn-content"> | ||
{{#each this.whatsNew.entries as |entry|}} | ||
<div class="gh-wn-entry"> | ||
<h4>{{moment-format entry.published_at "DD MMMM YYYY"}}</h4> | ||
<h1 class="f1 fw6 ma0 pa0 mb3">{{entry.title}}</h1> | ||
{{#if entry.feature_image}} | ||
<img class="mb5" src={{entry.feature_image}}> | ||
{{/if}} | ||
{{#if entry.custom_excerpt}} | ||
<p>{{entry.custom_excerpt}}</p> | ||
<a href={{entry.url}} class="dib fw6 mb6" target="_blank" rel="noopener noreferrer">Read the full post →</a> | ||
{{else}} | ||
{{{entry.html}}} | ||
{{/if}} | ||
</div> | ||
{{/each}} | ||
</div> | ||
<div class="modal-footer gh-wn-footer"> | ||
<a href={{this.whatsNew.changelogUrl}} target="_blank" rel="noopener noreferrer"> | ||
See all past updates | ||
</a> | ||
</div> |
Oops, something went wrong.