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) {