Added email limit checks and email disabled messaging to publish flow

closes https://github.com/TryGhost/Team/issues/1584
refs https://github.com/TryGhost/Team/issues/1605

- added email limit check to PublishOptions setup
- moved email disabled messaging from the email recipients option to the publish type option
  - it was confusing to have the email publish type options disabled without any indication of why, with the message hidden within the closed email recipients option
This commit is contained in:
Kevin Ansfield 2022-05-11 17:00:20 +01:00
parent bb2b8fae27
commit f559170a39
6 changed files with 90 additions and 57 deletions

View File

@ -32,7 +32,11 @@
{{#unless @publishOptions.emailUnavailable}}
<div class="gh-publish-setting">
{{#if @publishOptions.willEmail}}
<button type="button" class="gh-publish-setting-title {{if (eq @publishOptions.publishType "publish") "disabled"}}" {{on "click" (fn this.toggleSection "emailRecipients")}}>
<button
type="button"
class="gh-publish-setting-title"
{{on "click" (fn this.toggleSection "emailRecipients")}}
>
{{svg-jar "member"}}
<div class="gh-publish-setting-trigger">
{{#let (members-count-fetcher query=(hash filter=@publishOptions.fullRecipientFilter)) as |countFetcher|}}
@ -56,21 +60,18 @@
</span>
</button>
{{else}}
<div class="gh-publish-setting-title {{if (eq @publishOptions.publishType "publish") "disabled"}}">
<button
type="button"
class="gh-publish-setting-title disabled"
>
{{svg-jar "member"}}
{{#if (eq @publishOptions.publishType "publish")}}
<div class="gh-publish-setting-trigger">
Not sent to any members
</div>
{{else}}
<button type="button" class="gh-publish-setting-trigger" {{on "click" (fn this.toggleSection "emailRecipients")}}>
Not sent to any members
</button>
{{/if}}
<span class="{{if (eq this.openSection "emailRecipients") "expanded"}}">
<div class="gh-publish-setting-trigger">
Not sent to any members
</div>
<span>
{{svg-jar "arrow-down" class="icon-expand"}}
</span>
</div>
</button>
{{/if}}
{{#liquid-if (eq this.openSection "emailRecipients")}}
<div class="gh-publish-setting-form">

View File

@ -19,6 +19,7 @@ const CONFIRM_EMAIL_MAX_POLL_LENGTH = 15 * 1000;
export class PublishOptions {
// passed in services
config = null;
limit = null;
settings = null;
store = null;
@ -89,6 +90,8 @@ export class PublishOptions {
// publish type ------------------------------------------------------------
@tracked publishType = 'publish+send';
// @tracked emailDisabledError;
@tracked emailDisabledError = 'Email sending is temporarily disabled because your account is currently in review. You should have an email about this from us already, but you can also reach us any time at support@ghost.org.';
get publishTypeOptions() {
return [{
@ -124,14 +127,14 @@ export class PublishOptions {
// publish type dropdown is shown but email options are disabled
get emailDisabled() {
const mailgunIsNotConfigured = !get(this.settings, 'mailgunIsConfigured')
&& !get(this.config, 'mailgunIsConfigured');
const hasNoMembers = this.totalMemberCount === 0;
// TODO: check email limit
return !this.mailgunIsConfigured || hasNoMembers || this.emailDisabledError;
}
return mailgunIsNotConfigured || hasNoMembers;
get mailgunIsConfigured() {
return get(this.settings, 'mailgunIsConfigured')
|| get(this.config, 'mailgunIsConfigured');
}
@action
@ -219,8 +222,9 @@ export class PublishOptions {
// setup -------------------------------------------------------------------
constructor({config, post, settings, store, user} = {}) {
constructor({config, limit, post, settings, store, user} = {}) {
this.config = config;
this.limit = limit;
this.post = post;
this.settings = settings;
this.store = store;
@ -255,12 +259,12 @@ export class PublishOptions {
});
// email limits
// TODO: query limit service
const checkSendingLimit = this._checkSendingLimit();
// newsletters
const fetchNewsletters = this.store.query('newsletter', {status: 'active', limit: 'all', include: 'count.members'});
yield Promise.all([countTotalMembers, fetchNewsletters]);
yield Promise.all([countTotalMembers, checkSendingLimit, fetchNewsletters]);
}
// saving ------------------------------------------------------------------
@ -348,6 +352,20 @@ export class PublishOptions {
this.post[property] = this._originalModelValues[property];
});
}
async _checkSendingLimit() {
await this.settings.reload();
try {
if (this.limit.limiter && this.limit.limiter.isLimited('emails')) {
await this.limit.limiter.errorIfWouldGoOverLimit('emails');
} else if (get(this.settings, 'emailVerificationRequired')) {
this.emailDisabledError = 'Email sending is temporarily disabled because your account is currently in review. You should have an email about this from us already, but you can also reach us any time at support@ghost.org.';
}
} catch (e) {
this.emailDisabledError = e.message;
}
}
}
/* Component -----------------------------------------------------------------*/

View File

@ -1,32 +1,25 @@
{{#if (eq @publishOptions.totalMemberCount 0)}}
<p class="gh-box gh-content-box">
<LinkTo @route="members">Add members</LinkTo>
to start sending newsletters!
</p>
{{else}}
<div class="form-group max-width mb0">
{{#if (gt @publishOptions.newsletters.length 1)}}
<div class="mb4">
<PowerSelect
@selected={{@publishOptions.newsletter}}
@options={{@publishOptions.newsletters}}
@onChange={{@publishOptions.setNewsletter}}
@triggerComponent="gh-power-select/trigger"
@triggerClass="gh-publish-newsletter-trigger"
@dropdownClass="gh-publish-newsletter-dropdown"
as |newsletter|
>
{{newsletter.name}} <span>({{newsletter.count.members}})</span>
</PowerSelect>
</div>
{{/if}}
<div class="form-group max-width mb0">
{{#if (gt @publishOptions.newsletters.length 1)}}
<div class="mb4">
<PowerSelect
@selected={{@publishOptions.newsletter}}
@options={{@publishOptions.newsletters}}
@onChange={{@publishOptions.setNewsletter}}
@triggerComponent="gh-power-select/trigger"
@triggerClass="gh-publish-newsletter-trigger"
@dropdownClass="gh-publish-newsletter-dropdown"
as |newsletter|
>
{{newsletter.name}} <span>({{newsletter.count.members}})</span>
</PowerSelect>
</div>
{{/if}}
<GhMembersRecipientSelect
@filter={{@publishOptions.recipientFilter}}
@newsletter={{@publishOptions.newsletter}}
@onChange={{@publishOptions.setRecipientFilter}}
@renderInPlace={{false}}
@dropdownClass="gh-publishmenu-newsletter-dropdown"
/>
</div>
{{/if}}
<GhMembersRecipientSelect
@filter={{@publishOptions.recipientFilter}}
@newsletter={{@publishOptions.newsletter}}
@onChange={{@publishOptions.setRecipientFilter}}
@renderInPlace={{false}}
@dropdownClass="gh-publishmenu-newsletter-dropdown"
/>
</div>

View File

@ -14,4 +14,19 @@
<label for="publish-type-{{option.value}}">{{option.label}}</label>
</span>
{{/each}}
</fieldset>
</fieldset>
{{#if @publishOptions.emailDisabledError}}
<p class="gh-box gh-content-box">
{{@publishOptions.emailDisabledError}}
</p>
{{else if (eq @publishOptions.totalMemberCount 0)}}
<p class="gh-box gh-content-box">
<LinkTo @route="members">Add members</LinkTo>
to start sending newsletters!
</p>
{{else if (not @publishOptions.mailgunIsConfigured)}}
<p class="gh-box gh-content-box">
Setup <a href="https://ghost.org/docs/newsletters/#bulk-email-configuration" target="_blank" rel="noreferrer noopener">Mailgun</a> to start sending newsletters!
</p>
{{/if}}

View File

@ -5,6 +5,7 @@ import {tracked} from '@glimmer/tracking';
export default class PublishOptionsResource extends Resource {
@service config;
@service limit;
@service session;
@service settings;
@service store;
@ -32,10 +33,11 @@ export default class PublishOptionsResource extends Resource {
}
_createPublishOptions(post) {
const {config, settings, store} = this;
const {config, limit, settings, store} = this;
return new PublishOptions({
config,
limit,
post,
settings,
store,

View File

@ -633,6 +633,10 @@
color: var(--middarkgrey-d1);
}
.gh-publish-types + .gh-box {
margin-top: 12px;
}
.gh-publish-schedule .gh-radio {
margin: 0;
}
@ -723,12 +727,12 @@
transform: scale(0.98);
box-shadow: 0 0 0 0 rgba(48, 207, 67, 0.7);
}
70% {
transform: scale(1);
box-shadow: 0 0 0 8px rgba(48, 207, 67, 0);
}
100% {
transform: scale(0.98);
box-shadow: 0 0 0 0 rgba(48, 207, 67, 0);
@ -834,4 +838,4 @@
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
}
}