From da62355e1878a763a58132d77a55eec8f6a35dd7 Mon Sep 17 00:00:00 2001
From: Rishabh Garg
Date: Thu, 25 Aug 2022 15:47:14 +0530
Subject: [PATCH] Wired email alert settings for staff users on admin (#15313)
refs TryGhost/Team#1826
- allows staff users to manage their email alert settings behind the flag
- only owner and admin users are able to toggle their email alerts
---
.../app/controllers/settings/staff/user.js | 13 ++++
ghost/admin/app/models/user.js | 3 +
ghost/admin/app/styles/layouts/user.css | 6 +-
.../app/templates/settings/staff/user.hbs | 68 ++++++++++++++++++-
ghost/admin/tests/acceptance/staff-test.js | 33 +++++++++
ghost/admin/tests/helpers/members.js | 4 ++
6 files changed, 123 insertions(+), 4 deletions(-)
diff --git a/ghost/admin/app/controllers/settings/staff/user.js b/ghost/admin/app/controllers/settings/staff/user.js
index c9915f91ee..e4b2a40ba2 100644
--- a/ghost/admin/app/controllers/settings/staff/user.js
+++ b/ghost/admin/app/controllers/settings/staff/user.js
@@ -21,6 +21,7 @@ export default Controller.extend({
session: service(),
slugGenerator: service(),
utils: service(),
+ membersUtils: service(),
personalToken: null,
limitErrorMessage: null,
@@ -47,6 +48,8 @@ export default Controller.extend({
canChangeEmail: not('isAdminUserOnOwnerProfile'),
canChangePassword: not('isAdminUserOnOwnerProfile'),
+ canToggleMemberAlerts: or('currentUser.isOwnerOnly', 'isAdminUserOnOwnProfile'),
+ isAdminUserOnOwnProfile: and('currentUser.isAdminOnly', 'isOwnProfile'),
canMakeOwner: and('currentUser.isOwnerOnly', 'isNotOwnProfile', 'user.isAdminOnly', 'isNotSuspended'),
isAdminUserOnOwnerProfile: and('currentUser.isAdminOnly', 'user.isOwnerOnly'),
isNotOwnersProfile: not('user.isOwnerOnly'),
@@ -385,6 +388,16 @@ export default Controller.extend({
this.user.commentNotifications = event.target.checked;
}),
+ toggleMemberEmailAlerts: action(function (type, event) {
+ if (type === 'free-signup') {
+ this.user.freeMemberSignupNotification = event.target.checked;
+ } else if (type === 'paid-started') {
+ this.user.paidSubscriptionStartedNotification = event.target.checked;
+ } else if (type === 'paid-canceled') {
+ this.user.paidSubscriptionCanceledNotification = event.target.checked;
+ }
+ }),
+
deleteUser: task(function *() {
try {
yield this.user.destroyRecord();
diff --git a/ghost/admin/app/models/user.js b/ghost/admin/app/models/user.js
index 602ee56d13..9dbfd6d378 100644
--- a/ghost/admin/app/models/user.js
+++ b/ghost/admin/app/models/user.js
@@ -36,6 +36,9 @@ export default BaseModel.extend(ValidationEngine, {
twitter: attr('twitter-url-user'),
tour: attr('json-string'),
commentNotifications: attr(),
+ freeMemberSignupNotification: attr(),
+ paidSubscriptionStartedNotification: attr(),
+ paidSubscriptionCanceledNotification: attr(),
ghostPaths: service(),
ajax: service(),
diff --git a/ghost/admin/app/styles/layouts/user.css b/ghost/admin/app/styles/layouts/user.css
index ad38449301..b545710890 100644
--- a/ghost/admin/app/styles/layouts/user.css
+++ b/ghost/admin/app/styles/layouts/user.css
@@ -196,7 +196,7 @@
display: flex;
justify-content: space-between;
align-items: center;
- margin-top: 12px;
+ margin-top: 20px;
}
.user-setting-toggle label {
@@ -205,4 +205,8 @@
.user-setting-toggle p {
margin-top: 0;
+}
+
+.user-settings-subgroup .for-switch {
+ width: 38px !important;
}
\ No newline at end of file
diff --git a/ghost/admin/app/templates/settings/staff/user.hbs b/ghost/admin/app/templates/settings/staff/user.hbs
index fe84d63901..6eaccde5a1 100644
--- a/ghost/admin/app/templates/settings/staff/user.hbs
+++ b/ghost/admin/app/templates/settings/staff/user.hbs
@@ -306,16 +306,16 @@
You've used {{gh-count-down-characters this.user.bio 200}}
-
+ {{#if this.membersUtils.isMembersEnabled}}
Email notifications
-
Receive notifications when members comment on one of your posts
+
Every time a member comments on one of your posts
-
+ {{#if (and this.canToggleMemberAlerts (feature 'emailAlerts'))}}
+
+
+
+
Every time a new free member signs up
+
+
+
+
+
+ {{#if this.membersUtils.paidMembersEnabled}}
+
+
+
+
Every time a member starts a new paid subscription
+
+
+
+
+
+
+
+
+
Every time a member cancels their paid subscription
+
+
+
+
+
+ {{/if}}
+ {{/if}}
+ {{/if}}
diff --git a/ghost/admin/tests/acceptance/staff-test.js b/ghost/admin/tests/acceptance/staff-test.js
index 560a6df80f..c57171b0f0 100644
--- a/ghost/admin/tests/acceptance/staff-test.js
+++ b/ghost/admin/tests/acceptance/staff-test.js
@@ -4,6 +4,10 @@ import windowProxy from 'ghost-admin/utils/window-proxy';
import {Response} from 'miragejs';
import {afterEach, beforeEach, describe, it} from 'mocha';
import {authenticateSession, invalidateSession} from 'ember-simple-auth/test-support';
+import {enableLabsFlag} from '../helpers/labs-flag';
+import {enableMembers} from '../helpers/members';
+import {enableStripe} from '../helpers/stripe';
+
import {
blur,
click,
@@ -73,7 +77,11 @@ describe('Acceptance: Staff', function () {
beforeEach(async function () {
this.server.loadFixtures('roles');
+ this.server.loadFixtures('settings');
adminRole = this.server.schema.roles.find(1);
+ enableMembers(this.server);
+ enableStripe(this.server);
+ enableLabsFlag(this.server, 'emailAlerts');
admin = this.server.create('user', {email: 'admin@example.com', roles: [adminRole]});
@@ -816,6 +824,13 @@ describe('Acceptance: Staff', function () {
expect(find('[data-test-slug-input]').value).to.be.equal('test-1');
expect(find('[data-test-facebook-input]').value).to.be.equal('https://www.facebook.com/test');
});
+
+ it('cannot see email alerts for other user', async function () {
+ await visit('/settings/staff/test-1');
+ expect(find('[data-test-checkbox="free-signup-notifications"]'), 'free signup alert').to.not.exist;
+ expect(find('[data-test-checkbox="paid-started-notifications"]'), 'paid start alert').to.not.exist;
+ expect(find('[data-test-checkbox="paid-canceled-notifications"]'), 'paid cancel alert').to.not.exist;
+ });
});
describe('own user', function () {
@@ -856,6 +871,24 @@ describe('Acceptance: Staff', function () {
'old password validation is in error state after typing'
).to.not.have.class('error');
});
+
+ it('can toggle email alerts for own user', async function () {
+ await visit(`/settings/staff/${admin.slug}`);
+ expect(find('[data-test-checkbox="free-signup-notifications"]')).to.not.be.checked;
+ expect(find('[data-test-checkbox="paid-started-notifications"]')).to.not.be.checked;
+ expect(find('[data-test-checkbox="paid-canceled-notifications"]')).to.not.be.checked;
+
+ await click('[data-test-label="free-signup-notifications"]');
+ await click('[data-test-label="paid-started-notifications"]');
+ await click('[data-test-label="paid-canceled-notifications"]');
+
+ await click('[data-test-save-button]');
+ await visit(`/settings/staff/${admin.slug}`);
+
+ expect(find('[data-test-checkbox="free-signup-notifications"]')).to.be.checked;
+ expect(find('[data-test-checkbox="paid-started-notifications"]')).to.be.checked;
+ expect(find('[data-test-checkbox="paid-canceled-notifications"]')).to.be.checked;
+ });
});
it('redirects to 404 when user does not exist', async function () {
diff --git a/ghost/admin/tests/helpers/members.js b/ghost/admin/tests/helpers/members.js
index 872db5da82..3130c79b68 100644
--- a/ghost/admin/tests/helpers/members.js
+++ b/ghost/admin/tests/helpers/members.js
@@ -2,6 +2,10 @@ export function enableMembers(server) {
server.db.settings.find({key: 'members_signup_access'})
? server.db.settings.update({key: 'members_signup_access'}, {value: 'all'})
: server.create('setting', {key: 'members_signup_access', value: 'all', group: 'members'});
+
+ server.db.settings.find({key: 'members_enabled'})
+ ? server.db.settings.update({key: 'members_enabled'}, {value: true})
+ : server.create('setting', {key: 'members_enabled', value: true, group: 'members'});
}
export function disableMembers(server) {