Added filtering of announcement bar content
refs https://github.com/TryGhost/Team/issues/3051 - We need to show the announcement_content to specific audiences based on the announcement_visibility filter
This commit is contained in:
parent
3cf6800e3e
commit
cddf786424
6
ghost/announcement-bar-settings/.eslintrc.js
Normal file
6
ghost/announcement-bar-settings/.eslintrc.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: ['ghost'],
|
||||
extends: [
|
||||
'plugin:ghost/node'
|
||||
]
|
||||
};
|
23
ghost/announcement-bar-settings/README.md
Normal file
23
ghost/announcement-bar-settings/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Announcement Bar Settings
|
||||
|
||||
Announcement Bar settings logic
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
## Develop
|
||||
|
||||
This is a monorepo package.
|
||||
|
||||
Follow the instructions for the top-level repo.
|
||||
1. `git clone` this repo & `cd` into it as usual
|
||||
2. Run `yarn` to install top-level dependencies.
|
||||
|
||||
|
||||
|
||||
## Test
|
||||
|
||||
- `yarn lint` run just eslint
|
||||
- `yarn test` run lint and tests
|
||||
|
1
ghost/announcement-bar-settings/index.js
Normal file
1
ghost/announcement-bar-settings/index.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('./lib/AnnouncementBarSettings');
|
@ -0,0 +1,54 @@
|
||||
class AnnouncementBarSettings {
|
||||
#getAnnouncementSettings;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Object} deps
|
||||
* @param {() => {announcement: string, announcement_visibility: string[], announcement_background: string}} deps.getAnnouncementSettings
|
||||
*/
|
||||
constructor(deps) {
|
||||
this.#getAnnouncementSettings = deps.getAnnouncementSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} [member]
|
||||
* @param {string} member.status
|
||||
* @returns {{announcement: string, announcement_background: string}}
|
||||
*/
|
||||
getAnnouncementSettings(member) {
|
||||
let announcement = undefined;
|
||||
|
||||
// NOTE: combination of 'free_members' & 'paid_members' makes just a 'members' filter
|
||||
const announcementSettings = this.#getAnnouncementSettings();
|
||||
|
||||
if (announcementSettings.announcement) {
|
||||
const visibilities = announcementSettings.announcement_visibility;
|
||||
const announcementContent = announcementSettings.announcement;
|
||||
|
||||
// Available visibilities:
|
||||
// 'visitors', // Logged out visitors
|
||||
// 'free_members', // Free members
|
||||
// 'paid_members' // Paid members (aka non-free members)
|
||||
if (visibilities.length === 0) {
|
||||
announcement = undefined;
|
||||
} else {
|
||||
if (visibilities.includes('visitors') && !member) {
|
||||
announcement = announcementContent;
|
||||
} else if (visibilities.includes('free_members') && (member?.status === 'free')) {
|
||||
announcement = announcementContent;
|
||||
} else if (visibilities.includes('paid_members') && (member?.status !== 'free')) {
|
||||
announcement = announcementContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (announcement !== undefined) {
|
||||
return {
|
||||
announcement,
|
||||
announcement_background: announcementSettings.announcement_background
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnnouncementBarSettings;
|
26
ghost/announcement-bar-settings/package.json
Normal file
26
ghost/announcement-bar-settings/package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@tryghost/announcement-bar-settings",
|
||||
"version": "0.0.0",
|
||||
"repository": "https://github.com/TryGhost/Ghost/tree/main/packages/announcement-bar-settings",
|
||||
"author": "Ghost Foundation",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "echo \"Implement me!\"",
|
||||
"test:unit": "NODE_ENV=testing c8 --all --check-coverage --100 --reporter text --reporter cobertura mocha './test/**/*.test.js'",
|
||||
"test": "yarn test:unit",
|
||||
"lint:code": "eslint *.js lib/ --ext .js --cache",
|
||||
"lint": "yarn lint:code && yarn lint:test",
|
||||
"lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"lib"
|
||||
],
|
||||
"devDependencies": {
|
||||
"c8": "7.13.0",
|
||||
"mocha": "10.2.0",
|
||||
"sinon": "15.0.4"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
6
ghost/announcement-bar-settings/test/.eslintrc.js
Normal file
6
ghost/announcement-bar-settings/test/.eslintrc.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: ['ghost'],
|
||||
extends: [
|
||||
'plugin:ghost/test'
|
||||
]
|
||||
};
|
@ -0,0 +1,105 @@
|
||||
const assert = require('assert');
|
||||
const AnnouncementBarSettings = require('../index');
|
||||
|
||||
describe('AnnouncementBarSettings', function () {
|
||||
it('can initialize', function () {
|
||||
const announcementBarSettings = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: 'Hello world',
|
||||
announcement_visibility: ['visitors'],
|
||||
announcement_background: 'dark'
|
||||
})
|
||||
});
|
||||
|
||||
assert.ok(announcementBarSettings);
|
||||
});
|
||||
|
||||
describe('getAnnouncementSettings', function () {
|
||||
it('returns undefined if there is no announcement content', function () {
|
||||
const announcementBarSettings = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: null,
|
||||
announcement_visibility: [],
|
||||
announcement_background: 'dark'
|
||||
})
|
||||
});
|
||||
|
||||
const settings = announcementBarSettings.getAnnouncementSettings();
|
||||
|
||||
assert.equal(settings, undefined);
|
||||
});
|
||||
|
||||
it('returns undefined announcement settings if there is no announcement visibility', function () {
|
||||
const announcementBarSettings = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: 'Hello world',
|
||||
announcement_visibility: [],
|
||||
announcement_background: 'dark'
|
||||
})
|
||||
});
|
||||
|
||||
const settings = announcementBarSettings.getAnnouncementSettings();
|
||||
|
||||
assert.equal(settings, undefined);
|
||||
});
|
||||
|
||||
it('returns announcement if visibility is set to visitors and there is no logged in member', function () {
|
||||
const announcementBarSettings = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: 'Hello world',
|
||||
announcement_visibility: ['visitors'],
|
||||
announcement_background: 'dark'
|
||||
})
|
||||
});
|
||||
|
||||
const settings = announcementBarSettings.getAnnouncementSettings();
|
||||
|
||||
assert.equal(settings.announcement, 'Hello world');
|
||||
});
|
||||
|
||||
it('returns announcement if visibility is set to free members and member is free', function () {
|
||||
const announcementBarSettings = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: 'Hello world',
|
||||
announcement_visibility: ['free_members'],
|
||||
announcement_background: 'dark'
|
||||
})
|
||||
});
|
||||
|
||||
const settings = announcementBarSettings.getAnnouncementSettings({
|
||||
status: 'free'
|
||||
});
|
||||
assert.equal(settings.announcement, 'Hello world');
|
||||
});
|
||||
|
||||
it('returns announcement if visibility is set to paid members and member is paid', function () {
|
||||
const announcementBarSettings = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: 'Hello world',
|
||||
announcement_visibility: ['paid_members'],
|
||||
announcement_background: 'dark'
|
||||
})
|
||||
});
|
||||
|
||||
const settings = announcementBarSettings.getAnnouncementSettings({
|
||||
status: 'paid'
|
||||
});
|
||||
assert.equal(settings.announcement, 'Hello world');
|
||||
});
|
||||
|
||||
it('returns announcement if visibility is set to paid and paid members and member is comped', function () {
|
||||
const announcementBarSettings = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: 'Hello world',
|
||||
announcement_visibility: ['paid_members'],
|
||||
announcement_background: 'dark'
|
||||
})
|
||||
});
|
||||
|
||||
const settings = announcementBarSettings.getAnnouncementSettings({
|
||||
status: 'comped'
|
||||
});
|
||||
assert.equal(settings.announcement, 'Hello world');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,19 +1,25 @@
|
||||
const settingsCache = require('../../../shared/settings-cache');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const ghostVersion = require('@tryghost/version');
|
||||
const announcementBarSettings = require('../../services/announcement-bar-service');
|
||||
|
||||
module.exports = {
|
||||
docName: 'settings',
|
||||
|
||||
browse: {
|
||||
permissions: true,
|
||||
query() {
|
||||
query(frame) {
|
||||
const announcementSettings = announcementBarSettings.getAnnouncementSettings(frame.options.context?.member);
|
||||
|
||||
// @TODO: decouple settings cache from API knowledge
|
||||
// The controller fetches models (or cached models) and the API frame for the target API version formats the response.
|
||||
return Object.assign({}, settingsCache.getPublic(), {
|
||||
url: urlUtils.urlFor('home', true),
|
||||
version: ghostVersion.safe
|
||||
});
|
||||
return Object.assign({},
|
||||
settingsCache.getPublic(),
|
||||
announcementSettings, {
|
||||
url: urlUtils.urlFor('home', true),
|
||||
version: ghostVersion.safe
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -0,0 +1,12 @@
|
||||
const settingsCache = require('../../../shared/settings-cache');
|
||||
const AnnouncementBarSettings = require('@tryghost/announcement-bar-settings');
|
||||
|
||||
const announcementBarService = new AnnouncementBarSettings({
|
||||
getAnnouncementSettings: () => ({
|
||||
announcement: settingsCache.get('announcement_content'),
|
||||
announcement_background: settingsCache.get('announcement_background'),
|
||||
announcement_visibility: settingsCache.get('announcement_visibility')
|
||||
})
|
||||
});
|
||||
|
||||
module.exports = announcementBarService;
|
@ -4,6 +4,7 @@ const api = require('../../../../api').endpoints;
|
||||
const {http} = require('@tryghost/api-framework');
|
||||
const mw = require('./middleware');
|
||||
const config = require('../../../../../shared/config');
|
||||
const membersService = require('../../../../../server/services/members');
|
||||
|
||||
module.exports = function apiRoutes() {
|
||||
const router = express.Router('content api');
|
||||
@ -31,7 +32,7 @@ module.exports = function apiRoutes() {
|
||||
router.get('/tags/slug/:slug', mw.authenticatePublic, http(api.tagsPublic.read));
|
||||
|
||||
// ## Settings
|
||||
router.get('/settings', mw.authenticatePublic, http(api.publicSettings.browse));
|
||||
router.get('/settings', mw.authenticatePublic, membersService.middleware.loadMemberSession, http(api.publicSettings.browse));
|
||||
|
||||
// ## Members
|
||||
router.get('/newsletters', mw.authenticatePublic, http(api.newslettersPublic.browse));
|
||||
|
@ -135,7 +135,7 @@ class CacheManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the publically accessible cache entries with their correct names
|
||||
* Get all the publicly accessible cache entries with their correct names
|
||||
* Uses clone to prevent modifications from being reflected
|
||||
* @return {object} cache
|
||||
*/
|
||||
|
@ -39,7 +39,5 @@ module.exports = {
|
||||
portal_plans: 'portal_plans',
|
||||
portal_name: 'portal_name',
|
||||
portal_button: 'portal_button',
|
||||
comments_enabled: 'comments_enabled',
|
||||
announcement: 'announcement_content',
|
||||
announcement_background: 'announcement_background'
|
||||
comments_enabled: 'comments_enabled'
|
||||
};
|
||||
|
@ -63,6 +63,7 @@
|
||||
"@tryghost/adapter-cache-redis": "0.0.0",
|
||||
"@tryghost/adapter-manager": "0.0.0",
|
||||
"@tryghost/admin-api-schema": "4.3.0",
|
||||
"@tryghost/announcement-bar-settings": "0.0.0",
|
||||
"@tryghost/api-framework": "0.0.0",
|
||||
"@tryghost/api-version-compatibility-service": "0.0.0",
|
||||
"@tryghost/audience-feedback": "0.0.0",
|
||||
|
@ -5,8 +5,6 @@ Object {
|
||||
"meta": Object {},
|
||||
"settings": Object {
|
||||
"accent_color": "#FF1A75",
|
||||
"announcement": null,
|
||||
"announcement_background": "dark",
|
||||
"codeinjection_foot": null,
|
||||
"codeinjection_head": null,
|
||||
"comments_enabled": "off",
|
||||
|
@ -1339,8 +1339,6 @@ Object {
|
||||
"meta": Object {},
|
||||
"settings": Object {
|
||||
"accent_color": "#FF1A75",
|
||||
"announcement": null,
|
||||
"announcement_background": "dark",
|
||||
"codeinjection_foot": null,
|
||||
"codeinjection_head": null,
|
||||
"comments_enabled": "off",
|
||||
@ -1437,8 +1435,6 @@ Object {
|
||||
"meta": Object {},
|
||||
"settings": Object {
|
||||
"accent_color": "#FF1A75",
|
||||
"announcement": null,
|
||||
"announcement_background": "dark",
|
||||
"codeinjection_foot": null,
|
||||
"codeinjection_head": null,
|
||||
"comments_enabled": "off",
|
||||
|
12
yarn.lock
12
yarn.lock
@ -27498,6 +27498,18 @@ sinon@15.0.3:
|
||||
nise "^5.1.4"
|
||||
supports-color "^7.2.0"
|
||||
|
||||
sinon@15.0.4:
|
||||
version "15.0.4"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-15.0.4.tgz#bcca6fef19b14feccc96473f0d7adc81e0bc5268"
|
||||
integrity sha512-uzmfN6zx3GQaria1kwgWGeKiXSSbShBbue6Dcj0SI8fiCNFbiUDqKl57WFlY5lyhxZVUKmXvzgG2pilRQCBwWg==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^3.0.0"
|
||||
"@sinonjs/fake-timers" "^10.0.2"
|
||||
"@sinonjs/samsam" "^8.0.0"
|
||||
diff "^5.1.0"
|
||||
nise "^5.1.4"
|
||||
supports-color "^7.2.0"
|
||||
|
||||
sinon@^9.0.0:
|
||||
version "9.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.2.4.tgz#e55af4d3b174a4443a8762fa8421c2976683752b"
|
||||
|
Loading…
Reference in New Issue
Block a user