From 060d791a638d9e354e4219abe9caaa6dab0a6e49 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Fri, 7 Oct 2022 14:23:21 +0100 Subject: [PATCH] Removed need for `.get()` with settings service no issue The `settings` service has been a source of confusion when writing with modern Ember patterns because it's use of the deprecated `ProxyMixin` forced all property access/setting to go via `.get()` and `.set()` whereas the rest of the system has mostly (there are a few other uses of ProxyObjects remaining) eliminated the use of the non-native get/set methods. - removed use of `ProxyMixin` in the `settings` service by grabbing the attributes off the setting model after fetching and using `Object.defineProperty()` to add native getters/setters that pass through to the model's getters/setters. Ember's autotracking automatically works across the native getters/setters so we can then use the service as if it was any other native object - updated all code to use `settings.{attrName}` directly for getting/setting instead of `.get()` and `.set()` - removed use of observer in the `customViews` service because it was being set up before the native properties had been added on the settings service meaning autotracking wasn't able to set up properly --- .../components/editor/modals/preview/email.js | 2 +- .../editor/modals/preview/social.js | 6 +- .../editor/modals/publish-flow/confirm.js | 2 +- .../editor/publish-options/publish-at.js | 6 +- .../app/components/gh-editor-post-status.js | 2 +- .../app/components/gh-facebook-url-input.js | 9 +-- .../components/gh-koenig-editor-lexical.js | 2 +- .../app/components/gh-markdown-editor.js | 2 +- .../components/gh-post-settings-menu/email.js | 2 +- .../app/components/gh-psm-visibility-input.js | 4 +- .../app/components/gh-twitter-url-input.js | 9 +-- .../members-activity/event-type-filter.js | 2 +- ghost/admin/app/components/members/filter.js | 14 ++-- .../components/modal-email-design-settings.js | 38 +++++----- .../modal-free-membership-settings.js | 18 ++--- .../app/components/modal-portal-settings.js | 64 ++++++++--------- .../app/components/modal-stripe-connect.js | 8 +-- ghost/admin/app/components/modal-tier.js | 4 +- .../modals/newsletters/edit/preview.js | 4 +- .../modals/settings/verify-email.js | 2 +- .../app/components/posts-list/list-item.js | 2 +- .../settings/form-fields/accent-color.js | 8 +-- .../settings/form-fields/publication-cover.js | 2 +- .../settings/form-fields/publication-icon.js | 2 +- .../settings/form-fields/publication-logo.js | 2 +- .../settings/form-fields/site-description.js | 4 +- .../settings/members-comment-access.js | 4 +- .../settings/members-default-post-access.js | 20 +++--- .../settings/members-subscription-access.js | 6 +- .../settings/members/stripe-settings-form.js | 46 ++++++------- .../app/components/settings/newsletters.js | 54 +++++++-------- ghost/admin/app/components/tags/tag-form.js | 6 +- ghost/admin/app/controllers/editor.js | 2 +- ghost/admin/app/controllers/lexical-editor.js | 2 +- .../admin/app/controllers/members-activity.js | 2 +- .../app/controllers/settings/design/index.js | 2 +- .../admin/app/controllers/settings/general.js | 18 ++--- .../controllers/settings/integrations/amp.js | 2 +- .../settings/integrations/firstpromoter.js | 2 +- .../settings/integrations/slack.js | 2 +- .../settings/integrations/unsplash.js | 2 +- ghost/admin/app/controllers/settings/labs.js | 2 +- .../app/controllers/settings/membership.js | 22 +++--- .../app/controllers/settings/navigation.js | 8 +-- ghost/admin/app/controllers/settings/tier.js | 14 ++-- ghost/admin/app/helpers/get-setting.js | 3 +- .../admin/app/helpers/gh-format-post-time.js | 2 +- ghost/admin/app/helpers/is-moment-today.js | 4 +- .../admin/app/helpers/members-event-filter.js | 4 +- ghost/admin/app/helpers/moment-site-tz.js | 2 +- ghost/admin/app/models/post.js | 30 ++++---- ghost/admin/app/models/setting.js | 4 -- .../app/routes/settings/code-injection.js | 2 +- .../admin/app/routes/settings/design/index.js | 2 +- ghost/admin/app/routes/settings/general.js | 2 +- .../app/routes/settings/integrations/amp.js | 2 +- .../settings/integrations/firstpromoter.js | 2 +- .../app/routes/settings/integrations/slack.js | 2 +- .../routes/settings/integrations/unsplash.js | 2 +- .../admin/app/routes/settings/newsletters.js | 2 +- ghost/admin/app/services/custom-views.js | 49 ++++++------- ghost/admin/app/services/dashboard-stats.js | 2 +- ghost/admin/app/services/feature.js | 2 +- ghost/admin/app/services/frontend.js | 6 +- ghost/admin/app/services/members-utils.js | 38 +++++----- ghost/admin/app/services/navigation.js | 7 +- ghost/admin/app/services/settings.js | 69 ++++++++++++------- ghost/admin/app/services/theme-management.js | 10 +-- ghost/admin/app/services/ui.js | 2 +- ghost/admin/app/utils/publish-options.js | 16 ++--- .../helpers/gh-format-post-time-test.js | 4 +- .../unit/controllers/settings/design-test.js | 36 +++++----- 72 files changed, 368 insertions(+), 374 deletions(-) diff --git a/ghost/admin/app/components/editor/modals/preview/email.js b/ghost/admin/app/components/editor/modals/preview/email.js index 13ec72238b..4c161e1732 100644 --- a/ghost/admin/app/components/editor/modals/preview/email.js +++ b/ghost/admin/app/components/editor/modals/preview/email.js @@ -39,7 +39,7 @@ export default class ModalPostPreviewEmailComponent extends Component { get mailgunIsEnabled() { return this.config.get('mailgunIsConfigured') || - !!(this.settings.get('mailgunApiKey') && this.settings.get('mailgunDomain') && this.settings.get('mailgunBaseUrl')); + !!(this.settings.mailgunApiKey && this.settings.mailgunDomain && this.settings.mailgunBaseUrl); } @action diff --git a/ghost/admin/app/components/editor/modals/preview/social.js b/ghost/admin/app/components/editor/modals/preview/social.js index aec87454de..3f265dc4f8 100644 --- a/ghost/admin/app/components/editor/modals/preview/social.js +++ b/ghost/admin/app/components/editor/modals/preview/social.js @@ -24,7 +24,7 @@ export default class ModalPostPreviewSocialComponent extends Component { get _fallbackDescription() { return this.args.post.customExcerpt || this.serpDescription || - this.settings.get('description'); + this.settings.description; } @action @@ -107,7 +107,7 @@ export default class ModalPostPreviewSocialComponent extends Component { } get facebookImage() { - return this.args.post.ogImage || this.args.post.featureImage || this.settings.get('ogImage') || this.settings.get('coverImage'); + return this.args.post.ogImage || this.args.post.featureImage || this.settings.ogImage || this.settings.coverImage; } @action @@ -166,7 +166,7 @@ export default class ModalPostPreviewSocialComponent extends Component { } get twitterImage() { - return this.args.post.twitterImage || this.args.post.featureImage || this.settings.get('twitterImage') || this.settings.get('coverImage'); + return this.args.post.twitterImage || this.args.post.featureImage || this.settings.twitterImage || this.settings.coverImage; } @action diff --git a/ghost/admin/app/components/editor/modals/publish-flow/confirm.js b/ghost/admin/app/components/editor/modals/publish-flow/confirm.js index 81bc95f0b9..54410befbe 100644 --- a/ghost/admin/app/components/editor/modals/publish-flow/confirm.js +++ b/ghost/admin/app/components/editor/modals/publish-flow/confirm.js @@ -66,7 +66,7 @@ export default class PublishFlowOptions extends Component { } if (this.args.publishOptions.isScheduled) { - const scheduleMoment = moment.tz(this.args.publishOptions.scheduledAtUTC, this.settings.get('timezone')); + const scheduleMoment = moment.tz(this.args.publishOptions.scheduledAtUTC, this.settings.timezone); buttonText += `, on ${scheduleMoment.format('MMMM Do')}`; } else { buttonText += ', right now'; diff --git a/ghost/admin/app/components/editor/publish-options/publish-at.js b/ghost/admin/app/components/editor/publish-options/publish-at.js index 7c423348ac..b028fce8a1 100644 --- a/ghost/admin/app/components/editor/publish-options/publish-at.js +++ b/ghost/admin/app/components/editor/publish-options/publish-at.js @@ -9,7 +9,7 @@ export default class PublishAtOption extends Component { @action setDate(selectedDate) { // selectedDate is a Date object that contains the correct date string in the blog timezone - const selectedMoment = moment.tz(selectedDate, this.settings.get('timezone')); + const selectedMoment = moment.tz(selectedDate, this.settings.timezone); const {years, months, date} = selectedMoment.toObject(); // Create a new moment from existing scheduledAtUTC _in site timezone_. @@ -17,7 +17,7 @@ export default class PublishAtOption extends Component { // to account for the converted UTC date being yesterday/tomorrow. const newDate = moment.tz( this.args.publishOptions.scheduledAtUTC, - this.settings.get('timezone') + this.settings.timezone ); newDate.set({years, months, date}); @@ -27,7 +27,7 @@ export default class PublishAtOption extends Component { @action setTime(time, event) { - const newDate = moment.tz(this.args.publishOptions.scheduledAtUTC, this.settings.get('timezone')); + const newDate = moment.tz(this.args.publishOptions.scheduledAtUTC, this.settings.timezone); // used to reset the time value on blur if it's invalid const oldTime = newDate.format('HH:mm'); diff --git a/ghost/admin/app/components/gh-editor-post-status.js b/ghost/admin/app/components/gh-editor-post-status.js index f7868e697a..e4b921652d 100644 --- a/ghost/admin/app/components/gh-editor-post-status.js +++ b/ghost/admin/app/components/gh-editor-post-status.js @@ -32,7 +32,7 @@ export default class GhEditorPostStatusComponent extends Component { return formatPostTime( this.args.post.publishedAtUTC, - {timezone: this.settings.get('timezone'), scheduled: true} + {timezone: this.settings.timezone, scheduled: true} ); } diff --git a/ghost/admin/app/components/gh-facebook-url-input.js b/ghost/admin/app/components/gh-facebook-url-input.js index 8f1676239d..4e8e5083ed 100644 --- a/ghost/admin/app/components/gh-facebook-url-input.js +++ b/ghost/admin/app/components/gh-facebook-url-input.js @@ -1,14 +1,11 @@ import Component from '@glimmer/component'; import validator from 'validator'; import {action} from '@ember/object'; -import {get, set} from '@ember/object'; export default class GhFacebookUrlInput extends Component { - // NOTE: `get` and `set` are required when reading/writing model properties - // because we can be dealing with proxy objects such as the settings service get value() { const {model, modelProperty, scratchValue} = this.args; - return scratchValue || get(model, modelProperty); + return scratchValue || model[modelProperty]; } @action @@ -28,7 +25,7 @@ export default class GhFacebookUrlInput extends Component { if (!newUrl) { // Clear out the Facebook url - set(model, modelProperty, null); + model[modelProperty] = null; this.args.setScratchValue?.(null); return; } @@ -51,7 +48,7 @@ export default class GhFacebookUrlInput extends Component { throw 'invalid url'; } - set(model, modelProperty, newUrl); + model[modelProperty] = newUrl; this.args.setScratchValue?.(null); } catch (e) { if (e === 'invalid url') { diff --git a/ghost/admin/app/components/gh-koenig-editor-lexical.js b/ghost/admin/app/components/gh-koenig-editor-lexical.js index ecc61744fd..5736be4f3e 100644 --- a/ghost/admin/app/components/gh-koenig-editor-lexical.js +++ b/ghost/admin/app/components/gh-koenig-editor-lexical.js @@ -21,7 +21,7 @@ export default class GhKoenigEditorReactComponent extends Component { } get accentColor() { - const color = this.settings.get('accentColor'); + const color = this.settings.accentColor; if (color && color[0] === '#') { return color.slice(1); } diff --git a/ghost/admin/app/components/gh-markdown-editor.js b/ghost/admin/app/components/gh-markdown-editor.js index 7b60e2d1f7..a14badde6d 100644 --- a/ghost/admin/app/components/gh-markdown-editor.js +++ b/ghost/admin/app/components/gh-markdown-editor.js @@ -164,7 +164,7 @@ export default class GhMarkdownEditor extends Component.extend(ShortcutsMixin) { toolbar.splice(index, 1); } - if (this.get('settings.unsplash')) { + if (this.settings.unsplash) { let image = toolbar.findBy('name', 'image'); let index = toolbar.indexOf(image) + 1; diff --git a/ghost/admin/app/components/gh-post-settings-menu/email.js b/ghost/admin/app/components/gh-post-settings-menu/email.js index 23749e49d5..d6feda3a99 100644 --- a/ghost/admin/app/components/gh-post-settings-menu/email.js +++ b/ghost/admin/app/components/gh-post-settings-menu/email.js @@ -42,7 +42,7 @@ export default class Email extends Component { 'config.mailgunIsConfigured' ) get mailgunIsEnabled() { - return this.get('settings.mailgunApiKey') && this.get('settings.mailgunDomain') && this.get('settings.mailgunBaseUrl') || this.get('config.mailgunIsConfigured'); + return this.settings.mailgunApiKey && this.settings.mailgunDomain && this.settings.mailgunBaseUrl || this.get('config.mailgunIsConfigured'); } @action diff --git a/ghost/admin/app/components/gh-psm-visibility-input.js b/ghost/admin/app/components/gh-psm-visibility-input.js index 77ddc2fdcd..554d2439d1 100644 --- a/ghost/admin/app/components/gh-psm-visibility-input.js +++ b/ghost/admin/app/components/gh-psm-visibility-input.js @@ -12,13 +12,13 @@ const VISIBILITIES = [ @classic export default class GhPsmVisibilityInput extends Component { @service settings; - + // public attrs post = null; @computed('post.visibility') get selectedVisibility() { - return this.get('post.visibility') || this.settings.get('defaultContentVisibility'); + return this.get('post.visibility') || this.settings.defaultContentVisibility; } init() { diff --git a/ghost/admin/app/components/gh-twitter-url-input.js b/ghost/admin/app/components/gh-twitter-url-input.js index bb64540773..0f86e7c8f6 100644 --- a/ghost/admin/app/components/gh-twitter-url-input.js +++ b/ghost/admin/app/components/gh-twitter-url-input.js @@ -1,13 +1,10 @@ import Component from '@glimmer/component'; import {action} from '@ember/object'; -import {get, set} from '@ember/object'; export default class GhTwitterUrlInput extends Component { - // NOTE: `get` and `set` are required when reading/writing model properties - // because we can be dealing with proxy objects such as the settings service get value() { const {model, modelProperty, scratchValue} = this.args; - return scratchValue || get(model, modelProperty); + return scratchValue || model[modelProperty]; } @action @@ -27,7 +24,7 @@ export default class GhTwitterUrlInput extends Component { if (!newUrl) { // Clear out the Twitter url - set(model, modelProperty, ''); + model[modelProperty] = ''; this.args.setScratchValue?.(null); return; } @@ -52,7 +49,7 @@ export default class GhTwitterUrlInput extends Component { return; } - set(model, modelProperty, `https://twitter.com/${username}`); + model[modelProperty] = `https://twitter.com/${username}`; this.args.setScratchValue?.(null); model.hasValidated.pushObject(modelProperty); diff --git a/ghost/admin/app/components/members-activity/event-type-filter.js b/ghost/admin/app/components/members-activity/event-type-filter.js index 17bc5a18be..3ef8416553 100644 --- a/ghost/admin/app/components/members-activity/event-type-filter.js +++ b/ghost/admin/app/components/members-activity/event-type-filter.js @@ -19,7 +19,7 @@ export default class MembersActivityEventTypeFilter extends Component { get availableEventTypes() { const extended = [...ALL_EVENT_TYPES]; - if (this.settings.get('commentsEnabled') !== 'off') { + if (this.settings.commentsEnabled !== 'off') { extended.push({event: 'comment_event', icon: 'event-comment', name: 'Comments'}); } diff --git a/ghost/admin/app/components/members/filter.js b/ghost/admin/app/components/members/filter.js index 6ec815a6a9..3223d3b4ff 100644 --- a/ghost/admin/app/components/members/filter.js +++ b/ghost/admin/app/components/members/filter.js @@ -178,12 +178,12 @@ export default class MembersFilter extends Component { }); // exclude subscription filters if Stripe isn't connected - if (!this.settings.get('paidMembersEnabled')) { + if (!this.settings.paidMembersEnabled) { availableFilters = availableFilters.reject(prop => prop.group === 'Subscription'); } // exclude email filters if email functionality is disabled - if (this.settings.get('editorDefaultEmailRecipients') === 'disabled') { + if (this.settings.editorDefaultEmailRecipients === 'disabled') { availableFilters = availableFilters.reject(prop => prop.group === 'Email'); } @@ -253,7 +253,7 @@ export default class MembersFilter extends Component { } else if (filterProperty.valueType === 'date') { let filterValue; - let tzMoment = moment.tz(moment(filter.value).format('YYYY-MM-DD'), this.settings.get('timezone')); + let tzMoment = moment.tz(moment(filter.value).format('YYYY-MM-DD'), this.settings.timezone); if (relationStr === '>') { tzMoment = tzMoment.set({hour: 23, minute: 59, second: 59}); @@ -364,7 +364,7 @@ export default class MembersFilter extends Component { relation, relationOptions: FILTER_RELATIONS_OPTIONS[key], value, - timezone: this.settings.get('timezone') + timezone: this.settings.timezone }); } } @@ -429,7 +429,7 @@ export default class MembersFilter extends Component { @action handleSubmitKeyup(e) { e.preventDefault(); - + if (e.key === 'Enter') { this.applyFilter(); } @@ -465,7 +465,7 @@ export default class MembersFilter extends Component { } if (newProp.valueType === 'date' && !defaultValue) { - defaultValue = moment(moment.tz(this.settings.get('timezone')).format('YYYY-MM-DD')).toDate(); + defaultValue = moment(moment.tz(this.settings.timezone).format('YYYY-MM-DD')).toDate(); } let defaultRelation = this.availableFilterRelationsOptions[newType][0].name; @@ -479,7 +479,7 @@ export default class MembersFilter extends Component { relation: defaultRelation, relationOptions: this.availableFilterRelationsOptions[newType], value: defaultValue, - timezone: this.settings.get('timezone') + timezone: this.settings.timezone }); const filterToSwap = this.filters.find(f => f === filter); diff --git a/ghost/admin/app/components/modal-email-design-settings.js b/ghost/admin/app/components/modal-email-design-settings.js index eaa414be2e..e2de7f56f8 100644 --- a/ghost/admin/app/components/modal-email-design-settings.js +++ b/ghost/admin/app/components/modal-email-design-settings.js @@ -14,22 +14,22 @@ export default class ModalEmailDesignSettings extends ModalComponent { @service session; @service settings; - @tracked headerImage = this.settings.get('newsletterHeaderImage'); - @tracked showHeaderIcon = this.settings.get('newsletterShowHeaderIcon'); - @tracked showHeaderTitle = this.settings.get('newsletterShowHeaderTitle'); - @tracked titleFontCategory = this.settings.get('newsletterTitleFontCategory'); - @tracked titleAlignment = this.settings.get('newsletterTitleAlignment'); - @tracked showFeatureImage = this.settings.get('newsletterShowFeatureImage'); - @tracked bodyFontCategory = this.settings.get('newsletterBodyFontCategory'); - @tracked footerContent = this.settings.get('newsletterFooterContent'); - @tracked showBadge = this.settings.get('newsletterShowBadge'); + @tracked headerImage = this.settings.newsletterHeaderImage; + @tracked showHeaderIcon = this.settings.newsletterShowHeaderIcon; + @tracked showHeaderTitle = this.settings.newsletterShowHeaderTitle; + @tracked titleFontCategory = this.settings.newsletterTitleFontCategory; + @tracked titleAlignment = this.settings.newsletterTitleAlignment; + @tracked showFeatureImage = this.settings.newsletterShowFeatureImage; + @tracked bodyFontCategory = this.settings.newsletterBodyFontCategory; + @tracked footerContent = this.settings.newsletterFooterContent; + @tracked showBadge = this.settings.newsletterShowBadge; currentDate = moment().format('D MMM YYYY'); copyrightYear = new Date().getFullYear(); imageExtensions = IMAGE_EXTENSIONS; get showHeader() { - return (this.showHeaderIcon && this.settings.get('icon')) || this.showHeaderTitle; + return (this.showHeaderIcon && this.settings.icon) || this.showHeaderTitle; } get featureImageUrl() { @@ -77,15 +77,15 @@ export default class ModalEmailDesignSettings extends ModalComponent { @task({drop: true}) *saveSettings() { - this.settings.set('newsletterHeaderImage', this.headerImage); - this.settings.set('newsletterShowHeaderIcon', this.showHeaderIcon); - this.settings.set('newsletterShowHeaderTitle', this.showHeaderTitle); - this.settings.set('newsletterTitleFontCategory', this.titleFontCategory); - this.settings.set('newsletterTitleAlignment', this.titleAlignment); - this.settings.set('newsletterShowFeatureImage', this.showFeatureImage); - this.settings.set('newsletterBodyFontCategory', this.bodyFontCategory); - this.settings.set('newsletterFooterContent', this.footerContent); - this.settings.set('newsletterShowBadge', this.showBadge); + this.settings.newsletterHeaderImage = this.headerImage; + this.settings.newsletterShowHeaderIcon = this.showHeaderIcon; + this.settings.newsletterShowHeaderTitle = this.showHeaderTitle; + this.settings.newsletterTitleFontCategory = this.titleFontCategory; + this.settings.newsletterTitleAlignment = this.titleAlignment; + this.settings.newsletterShowFeatureImage = this.showFeatureImage; + this.settings.newsletterBodyFontCategory = this.bodyFontCategory; + this.settings.newsletterFooterContent = this.footerContent; + this.settings.newsletterShowBadge = this.showBadge; yield this.settings.save(); this.closeModal(); diff --git a/ghost/admin/app/components/modal-free-membership-settings.js b/ghost/admin/app/components/modal-free-membership-settings.js index 0104f5595d..bbaf692665 100644 --- a/ghost/admin/app/components/modal-free-membership-settings.js +++ b/ghost/admin/app/components/modal-free-membership-settings.js @@ -30,10 +30,10 @@ export default class ModalFreeMembershipSettings extends ModalBase { this.close(); }, updateName(value) { - this.settings.set('membersFreePriceName', value); + this.settings.membersFreePriceName = value; }, updateDescription(value) { - this.settings.set('membersFreePriceDescription', value); + this.settings.membersFreePriceDescription = value; }, setFreeSignupRedirect(url) { this.freeSignupRedirect = url; @@ -47,7 +47,7 @@ export default class ModalFreeMembershipSettings extends ModalBase { *save() { try { this.send('validateFreeSignupRedirect'); - if (this.settings.get('errors').length !== 0) { + if (this.settings.errors.length !== 0) { return; } yield this.settings.save(); @@ -61,12 +61,12 @@ export default class ModalFreeMembershipSettings extends ModalBase { _validateSignupRedirect(url, type) { let errMessage = `Please enter a valid URL`; - this.settings.get('errors').remove(type); - this.settings.get('hasValidated').removeObject(type); + this.settings.errors.remove(type); + this.settings.hasValidated.removeObject(type); if (url === null) { - this.settings.get('errors').add(type, errMessage); - this.settings.get('hasValidated').pushObject(type); + this.settings.errors.add(type, errMessage); + this.settings.hasValidated.pushObject(type); return false; } @@ -77,9 +77,9 @@ export default class ModalFreeMembershipSettings extends ModalBase { if (url.href.startsWith(this.siteUrl)) { const path = url.href.replace(this.siteUrl, ''); - this.settings.set(type, path); + this.settings.type = path; } else { - this.settings.set(type, url.href); + this.settings.type = url.href; } } } diff --git a/ghost/admin/app/components/modal-portal-settings.js b/ghost/admin/app/components/modal-portal-settings.js index 3927ea8a83..76fe1c9bde 100644 --- a/ghost/admin/app/components/modal-portal-settings.js +++ b/ghost/admin/app/components/modal-portal-settings.js @@ -32,7 +32,7 @@ export default ModalComponent.extend({ confirm() {}, backgroundStyle: computed('settings.accentColor', function () { - let color = this.settings.get('accentColor') || '#ffffff'; + let color = this.settings.accentColor || '#ffffff'; return htmlSafe(`background-color: ${color}`); }), @@ -71,20 +71,20 @@ export default ModalComponent.extend({ selectedButtonStyle: computed('settings.portalButtonStyle', function () { return this.buttonStyleOptions.find((buttonStyle) => { - return (buttonStyle.name === this.settings.get('portalButtonStyle')); + return (buttonStyle.name === this.settings.portalButtonStyle); }); }), isFreeChecked: computed('settings.{portalPlans.[],membersSignupAccess}', function () { - const allowedPlans = this.settings.get('portalPlans') || []; - return (this.settings.get('membersSignupAccess') === 'all' && allowedPlans.includes('free')); + const allowedPlans = this.settings.portalPlans || []; + return (this.settings.membersSignupAccess === 'all' && allowedPlans.includes('free')); }), isMonthlyChecked: computed('settings.portalPlans.[]', 'membersUtils.paidMembersEnabled', function () { - const allowedPlans = this.settings.get('portalPlans') || []; + const allowedPlans = this.settings.portalPlans || []; return (this.membersUtils.paidMembersEnabled && allowedPlans.includes('monthly')); }), isYearlyChecked: computed('settings.portalPlans.[]', 'membersUtils.paidMembersEnabled', function () { - const allowedPlans = this.settings.get('portalPlans') || []; + const allowedPlans = this.settings.portalPlans || []; return (this.membersUtils.paidMembersEnabled && allowedPlans.includes('yearly')); }), tiers: computed('model.tiers.[]', 'changedTiers.[]', 'isPreloading', function () { @@ -130,13 +130,13 @@ export default ModalComponent.extend({ }]; this.iconExtensions = ICON_EXTENSIONS; this.changedTiers = []; - this.set('supportAddress', this.parseEmailAddress(this.settings.get('membersSupportAddress'))); + this.set('supportAddress', this.parseEmailAddress(this.settings.membersSupportAddress)); this.set('openSection', 'signup-options'); }, didInsertElement() { this._super(...arguments); - this.settings.get('errors').clear(); + this.settings.errors.clear(); }, actions: { @@ -150,11 +150,11 @@ export default ModalComponent.extend({ this.updateAllowedTier(tierId, event.target.checked); }, togglePortalButton(showButton) { - this.settings.set('portalButton', showButton); + this.settings.portalButton = showButton; }, togglePortalName(showSignupName) { - this.settings.set('portalName', showSignupName); + this.settings.portalName = showSignupName; }, toggleSection(section) { if (this.get('openSection') === section) { @@ -169,7 +169,7 @@ export default ModalComponent.extend({ }, isPlanSelected(plan) { - const allowedPlans = this.settings.get('portalPlans'); + const allowedPlans = this.settings.portalPlans; return allowedPlans.includes(plan); }, @@ -191,11 +191,11 @@ export default ModalComponent.extend({ }, setButtonStyle(buttonStyle) { - this.settings.set('portalButtonStyle', buttonStyle.name); + this.settings.portalButtonStyle = buttonStyle.name; }, setSignupButtonText(event) { - this.settings.set('portalButtonSignupText', event.target.value); + this.settings.portalButtonSignupText = event.target.value; }, /** * Fired after an image upload completes @@ -206,7 +206,7 @@ export default ModalComponent.extend({ imageUploaded(property, results) { if (results[0]) { this.set('customIcon', results[0].url); - this.settings.set('portalButtonIcon', results[0].url); + this.settings.portalButtonIcon = results[0].url; } }, /** @@ -221,11 +221,11 @@ export default ModalComponent.extend({ deleteCustomIcon() { this.set('customIcon', null); - this.settings.set('portalButtonIcon', this.membersUtils.defaultIconKeys[0]); + this.settings.portalButtonIcon = this.membersUtils.defaultIconKeys[0]; }, selectDefaultIcon(icon) { - this.settings.set('portalButtonIcon', icon); + this.settings.portalButtonIcon = icon; }, closeLeaveSettingsModal() { @@ -253,9 +253,9 @@ export default ModalComponent.extend({ this.set('supportAddress', supportAddress); if (this.config.emailDomain && supportAddress === `noreply@${this.config.emailDomain}`) { - this.settings.set('membersSupportAddress', 'noreply'); + this.settings.membersSupportAddress = 'noreply'; } else { - this.settings.set('membersSupportAddress', supportAddress); + this.settings.membersSupportAddress = supportAddress; } } }, @@ -270,18 +270,18 @@ export default ModalComponent.extend({ }, updateAllowedPlan(plan, isChecked) { - const portalPlans = this.settings.get('portalPlans') || []; + const portalPlans = this.settings.portalPlans || []; const allowedPlans = [...portalPlans]; const freeTier = this.model.tiers.find(p => p.type === 'free'); if (!isChecked) { - this.settings.set('portalPlans', allowedPlans.filter(p => p !== plan)); + this.settings.portalPlans = allowedPlans.filter(p => p !== plan); if (plan === 'free') { freeTier.set('visibility', 'none'); } } else { allowedPlans.push(plan); - this.settings.set('portalPlans', allowedPlans); + this.settings.portalPlans = allowedPlans; if (plan === 'free') { freeTier.set('visibility', 'public'); } @@ -303,12 +303,12 @@ export default ModalComponent.extend({ _validateSignupRedirect(url, type) { let errMessage = `Please enter a valid URL`; - this.settings.get('errors').remove(type); - this.settings.get('hasValidated').removeObject(type); + this.settings.errors.remove(type); + this.settings.hasValidated.removeObject(type); if (url === null) { - this.settings.get('errors').add(type, errMessage); - this.settings.get('hasValidated').pushObject(type); + this.settings.errors.add(type, errMessage); + this.settings.hasValidated.pushObject(type); return false; } @@ -319,9 +319,9 @@ export default ModalComponent.extend({ if (url.href.startsWith(this.siteUrl)) { const path = url.href.replace(this.siteUrl, ''); - this.settings.set(type, path); + this.settings[type] = path; } else { - this.settings.set(type, url.href); + this.settings[type] = url.href; } }, @@ -330,9 +330,9 @@ export default ModalComponent.extend({ await this.model.preloadTask; } - const portalButtonIcon = this.settings.get('portalButtonIcon') || ''; + const portalButtonIcon = this.settings.portalButtonIcon || ''; if (portalButtonIcon && !this.membersUtils.defaultIconKeys.includes(portalButtonIcon)) { - this.set('customIcon', this.settings.get('portalButtonIcon')); + this.set('customIcon', this.settings.portalButtonIcon); } this.siteUrl = this.config.get('blogUrl'); @@ -360,7 +360,7 @@ export default ModalComponent.extend({ this.settings.errors.remove('members_support_address'); this.settings.hasValidated.removeObject('members_support_address'); - if (this.settings.get('errors').length !== 0) { + if (this.settings.errors.length !== 0) { return; } @@ -374,14 +374,14 @@ export default ModalComponent.extend({ }) ); - const newEmail = this.settings.get('membersSupportAddress'); + const newEmail = this.settings.membersSupportAddress; try { const result = yield this.settings.save(); if (result._meta?.sent_email_verification) { yield this.modals.open(ConfirmEmailModal, { newEmail, - currentEmail: this.settings.get('membersSupportAddress') + currentEmail: this.settings.membersSupportAddress }); } diff --git a/ghost/admin/app/components/modal-stripe-connect.js b/ghost/admin/app/components/modal-stripe-connect.js index fb4db86d75..db678db087 100644 --- a/ghost/admin/app/components/modal-stripe-connect.js +++ b/ghost/admin/app/components/modal-stripe-connect.js @@ -11,14 +11,14 @@ export default class ModalStripeConnect extends ModalBase { @action setStripeConnectIntegrationTokenSetting(stripeConnectIntegrationToken) { - this.settings.set('stripeConnectIntegrationToken', stripeConnectIntegrationToken); + this.settings.stripeConnectIntegrationToken = stripeConnectIntegrationToken; } @action reset() { // stripeConnectIntegrationToken is not a persisted value so we don't want // to keep it around across transitions - this.settings.set('stripeConnectIntegrationToken', undefined); + this.settings.stripeConnectIntegrationToken = undefined; } @action @@ -36,7 +36,7 @@ export default class ModalStripeConnect extends ModalBase { @action updateSuccessModifier() { // Note, we should also check isStripeEnabled because stripeDirect option might be enabled - if (this.membersUtils.get('isStripeEnabled') && this.settings.get('stripeConnectAccountId')) { + if (this.membersUtils.get('isStripeEnabled') && this.settings.stripeConnectAccountId) { if (this.modifier?.indexOf('stripe-connected') === -1) { this.updateModifier(`${this.modifier} stripe-connected`); } @@ -49,7 +49,7 @@ export default class ModalStripeConnect extends ModalBase { actions = { confirm() { - if (this.settings.get('stripeConnectAccountId')) { + if (this.settings.stripeConnectAccountId) { return this.confirmAction(); } // noop - enter key shouldn't do anything diff --git a/ghost/admin/app/components/modal-tier.js b/ghost/admin/app/components/modal-tier.js index 0f01653db0..37ccdd1d85 100644 --- a/ghost/admin/app/components/modal-tier.js +++ b/ghost/admin/app/components/modal-tier.js @@ -86,7 +86,7 @@ export default class ModalTierPrice extends ModalBase { if (this.tier.get('trialDays')) { this.freeTrialEnabled = true; } - this.accentColorStyle = htmlSafe(`color: ${this.settings.get('accentColor')}`); + this.accentColorStyle = htmlSafe(`color: ${this.settings.accentColor}`); } @action @@ -179,7 +179,7 @@ export default class ModalTierPrice extends ModalBase { } this.tier.set('benefits', this.benefits.filter(benefit => !benefit.get('isBlank'))); - + try { yield this.tier.save(); this.hasSaved = true; diff --git a/ghost/admin/app/components/modals/newsletters/edit/preview.js b/ghost/admin/app/components/modals/newsletters/edit/preview.js index 1d5b194dcf..0b17177773 100644 --- a/ghost/admin/app/components/modals/newsletters/edit/preview.js +++ b/ghost/admin/app/components/modals/newsletters/edit/preview.js @@ -8,7 +8,7 @@ export default class EditNewsletterPreview extends Component { @service settings; get showHeader() { - return (this.args.newsletter.showHeaderIcon && this.settings.get('icon')) + return (this.args.newsletter.showHeaderIcon && this.settings.icon) || this.headerTitle; } @@ -18,7 +18,7 @@ export default class EditNewsletterPreview extends Component { get headerTitle() { if (this.args.newsletter.showHeaderTitle) { - return this.settings.get('title'); + return this.settings.title; } else if (this.args.newsletter.showHeaderName) { return this.args.newsletter.name; } diff --git a/ghost/admin/app/components/modals/settings/verify-email.js b/ghost/admin/app/components/modals/settings/verify-email.js index b09f671a83..5f5a9f8e4f 100644 --- a/ghost/admin/app/components/modals/settings/verify-email.js +++ b/ghost/admin/app/components/modals/settings/verify-email.js @@ -33,7 +33,7 @@ export default class VerifyEmail extends Component { yield this.ajax.put(url, {data: {token}}); yield this.settings.reload(); - this.email = this.settings.get('membersSupportAddress'); + this.email = this.settings.membersSupportAddress; } catch (e) { this.error = e.message; } diff --git a/ghost/admin/app/components/posts-list/list-item.js b/ghost/admin/app/components/posts-list/list-item.js index 9012744a70..61f906a247 100644 --- a/ghost/admin/app/components/posts-list/list-item.js +++ b/ghost/admin/app/components/posts-list/list-item.js @@ -27,7 +27,7 @@ export default class PostsListItemClicks extends Component { let formattedTime = formatPostTime( this.post.publishedAtUTC, - {timezone: this.settings.get('timezone'), scheduled: true} + {timezone: this.settings.timezone, scheduled: true} ); text.push(formattedTime); diff --git a/ghost/admin/app/components/settings/form-fields/accent-color.js b/ghost/admin/app/components/settings/form-fields/accent-color.js index f9eec80630..5bd4a635f6 100644 --- a/ghost/admin/app/components/settings/form-fields/accent-color.js +++ b/ghost/admin/app/components/settings/form-fields/accent-color.js @@ -8,7 +8,7 @@ export default class AccentColorFormField extends Component { @service settings; get accentColor() { - const color = this.settings.get('accentColor'); + const color = this.settings.accentColor; if (color && color[0] === '#') { return color.slice(1); } @@ -16,7 +16,7 @@ export default class AccentColorFormField extends Component { } get accentColorPickerValue() { - return this.settings.get('accentColor') || '#ffffff'; + return this.settings.accentColor || '#ffffff'; } get accentColorBgStyle() { @@ -31,7 +31,7 @@ export default class AccentColorFormField extends Component { @action async updateAccentColor(event) { let newColor = event.target.value; - const oldColor = this.settings.get('accentColor'); + const oldColor = this.settings.accentColor; // reset errors and validation this.settings.errors.remove('accentColor'); @@ -62,7 +62,7 @@ export default class AccentColorFormField extends Component { return; } - this.settings.set('accentColor', newColor); + this.settings.accentColor = newColor; this.args.didUpdate('accentColor', newColor); } else { this.settings.errors.add('accentColor', 'Please enter a color in hex format'); diff --git a/ghost/admin/app/components/settings/form-fields/publication-cover.js b/ghost/admin/app/components/settings/form-fields/publication-cover.js index 39667e99ca..0ceb7db6f9 100644 --- a/ghost/admin/app/components/settings/form-fields/publication-cover.js +++ b/ghost/admin/app/components/settings/form-fields/publication-cover.js @@ -25,7 +25,7 @@ export default class PublicationCoverFormField extends Component { @action update(value) { - this.settings.set('coverImage', value); + this.settings.coverImage = value; this.args.didUpdate('coverImage', value); } diff --git a/ghost/admin/app/components/settings/form-fields/publication-icon.js b/ghost/admin/app/components/settings/form-fields/publication-icon.js index 280b58364c..e45aaf783b 100644 --- a/ghost/admin/app/components/settings/form-fields/publication-icon.js +++ b/ghost/admin/app/components/settings/form-fields/publication-icon.js @@ -21,7 +21,7 @@ export default class PublicationIconFormField extends Component { @action update(value) { - this.settings.set('icon', value); + this.settings.icon = value; this.args.didUpdate('icon', value); } } diff --git a/ghost/admin/app/components/settings/form-fields/publication-logo.js b/ghost/admin/app/components/settings/form-fields/publication-logo.js index 39269bca72..f9cf05c2dc 100644 --- a/ghost/admin/app/components/settings/form-fields/publication-logo.js +++ b/ghost/admin/app/components/settings/form-fields/publication-logo.js @@ -21,7 +21,7 @@ export default class PublicationLogoFormField extends Component { @action update(value) { - this.settings.set('logo', value); + this.settings.logo = value; this.args.didUpdate('logo', value); } } diff --git a/ghost/admin/app/components/settings/form-fields/site-description.js b/ghost/admin/app/components/settings/form-fields/site-description.js index ea2c685728..a73b904c0a 100644 --- a/ghost/admin/app/components/settings/form-fields/site-description.js +++ b/ghost/admin/app/components/settings/form-fields/site-description.js @@ -7,13 +7,13 @@ export default class SiteDescriptionFormField extends Component { @action update(event) { - this.settings.set('description', event.target.value); + this.settings.description = event.target.value; } @action async validate(event) { const value = event.target.value; - this.settings.set('description', value); + this.settings.description = value; await this.settings.validate({property: 'description'}); this.args.didUpdate('description', value); } diff --git a/ghost/admin/app/components/settings/members-comment-access.js b/ghost/admin/app/components/settings/members-comment-access.js index 7a5a246a71..066a1ecced 100644 --- a/ghost/admin/app/components/settings/members-comment-access.js +++ b/ghost/admin/app/components/settings/members-comment-access.js @@ -28,12 +28,12 @@ export default class SettingsMembersCommentAccess extends Component { } get selectedOption() { - return this.options.find(o => o.value === this.settings.get('commentsEnabled')); + return this.options.find(o => o.value === this.settings.commentsEnabled); } @action setCommentAccess(option) { - this.settings.set('commentsEnabled', option.value); + this.settings.commentsEnabled = option.value; this.args.onChange?.(option.value); } } diff --git a/ghost/admin/app/components/settings/members-default-post-access.js b/ghost/admin/app/components/settings/members-default-post-access.js index 589351fd09..e6f5876cfb 100644 --- a/ghost/admin/app/components/settings/members-default-post-access.js +++ b/ghost/admin/app/components/settings/members-default-post-access.js @@ -37,22 +37,22 @@ export default class SettingsMembersDefaultPostAccess extends Component { } get hasVisibilityFilter() { - return !['public', 'members', 'paid'].includes(this.settings.get('defaultContentVisibility')); + return !['public', 'members', 'paid'].includes(this.settings.defaultContentVisibility); } get visibilityTiers() { - const visibilityTiersData = this.settings.get('defaultContentVisibilityTiers'); + const visibilityTiersData = this.settings.defaultContentVisibilityTiers; return (visibilityTiersData || []).map((id) => { return {id}; }); } get selectedOption() { - if (this.settings.get('membersSignupAccess') === 'none') { + if (this.settings.membersSignupAccess === 'none') { return this.options.find(o => o.value === 'public'); } - return this.options.find(o => o.value === this.settings.get('defaultContentVisibility')); + return this.options.find(o => o.value === this.settings.defaultContentVisibility); } @action @@ -61,21 +61,21 @@ export default class SettingsMembersDefaultPostAccess extends Component { const tierIds = segment?.map((tier) => { return tier.id; }); - this.settings.set('defaultContentVisibility', 'tiers'); - this.settings.set('defaultContentVisibilityTiers', tierIds); + this.settings.defaultContentVisibility = 'tiers'; + this.settings.defaultContentVisibilityTiers = tierIds; this.showSegmentError = false; } else { - this.settings.set('defaultContentVisibility', ''); + this.settings.defaultContentVisibility = ''; this.showSegmentError = true; } } @action setDefaultContentVisibility(option) { - if (this.settings.get('membersSignupAccess') !== 'none') { - this.settings.set('defaultContentVisibility', option.value); + if (this.settings.membersSignupAccess !== 'none') { + this.settings.defaultContentVisibility = option.value; if (option.value === 'tiers') { - this.settings.set('defaultContentVisibilityTiers', []); + this.settings.defaultContentVisibilityTiers = []; } } } diff --git a/ghost/admin/app/components/settings/members-subscription-access.js b/ghost/admin/app/components/settings/members-subscription-access.js index c379ac4e2a..fdc8d22c75 100644 --- a/ghost/admin/app/components/settings/members-subscription-access.js +++ b/ghost/admin/app/components/settings/members-subscription-access.js @@ -28,16 +28,16 @@ export default class SettingsMembersSubscriptionAccess extends Component { } get selectedOption() { - return this.options.find(o => o.value === this.settings.get('membersSignupAccess')); + return this.options.find(o => o.value === this.settings.membersSignupAccess); } @action setSignupAccess(option) { - this.settings.set('membersSignupAccess', option.value); + this.settings.membersSignupAccess = option.value; this.args.onChange?.(option.value); if (option.value === 'none') { - this.settings.set('defaultContentVisibility', 'public'); + this.settings.defaultContentVisibility = 'public'; } } } diff --git a/ghost/admin/app/components/settings/members/stripe-settings-form.js b/ghost/admin/app/components/settings/members/stripe-settings-form.js index f72fdda49b..bd09d7f076 100644 --- a/ghost/admin/app/components/settings/members/stripe-settings-form.js +++ b/ghost/admin/app/components/settings/members/stripe-settings-form.js @@ -57,20 +57,20 @@ export default class StripeSettingsForm extends Component { /** OLD **/ get stripeDirectPublicKey() { - return this.settings.get('stripePublishableKey'); + return this.settings.stripePublishableKey; } get stripeDirectSecretKey() { - return this.settings.settings.get('stripeSecretKey'); + return this.settings.stripeSecretKey; } get stripeConnectAccountId() { - return this.settings.get('stripeConnectAccountId'); + return this.settings.stripeConnectAccountId; } get stripeConnectAccountName() { - return this.settings.get('stripeConnectDisplayName'); + return this.settings.stripeConnectDisplayName; } get stripeConnectLivemode() { - return this.settings.get('stripeConnectLivemode'); + return this.settings.stripeConnectLivemode; } get selectedCurrency() { @@ -79,7 +79,7 @@ export default class StripeSettingsForm extends Component { } get stripePlans() { - const plans = this.settings.get('stripePlans'); + const plans = this.settings.stripePlans; const monthly = plans.find(plan => plan.interval === 'month'); const yearly = plans.find(plan => plan.interval === 'year' && plan.name !== 'Complimentary'); @@ -112,14 +112,14 @@ export default class StripeSettingsForm extends Component { @action setStripeDirectPublicKey(event) { - this.settings.set('stripeProductName', this.settings.get('title')); - this.settings.set('stripePublishableKey', event.target.value); + this.settings.stripeProductName = this.settings.title; + this.settings.stripePublishableKey = event.target.value; } @action setStripeDirectSecretKey(event) { - this.settings.set('stripeProductName', this.settings.get('title')); - this.settings.set('stripeSecretKey', event.target.value); + this.settings.stripeProductName = this.settings.title; + this.settings.stripeSecretKey = event.target.value; } @action @@ -130,7 +130,7 @@ export default class StripeSettingsForm extends Component { @action setStripePlansCurrency(event) { const newCurrency = event.value; - const updatedPlans = this.settings.get('stripePlans').map((plan) => { + const updatedPlans = this.settings.stripePlans.map((plan) => { if (plan.name !== 'Complimentary') { return Object.assign({}, plan, { currency: newCurrency @@ -152,7 +152,7 @@ export default class StripeSettingsForm extends Component { }); } - this.settings.set('stripePlans', updatedPlans); + this.settings.stripePlans = updatedPlans; this._scratchStripeYearlyAmount = null; this._scratchStripeMonthlyAmount = null; this.validateStripePlans(); @@ -160,7 +160,7 @@ export default class StripeSettingsForm extends Component { @action setStripeConnectIntegrationToken(event) { - this.settings.set('stripeProductName', this.settings.get('title')); + this.settings.stripeProductName = this.settings.title; this.args.setStripeConnectIntegrationTokenSetting(event.target.value); } @@ -183,13 +183,13 @@ export default class StripeSettingsForm extends Component { updateStripeDirect() { // Allow disabling stripe direct keys if stripe is still enabled, while the config is disabled this.stripeDirect = this.config.get('stripeDirect') - || (this.membersUtils.isStripeEnabled && !this.settings.get('stripeConnectAccountId')); + || (this.membersUtils.isStripeEnabled && !this.settings.stripeConnectAccountId); } @action validateStripePlans() { - this.settings.get('errors').remove('stripePlans'); - this.settings.get('hasValidated').removeObject('stripePlans'); + this.settings.errors.remove('stripePlans'); + this.settings.hasValidated.removeObject('stripePlans'); if (this._scratchStripeYearlyAmount === null) { this._scratchStripeYearlyAmount = this.stripePlans.yearly.amount; @@ -203,7 +203,7 @@ export default class StripeSettingsForm extends Component { const yearlyAmount = parseInt(this._scratchStripeYearlyAmount); const monthlyAmount = parseInt(this._scratchStripeMonthlyAmount); if (!yearlyAmount || yearlyAmount < 1 || !monthlyAmount || monthlyAmount < 1) { - const minimum = Intl.NumberFormat(this.settings.get('locale'), { + const minimum = Intl.NumberFormat(this.settings.locale, { currency: selectedCurrency.isoCode, style: 'currency' }).format(1); @@ -211,7 +211,7 @@ export default class StripeSettingsForm extends Component { throw new TypeError(`Subscription amount must be at least ${minimum}`); } - const updatedPlans = this.settings.get('stripePlans').map((plan) => { + const updatedPlans = this.settings.stripePlans.map((plan) => { if (plan.name !== 'Complimentary') { let newAmount; if (plan.interval === 'year') { @@ -226,11 +226,11 @@ export default class StripeSettingsForm extends Component { return plan; }); - this.settings.set('stripePlans', updatedPlans); + this.settings.stripePlans = updatedPlans; } catch (err) { - this.settings.get('errors').add('stripePlans', err.message); + this.settings.errors.add('stripePlans', err.message); } finally { - this.settings.get('hasValidated').pushObject('stripePlans'); + this.settings.hasValidated.pushObject('stripePlans'); } } @@ -296,12 +296,12 @@ export default class StripeSettingsForm extends Component { *saveStripeSettingsTask() { this.stripeConnectError = null; - if (this.settings.get('stripeConnectIntegrationToken')) { + if (this.settings.stripeConnectIntegrationToken) { try { let response = yield this.settings.save(); yield this.saveTier.perform(); - this.settings.set('portalPlans', ['free', 'monthly', 'yearly']); + this.settings.portalPlans = ['free', 'monthly', 'yearly']; response = yield this.settings.save(); diff --git a/ghost/admin/app/components/settings/newsletters.js b/ghost/admin/app/components/settings/newsletters.js index f0ddb7bdb8..42ed6cf96d 100644 --- a/ghost/admin/app/components/settings/newsletters.js +++ b/ghost/admin/app/components/settings/newsletters.js @@ -20,46 +20,46 @@ export default class Newsletters extends Component { mailgunRegions = [US, EU]; get emailNewsletterEnabled() { - return this.settings.get('editorDefaultEmailRecipients') !== 'disabled'; + return this.settings.editorDefaultEmailRecipients !== 'disabled'; } get mailgunRegion() { - if (!this.settings.get('mailgunBaseUrl')) { + if (!this.settings.mailgunBaseUrl) { return US; } return [US, EU].find((region) => { - return region.baseUrl === this.settings.get('mailgunBaseUrl'); + return region.baseUrl === this.settings.mailgunBaseUrl; }); } get mailgunSettings() { return { - apiKey: this.settings.get('mailgunApiKey') || '', - domain: this.settings.get('mailgunDomain') || '', - baseUrl: this.settings.get('mailgunBaseUrl') || '' + apiKey: this.settings.mailgunApiKey || '', + domain: this.settings.mailgunDomain || '', + baseUrl: this.settings.mailgunBaseUrl || '' }; } @action setMailgunDomain(event) { - this.settings.set('mailgunDomain', event.target.value); - if (!this.settings.get('mailgunBaseUrl')) { - this.settings.set('mailgunBaseUrl', this.mailgunRegion.baseUrl); + this.settings.mailgunDomain = event.target.value; + if (!this.settings.mailgunBaseUrl) { + this.settings.mailgunBaseUrl = this.mailgunRegion.baseUrl; } } @action setMailgunApiKey(event) { - this.settings.set('mailgunApiKey', event.target.value); - if (!this.settings.get('mailgunBaseUrl')) { - this.settings.set('mailgunBaseUrl', this.mailgunRegion.baseUrl); + this.settings.mailgunApiKey = event.target.value; + if (!this.settings.mailgunBaseUrl) { + this.settings.mailgunBaseUrl = this.mailgunRegion.baseUrl; } } @action setMailgunRegion(region) { - this.settings.set('mailgunBaseUrl', region.baseUrl); + this.settings.mailgunBaseUrl = region.baseUrl; } @action @@ -67,7 +67,7 @@ export default class Newsletters extends Component { if (event) { event.preventDefault(); } - this.settings.set('emailTrackOpens', !this.settings.get('emailTrackOpens')); + this.settings.emailTrackOpens = !this.settings.emailTrackOpens; } @action @@ -75,7 +75,7 @@ export default class Newsletters extends Component { if (event) { event.preventDefault(); } - this.settings.set('emailTrackClicks', !this.settings.get('emailTrackClicks')); + this.settings.emailTrackClicks = !this.settings.emailTrackClicks; } @action @@ -87,10 +87,10 @@ export default class Newsletters extends Component { const newsletterEnabled = !this.emailNewsletterEnabled; if (newsletterEnabled) { - this.settings.set('editorDefaultEmailRecipients', 'visibility'); + this.settings.editorDefaultEmailRecipients = 'visibility'; } else { - this.settings.set('editorDefaultEmailRecipients', 'disabled'); - this.settings.set('editorDefaultEmailRecipientsFilter', null); + this.settings.editorDefaultEmailRecipients = 'disabled'; + this.settings.editorDefaultEmailRecipientsFilter = null; } this.recipientsSelectValue = this._getDerivedRecipientsSelectValue(); @@ -106,22 +106,22 @@ export default class Newsletters extends Component { // Update the underlying setting properties to match the selected recipients option if (['visibility', 'disabled'].includes(value)) { - this.settings.set('editorDefaultEmailRecipients', value); - this.settings.set('editorDefaultEmailRecipientsFilter', null); + this.settings.editorDefaultEmailRecipients = value; + this.settings.editorDefaultEmailRecipientsFilter = null; } else { - this.settings.set('editorDefaultEmailRecipients', 'filter'); + this.settings.editorDefaultEmailRecipients = 'filter'; } if (value === 'all-members') { - this.settings.set('editorDefaultEmailRecipientsFilter', 'status:free,status:-free'); + this.settings.editorDefaultEmailRecipientsFilter = 'status:free,status:-free'; } if (value === 'paid-only') { - this.settings.set('editorDefaultEmailRecipientsFilter', 'status:-free'); + this.settings.editorDefaultEmailRecipientsFilter = 'status:-free'; } if (value === 'none') { - this.settings.set('editorDefaultEmailRecipientsFilter', null); + this.settings.editorDefaultEmailRecipientsFilter = null; } // Update the value used to display the selected recipients option explicitly @@ -131,12 +131,12 @@ export default class Newsletters extends Component { @action setDefaultEmailRecipientsFilter(filter) { - this.settings.set('editorDefaultEmailRecipientsFilter', filter); + this.settings.editorDefaultEmailRecipientsFilter = filter; } _getDerivedRecipientsSelectValue() { - const defaultEmailRecipients = this.settings.get('editorDefaultEmailRecipients'); - const defaultEmailRecipientsFilter = this.settings.get('editorDefaultEmailRecipientsFilter'); + const defaultEmailRecipients = this.settings.editorDefaultEmailRecipients; + const defaultEmailRecipientsFilter = this.settings.editorDefaultEmailRecipientsFilter; if (defaultEmailRecipients === 'filter') { if (defaultEmailRecipientsFilter === 'status:free,status:-free') { diff --git a/ghost/admin/app/components/tags/tag-form.js b/ghost/admin/app/components/tags/tag-form.js index 1c9e231377..75eb1f0274 100644 --- a/ghost/admin/app/components/tags/tag-form.js +++ b/ghost/admin/app/components/tags/tag-form.js @@ -21,7 +21,7 @@ export default class TagForm extends Component { @tracked codeInjectionOpen = false; get seoTitle() { - const settingsTitle = this.settings.get('title') || ''; + const settingsTitle = this.settings.title || ''; const tagName = settingsTitle ? `${this.args.tag.name} - ${settingsTitle}` : this.args.tag.name; let metaTitle = this.args.tag.metaTitle || tagName; @@ -74,7 +74,7 @@ export default class TagForm extends Component { } get twitterDescription() { - return this.args.tag.twitterDescription || this.seoDescription || this.settings.get('metaDescription') || ''; + return this.args.tag.twitterDescription || this.seoDescription || this.settings.metaDescription || ''; } get twitterImage() { @@ -86,7 +86,7 @@ export default class TagForm extends Component { } get facebookDescription() { - return this.args.tag.facebookDescription || this.seoDescription || this.settings.get('metaDescription') || ''; + return this.args.tag.facebookDescription || this.seoDescription || this.settings.metaDescription || ''; } get facebookImage() { diff --git a/ghost/admin/app/controllers/editor.js b/ghost/admin/app/controllers/editor.js index 13a7c6d50d..a77cd5f211 100644 --- a/ghost/admin/app/controllers/editor.js +++ b/ghost/admin/app/controllers/editor.js @@ -1039,7 +1039,7 @@ export default class EditorController extends Controller { emailOnly, newsletter } = this.post; - let publishedAtBlogTZ = moment.tz(publishedAtUTC, this.settings.get('timezone')); + let publishedAtBlogTZ = moment.tz(publishedAtUTC, this.settings.timezone); let title = 'Scheduled'; let description = emailOnly ? ['Will be sent'] : ['Will be published']; diff --git a/ghost/admin/app/controllers/lexical-editor.js b/ghost/admin/app/controllers/lexical-editor.js index 0f14fdb88f..b059c2c9ba 100644 --- a/ghost/admin/app/controllers/lexical-editor.js +++ b/ghost/admin/app/controllers/lexical-editor.js @@ -1035,7 +1035,7 @@ export default class LexicalEditorController extends Controller { emailOnly, newsletter } = this.post; - let publishedAtBlogTZ = moment.tz(publishedAtUTC, this.settings.get('timezone')); + let publishedAtBlogTZ = moment.tz(publishedAtUTC, this.settings.timezone); let title = 'Scheduled'; let description = emailOnly ? ['Will be sent'] : ['Will be published']; diff --git a/ghost/admin/app/controllers/members-activity.js b/ghost/admin/app/controllers/members-activity.js index 3a58abe8e0..da787b56df 100644 --- a/ghost/admin/app/controllers/members-activity.js +++ b/ghost/admin/app/controllers/members-activity.js @@ -24,7 +24,7 @@ export default class MembersActivityController extends Controller { hiddenEvents.push(...EMAIL_EVENTS); } - if (this.settings.get('editorDefaultEmailRecipients') === 'disabled') { + if (this.settings.editorDefaultEmailRecipients === 'disabled') { hiddenEvents.push(...EMAIL_EVENTS, ...NEWSLETTER_EVENTS); } diff --git a/ghost/admin/app/controllers/settings/design/index.js b/ghost/admin/app/controllers/settings/design/index.js index 12cc04d356..b9cf476e9c 100644 --- a/ghost/admin/app/controllers/settings/design/index.js +++ b/ghost/admin/app/controllers/settings/design/index.js @@ -35,7 +35,7 @@ export default class SettingsDesignIndexController extends Controller { @task *saveTask() { try { - if (this.settings.get('errors').length !== 0) { + if (this.settings.errors.length !== 0) { return; } diff --git a/ghost/admin/app/controllers/settings/general.js b/ghost/admin/app/controllers/settings/general.js index e69b04f90d..d37c2c7967 100644 --- a/ghost/admin/app/controllers/settings/general.js +++ b/ghost/admin/app/controllers/settings/general.js @@ -39,7 +39,7 @@ export default class GeneralController extends Controller { @computed('config.blogUrl', 'settings.publicHash') get privateRSSUrl() { let blogUrl = this.get('config.blogUrl'); - let publicHash = this.get('settings.publicHash'); + let publicHash = this.settings.publicHash; return `${blogUrl}/${publicHash}/rss`; } @@ -51,13 +51,13 @@ export default class GeneralController extends Controller { @action setTimezone(timezone) { - this.set('settings.timezone', timezone.name); + this.settings.timezone = timezone.name; } @action removeImage(image) { // setting `null` here will error as the server treats it as "null" - this.settings.set(image, ''); + this.settings[image] = ''; } /** @@ -80,7 +80,7 @@ export default class GeneralController extends Controller { @action imageUploaded(property, results) { if (results[0]) { - return this.settings.set(property, results[0].url); + return this.settings[property] = results[0].url; } } @@ -88,18 +88,18 @@ export default class GeneralController extends Controller { toggleIsPrivate(isPrivate) { let settings = this.settings; - settings.set('isPrivate', isPrivate); - settings.get('errors').remove('password'); + settings.isPrivate = isPrivate; + settings.errors.remove('password'); let changedAttrs = settings.changedAttributes(); // set a new random password when isPrivate is enabled if (isPrivate && changedAttrs.isPrivate) { - settings.set('password', randomPassword()); + settings.password = randomPassword(); // reset the password when isPrivate is disabled } else if (changedAttrs.password) { - settings.set('password', changedAttrs.password[0]); + settings.password = changedAttrs.password[0]; } } @@ -135,7 +135,7 @@ export default class GeneralController extends Controller { this.clearScratchValues(); - config.set('blogTitle', settings.get('title')); + config.set('blogTitle', settings.title); if (changedAttrs.password) { this.frontend.loginIfNeeded(); diff --git a/ghost/admin/app/controllers/settings/integrations/amp.js b/ghost/admin/app/controllers/settings/integrations/amp.js index 849c71d165..7edbbcb65c 100644 --- a/ghost/admin/app/controllers/settings/integrations/amp.js +++ b/ghost/admin/app/controllers/settings/integrations/amp.js @@ -9,7 +9,7 @@ export default class AmpController extends Controller { @action update(value) { - this.settings.set('amp', value); + this.settings.amp = value; } @action diff --git a/ghost/admin/app/controllers/settings/integrations/firstpromoter.js b/ghost/admin/app/controllers/settings/integrations/firstpromoter.js index d6a64b30f5..6b1432d650 100644 --- a/ghost/admin/app/controllers/settings/integrations/firstpromoter.js +++ b/ghost/admin/app/controllers/settings/integrations/firstpromoter.js @@ -9,7 +9,7 @@ export default class FirstpromoterController extends Controller { @action update(value) { - this.settings.set('firstpromoter', value); + this.settings.firstpromoter = value; } @action diff --git a/ghost/admin/app/controllers/settings/integrations/slack.js b/ghost/admin/app/controllers/settings/integrations/slack.js index d11a7ebc6e..2393599e6a 100644 --- a/ghost/admin/app/controllers/settings/integrations/slack.js +++ b/ghost/admin/app/controllers/settings/integrations/slack.js @@ -11,7 +11,7 @@ export default class SlackController extends Controller { @service settings; get testNotificationDisabled() { - const slackUrl = this.settings.get('slackUrl'); + const slackUrl = this.settings.slackUrl; return !slackUrl; } diff --git a/ghost/admin/app/controllers/settings/integrations/unsplash.js b/ghost/admin/app/controllers/settings/integrations/unsplash.js index e5c475c1e1..da7b4868fe 100644 --- a/ghost/admin/app/controllers/settings/integrations/unsplash.js +++ b/ghost/admin/app/controllers/settings/integrations/unsplash.js @@ -9,7 +9,7 @@ export default class UnsplashController extends Controller { @action update(value) { - this.settings.set('unsplash', value); + this.settings.unsplash = value; } @action diff --git a/ghost/admin/app/controllers/settings/labs.js b/ghost/admin/app/controllers/settings/labs.js index ee2ce19058..1eb9c1a377 100644 --- a/ghost/admin/app/controllers/settings/labs.js +++ b/ghost/admin/app/controllers/settings/labs.js @@ -119,7 +119,7 @@ export default class LabsController extends Controller { // reload settings return this.settings.reload().then((settings) => { this.feature.fetch(); - this.config.set('blogTitle', settings.get('title')); + this.config.set('blogTitle', settings.title); }); }); }).catch((response) => { diff --git a/ghost/admin/app/controllers/settings/membership.js b/ghost/admin/app/controllers/settings/membership.js index e1b34e7c03..d44bd0416d 100644 --- a/ghost/admin/app/controllers/settings/membership.js +++ b/ghost/admin/app/controllers/settings/membership.js @@ -94,7 +94,7 @@ export default class MembersAccessController extends Controller { } get isDirty() { - return this.settings.get('hasDirtyAttributes') || this.hasChangedPrices; + return this.settings.hasDirtyAttributes || this.hasChangedPrices; } @action @@ -239,7 +239,7 @@ export default class MembersAccessController extends Controller { // TODO: can these be worked out from settings in membersUtils? const monthlyPrice = Math.round(this.stripeMonthlyAmount * 100); const yearlyPrice = Math.round(this.stripeYearlyAmount * 100); - let portalPlans = this.settings.get('portalPlans') || []; + let portalPlans = this.settings.portalPlans || []; let isMonthlyChecked = portalPlans.includes('monthly'); let isYearlyChecked = portalPlans.includes('yearly'); @@ -339,11 +339,11 @@ export default class MembersAccessController extends Controller { @task({drop: true}) *saveSettingsTask(options) { - if (this.settings.get('errors').length !== 0) { + if (this.settings.errors.length !== 0) { return; } // When no filer is selected in `Specific tier(s)` option - if (!this.settings.get('defaultContentVisibility')) { + if (!this.settings.defaultContentVisibility) { return; } const result = yield this.settings.save(); @@ -353,7 +353,7 @@ export default class MembersAccessController extends Controller { } async saveTier() { - const paidMembersEnabled = this.settings.get('paidMembersEnabled'); + const paidMembersEnabled = this.settings.paidMembersEnabled; if (this.tier && paidMembersEnabled) { const monthlyAmount = Math.round(this.stripeMonthlyAmount * 100); const yearlyAmount = Math.round(this.stripeYearlyAmount * 100); @@ -385,12 +385,12 @@ export default class MembersAccessController extends Controller { _validateSignupRedirect(url, type) { const siteUrl = this.config.get('blogUrl'); let errMessage = `Please enter a valid URL`; - this.settings.get('errors').remove(type); - this.settings.get('hasValidated').removeObject(type); + this.settings.errors.remove(type); + this.settings.hasValidated.removeObject(type); if (url === null) { - this.settings.get('errors').add(type, errMessage); - this.settings.get('hasValidated').pushObject(type); + this.settings.errors.add(type, errMessage); + this.settings.hasValidated.pushObject(type); return false; } @@ -401,9 +401,9 @@ export default class MembersAccessController extends Controller { if (url.href.startsWith(siteUrl)) { const path = url.href.replace(siteUrl, ''); - this.settings.set(type, path); + this.settings[type] = path; } else { - this.settings.set(type, url.href); + this.settings[type] = url.href; } } } diff --git a/ghost/admin/app/controllers/settings/navigation.js b/ghost/admin/app/controllers/settings/navigation.js index 15303e1cb0..87abef3e82 100644 --- a/ghost/admin/app/controllers/settings/navigation.js +++ b/ghost/admin/app/controllers/settings/navigation.js @@ -56,7 +56,7 @@ export default class NavigationController extends Controller { return; } - let navItems = item.isSecondary ? this.get('settings.secondaryNavigation') : this.get('settings.navigation'); + let navItems = item.isSecondary ? this.settings.secondaryNavigation : this.settings.navigation; navItems.removeObject(item); this.set('dirtyAttributes', true); @@ -95,7 +95,7 @@ export default class NavigationController extends Controller { } addNewNavItem(item) { - let navItems = item.isSecondary ? this.get('settings.secondaryNavigation') : this.get('settings.navigation'); + let navItems = item.isSecondary ? this.settings.secondaryNavigation : this.settings.navigation; item.set('isNew', false); navItems.pushObject(item); @@ -112,8 +112,8 @@ export default class NavigationController extends Controller { @task *saveTask() { - let navItems = this.get('settings.navigation'); - let secondaryNavItems = this.get('settings.secondaryNavigation'); + let navItems = this.settings.navigation; + let secondaryNavItems = this.settings.secondaryNavigation; let notifications = this.notifications; let validationPromises = []; diff --git a/ghost/admin/app/controllers/settings/tier.js b/ghost/admin/app/controllers/settings/tier.js index 0b0ac6b4a4..7265b208da 100644 --- a/ghost/admin/app/controllers/settings/tier.js +++ b/ghost/admin/app/controllers/settings/tier.js @@ -170,7 +170,7 @@ export default class TierController extends Controller { if (this.tier.get('errors').length !== 0) { return; } - if (this.settings.get('errors').length !== 0) { + if (this.settings.errors.length !== 0) { return; } yield this.settings.save(); @@ -183,12 +183,12 @@ export default class TierController extends Controller { _validateSignupRedirect(url, type) { let errMessage = `Please enter a valid URL`; - this.settings.get('errors').remove(type); - this.settings.get('hasValidated').removeObject(type); + this.settings.errors.remove(type); + this.settings.hasValidated.removeObject(type); if (url === null) { - this.settings.get('errors').add(type, errMessage); - this.settings.get('hasValidated').pushObject(type); + this.settings.errors.add(type, errMessage); + this.settings.hasValidated.pushObject(type); return false; } @@ -199,9 +199,9 @@ export default class TierController extends Controller { if (url.href.startsWith(this.siteUrl)) { const path = url.href.replace(this.siteUrl, ''); - this.settings.set(type, path); + this.settings[type] = path; } else { - this.settings.set(type, url.href); + this.settings[type] = url.href; } } } diff --git a/ghost/admin/app/helpers/get-setting.js b/ghost/admin/app/helpers/get-setting.js index adbbc7be6f..80050598b6 100644 --- a/ghost/admin/app/helpers/get-setting.js +++ b/ghost/admin/app/helpers/get-setting.js @@ -1,11 +1,10 @@ import Helper from '@ember/component/helper'; -import {get} from '@ember/object'; import {inject as service} from '@ember/service'; export default class GetSetting extends Helper { @service settings; compute([key = '']) { - return get(this.settings, key); + return this.settings[key]; } } diff --git a/ghost/admin/app/helpers/gh-format-post-time.js b/ghost/admin/app/helpers/gh-format-post-time.js index 18a0be6812..c9f4c108ee 100644 --- a/ghost/admin/app/helpers/gh-format-post-time.js +++ b/ghost/admin/app/helpers/gh-format-post-time.js @@ -59,6 +59,6 @@ export default class GhFormatPostTimeHelper extends Helper { compute([timeago], options) { assert('You must pass a time to the gh-format-post-time helper', timeago); - return formatPostTime(timeago, Object.assign({}, options, {timezone: this.settings.get('timezone')})); + return formatPostTime(timeago, Object.assign({}, options, {timezone: this.settings.timezone})); } } diff --git a/ghost/admin/app/helpers/is-moment-today.js b/ghost/admin/app/helpers/is-moment-today.js index cfcec154a0..8dcb922a39 100644 --- a/ghost/admin/app/helpers/is-moment-today.js +++ b/ghost/admin/app/helpers/is-moment-today.js @@ -6,8 +6,8 @@ export default class IsMomentToday extends Helper { @service settings; compute([date]) { - const today = moment().tz(this.settings.get('timezone')); - const dateMoment = moment.tz(date, this.settings.get('timezone')); + const today = moment().tz(this.settings.timezone); + const dateMoment = moment.tz(date, this.settings.timezone); return dateMoment.isSame(today, 'day'); } diff --git a/ghost/admin/app/helpers/members-event-filter.js b/ghost/admin/app/helpers/members-event-filter.js index 8bd7b6205f..6f795a8b0f 100644 --- a/ghost/admin/app/helpers/members-event-filter.js +++ b/ghost/admin/app/helpers/members-event-filter.js @@ -17,10 +17,10 @@ export default class MembersEventFilter extends Helper { ) { const excludedEventsSet = new Set(); - if (this.settings.get('editorDefaultEmailRecipients') === 'disabled') { + if (this.settings.editorDefaultEmailRecipients === 'disabled') { [...EMAIL_EVENTS, ...NEWSLETTER_EVENTS].forEach(type => excludedEventsSet.add(type)); } - if (this.settings.get('commentsEnabled') === 'off') { + if (this.settings.commentsEnabled === 'off') { excludedEventsSet.add('comment_event'); } diff --git a/ghost/admin/app/helpers/moment-site-tz.js b/ghost/admin/app/helpers/moment-site-tz.js index 1ff2bb81a7..089fcefc7d 100644 --- a/ghost/admin/app/helpers/moment-site-tz.js +++ b/ghost/admin/app/helpers/moment-site-tz.js @@ -6,6 +6,6 @@ export default class MomentSiteTz extends Helper { @service settings; compute([date]) { - return moment.tz(date, this.settings.get('timezone')); + return moment.tz(date, this.settings.timezone); } } diff --git a/ghost/admin/app/models/post.js b/ghost/admin/app/models/post.js index 07de2fa4eb..1826c6c69b 100644 --- a/ghost/admin/app/models/post.js +++ b/ghost/admin/app/models/post.js @@ -185,39 +185,39 @@ export default Model.extend(Comparable, ValidationEngine, { hasBeenEmailed: computed('isPost', 'isSent', 'isPublished', 'email', function () { return this.isPost - && (this.isSent || this.isPublished) + && (this.isSent || this.isPublished) && this.email && this.email.status !== 'failed'; }), didEmailFail: computed('isPost', 'isSent', 'isPublished', 'email.status', function () { return this.isPost - && (this.isSent || this.isPublished) + && (this.isSent || this.isPublished) && this.email && this.email.status === 'failed'; }), showEmailOpenAnalytics: computed('hasBeenEmailed', 'isSent', 'isPublished', function () { return this.hasBeenEmailed && !this.session.user.isContributor - && this.settings.get('membersSignupAccess') !== 'none' - && this.settings.get('editorDefaultEmailRecipients') !== 'disabled' + && this.settings.membersSignupAccess !== 'none' + && this.settings.editorDefaultEmailRecipients !== 'disabled' && this.hasBeenEmailed && this.email.trackOpens - && this.settings.get('emailTrackOpens'); + && this.settings.emailTrackOpens; }), showEmailClickAnalytics: computed('hasBeenEmailed', 'isSent', 'isPublished', 'email', function () { return this.hasBeenEmailed && !this.session.user.isContributor - && this.settings.get('membersSignupAccess') !== 'none' - && this.settings.get('editorDefaultEmailRecipients') !== 'disabled' - && (this.isSent || this.isPublished) + && this.settings.membersSignupAccess !== 'none' + && this.settings.editorDefaultEmailRecipients !== 'disabled' + && (this.isSent || this.isPublished) && this.email.trackClicks - && this.settings.get('emailTrackClicks'); + && this.settings.emailTrackClicks; }), showAttributionAnalytics: computed('isPage', 'emailOnly', 'isPublished', 'membersUtils.isMembersInviteOnly', function () { - return (this.isPage || !this.emailOnly) - && this.isPublished + return (this.isPage || !this.emailOnly) + && this.isPublished && this.feature.get('memberAttribution') && !this.membersUtils.isMembersInviteOnly && !this.session.user.isContributor; @@ -233,7 +233,7 @@ export default Model.extend(Comparable, ValidationEngine, { || this.showAttributionAnalytics ); }), - + previewUrl: computed('uuid', 'ghostPaths.url', 'config.blogUrl', function () { let blogUrl = this.get('config.blogUrl'); let uuid = this.uuid; @@ -252,7 +252,7 @@ export default Model.extend(Comparable, ValidationEngine, { visibilitySegment: computed('visibility', 'isPublic', 'tiers', function () { if (this.isPublic) { - return this.settings.get('defaultContentVisibility') === 'paid' ? 'status:-free' : 'status:free,status:-free'; + return this.settings.defaultContentVisibility === 'paid' ? 'status:-free' : 'status:free,status:-free'; } else { if (this.visibility === 'members') { return 'status:free,status:-free'; @@ -321,7 +321,7 @@ export default Model.extend(Comparable, ValidationEngine, { let publishedAtUTC = this.publishedAtUTC; let publishedAtBlogDate = this.publishedAtBlogDate; let publishedAtBlogTime = this.publishedAtBlogTime; - let blogTimezone = this.get('settings.timezone'); + let blogTimezone = this.settings.timezone; if (!publishedAtUTC && isBlank(publishedAtBlogDate) && isBlank(publishedAtBlogTime)) { return null; @@ -362,7 +362,7 @@ export default Model.extend(Comparable, ValidationEngine, { _setPublishedAtBlogStrings(momentDate) { if (momentDate) { - let blogTimezone = this.get('settings.timezone'); + let blogTimezone = this.settings.timezone; let publishedAtBlog = moment.tz(momentDate, blogTimezone); this.set('publishedAtBlogDate', publishedAtBlog.format('YYYY-MM-DD')); diff --git a/ghost/admin/app/models/setting.js b/ghost/admin/app/models/setting.js index d35e76d307..490ac7de4f 100644 --- a/ghost/admin/app/models/setting.js +++ b/ghost/admin/app/models/setting.js @@ -1,7 +1,5 @@ -/* eslint-disable camelcase */ import Model, {attr} from '@ember-data/model'; import ValidationEngine from 'ghost-admin/mixins/validation-engine'; -import {and} from '@ember/object/computed'; export default Model.extend(ValidationEngine, { validationType: 'setting', @@ -84,8 +82,6 @@ export default Model.extend(ValidationEngine, { editorDefaultEmailRecipientsFilter: attr('members-segment-string'), emailVerificationRequired: attr('boolean'), - mailgunIsConfigured: and('mailgunApiKey', 'mailgunDomain', 'mailgunBaseUrl'), - // HACK - not a real model attribute but a workaround for Ember Data not // exposing meta from save responses _meta: attr() diff --git a/ghost/admin/app/routes/settings/code-injection.js b/ghost/admin/app/routes/settings/code-injection.js index 47c4bfd831..82717c1363 100644 --- a/ghost/admin/app/routes/settings/code-injection.js +++ b/ghost/admin/app/routes/settings/code-injection.js @@ -45,7 +45,7 @@ export default class CodeInjectionRoute extends AdminRoute { async confirmUnsavedChanges() { const settings = this.settings; - if (settings.get('hasDirtyAttributes')) { + if (settings.hasDirtyAttributes) { this.confirmModal = this.modals .open(ConfirmUnsavedChangesModal) .finally(() => { diff --git a/ghost/admin/app/routes/settings/design/index.js b/ghost/admin/app/routes/settings/design/index.js index 41394c2871..87404885c0 100644 --- a/ghost/admin/app/routes/settings/design/index.js +++ b/ghost/admin/app/routes/settings/design/index.js @@ -36,7 +36,7 @@ export default class SettingsDesignIndexRoute extends AuthenticatedRoute { } confirmUnsavedChanges() { - if (!this.settings.get('hasDirtyAttributes') && !this.customThemeSettings.isDirty) { + if (!this.settings.hasDirtyAttributes && !this.customThemeSettings.isDirty) { return Promise.resolve(true); } diff --git a/ghost/admin/app/routes/settings/general.js b/ghost/admin/app/routes/settings/general.js index f243d1efe0..ed750c1cff 100644 --- a/ghost/admin/app/routes/settings/general.js +++ b/ghost/admin/app/routes/settings/general.js @@ -52,7 +52,7 @@ export default class GeneralSettingsRoute extends AdminRoute { } async confirmUnsavedChanges() { - if (this.settings.get('hasDirtyAttributes')) { + if (this.settings.hasDirtyAttributes) { this.confirmModal = this.modals .open(ConfirmUnsavedChangesModal) .finally(() => { diff --git a/ghost/admin/app/routes/settings/integrations/amp.js b/ghost/admin/app/routes/settings/integrations/amp.js index 7b438ace61..7d17e82871 100644 --- a/ghost/admin/app/routes/settings/integrations/amp.js +++ b/ghost/admin/app/routes/settings/integrations/amp.js @@ -43,7 +43,7 @@ export default class AMPRoute extends AdminRoute { } async confirmUnsavedChanges() { - if (this.settings.get('hasDirtyAttributes')) { + if (this.settings.hasDirtyAttributes) { this.confirmModal = this.modals .open(ConfirmUnsavedChangesModal) .finally(() => { diff --git a/ghost/admin/app/routes/settings/integrations/firstpromoter.js b/ghost/admin/app/routes/settings/integrations/firstpromoter.js index 5772d0d138..573c0fb768 100644 --- a/ghost/admin/app/routes/settings/integrations/firstpromoter.js +++ b/ghost/admin/app/routes/settings/integrations/firstpromoter.js @@ -43,7 +43,7 @@ export default class FirstPromotionIntegrationRoute extends AdminRoute { } async confirmUnsavedChanges() { - if (this.settings.get('hasDirtyAttributes')) { + if (this.settings.hasDirtyAttributes) { this.confirmModal = this.modals .open(ConfirmUnsavedChangesModal) .finally(() => { diff --git a/ghost/admin/app/routes/settings/integrations/slack.js b/ghost/admin/app/routes/settings/integrations/slack.js index d6255d66c1..22424c01bb 100644 --- a/ghost/admin/app/routes/settings/integrations/slack.js +++ b/ghost/admin/app/routes/settings/integrations/slack.js @@ -43,7 +43,7 @@ export default class SlackIntegrationRoute extends AdminRoute { } async confirmUnsavedChanges() { - if (this.settings.get('hasDirtyAttributes')) { + if (this.settings.hasDirtyAttributes) { this.confirmModal = this.modals .open(ConfirmUnsavedChangesModal) .finally(() => { diff --git a/ghost/admin/app/routes/settings/integrations/unsplash.js b/ghost/admin/app/routes/settings/integrations/unsplash.js index 9e05316ad7..96bba29ff0 100644 --- a/ghost/admin/app/routes/settings/integrations/unsplash.js +++ b/ghost/admin/app/routes/settings/integrations/unsplash.js @@ -43,7 +43,7 @@ export default class UnsplashIntegrationRoute extends AdminRoute { } async confirmUnsavedChanges() { - if (this.settings.get('hasDirtyAttributes')) { + if (this.settings.hasDirtyAttributes) { this.confirmModal = this.modals .open(ConfirmUnsavedChangesModal) .finally(() => { diff --git a/ghost/admin/app/routes/settings/newsletters.js b/ghost/admin/app/routes/settings/newsletters.js index ad3a536d5d..2c01410181 100644 --- a/ghost/admin/app/routes/settings/newsletters.js +++ b/ghost/admin/app/routes/settings/newsletters.js @@ -58,7 +58,7 @@ export default class MembersEmailLabsRoute extends AdminRoute { } confirmUnsavedChanges() { - if (!this.settings.get('hasDirtyAttributes')) { + if (!this.settings.hasDirtyAttributes) { return Promise.resolve(true); } diff --git a/ghost/admin/app/services/custom-views.js b/ghost/admin/app/services/custom-views.js index 6364e15d30..96da22ebdb 100644 --- a/ghost/admin/app/services/custom-views.js +++ b/ghost/admin/app/services/custom-views.js @@ -3,9 +3,7 @@ import EmberObject, {action} from '@ember/object'; import Service, {inject as service} from '@ember/service'; import ValidationEngine from 'ghost-admin/mixins/validation-engine'; import {isArray} from '@ember/array'; -import {observes} from '@ember-decorators/object'; import {task} from 'ember-concurrency'; -import {tracked} from '@glimmer/tracking'; const VIEW_COLORS = [ 'midgrey', @@ -108,33 +106,23 @@ export default class CustomViewsService extends Service { @service session; @service settings; - @tracked viewList = []; - - constructor() { - super(...arguments); - this.updateViewList(); - } - - // eslint-disable-next-line ghost/ember/no-observers - @observes('settings.sharedViews', 'session.{isAuthenticated,user}') - async updateViewList() { + get viewList() { let {settings, session} = this; // avoid fetching user before authenticated otherwise the 403 can fire // during authentication and cause errors during setup/signin if (!session.isAuthenticated || !session.user) { - return; + return []; } - let views = JSON.parse(settings.get('sharedViews') || '[]'); + let views = JSON.parse(settings.sharedViews || '[]'); views = isArray(views) ? views : []; - let viewList = []; + const viewList = []; // contributors can only see their own draft posts so it doesn't make // sense to show them default views which change the status/type filter - let user = await session.user; - if (!user.isContributor) { + if (!session.user.isContributor) { viewList.push(...DEFAULT_VIEWS); } @@ -142,15 +130,17 @@ export default class CustomViewsService extends Service { return CustomView.create(view); })); - this.viewList = viewList; + return viewList; } @task *saveViewTask(view) { yield view.validate(); + const {viewList} = this; + // perform some ad-hoc validation of duplicate names because ValidationEngine doesn't support it - let duplicateView = this.viewList.find((existingView) => { + let duplicateView = viewList.find((existingView) => { return existingView.route === view.route && existingView.name.trim().toLowerCase() === view.name.trim().toLowerCase() && !isFilterEqual(existingView.filter, view.filter); @@ -165,15 +155,15 @@ export default class CustomViewsService extends Service { // remove an older version of the view from our views list // - we don't allow editing the filter and route+filter combos are unique // - we create a new instance of a view from an existing one when editing to act as a "scratch" view - let matchingView = this.viewList.find(existingView => isViewEqual(existingView, view)); + let matchingView = viewList.find(existingView => isViewEqual(existingView, view)); if (matchingView) { - this.viewList.replace(this.viewList.indexOf(matchingView), 1, [view]); + viewList.replace(viewList.indexOf(matchingView), 1, [view]); } else { - this.viewList.push(view); + viewList.push(view); } // rebuild the "views" array in our user settings json string - yield this._saveViewSettings(); + yield this._saveViewSettings(viewList); view.set('isNew', false); return view; @@ -181,10 +171,11 @@ export default class CustomViewsService extends Service { @task *deleteViewTask(view) { - let matchingView = this.viewList.find(existingView => isViewEqual(existingView, view)); + const {viewList} = this; + let matchingView = viewList.find(existingView => isViewEqual(existingView, view)); if (matchingView && !matchingView.isDefault) { - this.viewList.removeObject(matchingView); - yield this._saveViewSettings(); + viewList.removeObject(matchingView); + yield this._saveViewSettings(viewList); return true; } } @@ -234,9 +225,9 @@ export default class CustomViewsService extends Service { }); } - async _saveViewSettings() { - let sharedViews = this.viewList.reject(view => view.isDefault).map(view => view.toJSON()); - this.settings.set('sharedViews', JSON.stringify(sharedViews)); + async _saveViewSettings(viewList) { + let sharedViews = viewList.reject(view => view.isDefault).map(view => view.toJSON()); + this.settings.sharedViews = JSON.stringify(sharedViews); return this.settings.save(); } } diff --git a/ghost/admin/app/services/dashboard-stats.js b/ghost/admin/app/services/dashboard-stats.js index b965c38c78..52781715f9 100644 --- a/ghost/admin/app/services/dashboard-stats.js +++ b/ghost/admin/app/services/dashboard-stats.js @@ -366,7 +366,7 @@ export default class DashboardStatsService extends Service { this.siteStatus = { hasPaidTiers, hasMultipleTiers: hasPaidTiers && this.activePaidTiers.length > 1, - newslettersEnabled: this.settings.get('editorDefaultEmailRecipients') !== 'disabled', + newslettersEnabled: this.settings.editorDefaultEmailRecipients !== 'disabled', membersEnabled: this.membersUtils.isMembersEnabled }; } diff --git a/ghost/admin/app/services/feature.js b/ghost/admin/app/services/feature.js index 6582e58be4..0fa14c381c 100644 --- a/ghost/admin/app/services/feature.js +++ b/ghost/admin/app/services/feature.js @@ -71,7 +71,7 @@ export default class FeatureService extends Service { @computed('settings.labs') get labs() { - let labs = this.get('settings.labs'); + let labs = this.settings.labs; try { return JSON.parse(labs) || {}; diff --git a/ghost/admin/app/services/frontend.js b/ghost/admin/app/services/frontend.js index 12543a487f..aac277161d 100644 --- a/ghost/admin/app/services/frontend.js +++ b/ghost/admin/app/services/frontend.js @@ -11,7 +11,7 @@ export default class FrontendService extends Service { _lastPassword = null; get hasPasswordChanged() { - return this._lastPassword !== this.settings.get('password'); + return this._lastPassword !== this.settings.password; } getUrl(path) { @@ -23,9 +23,9 @@ export default class FrontendService extends Service { } async loginIfNeeded() { - if (this.settings.get('isPrivate') && (this.hasPasswordChanged || !this._hasLoggedIn)) { + if (this.settings.isPrivate && (this.hasPasswordChanged || !this._hasLoggedIn)) { const privateLoginUrl = this.getUrl('/private/?r=%2F'); - this._lastPassword = this.settings.get('password'); + this._lastPassword = this.settings.password; return fetch(privateLoginUrl, { method: 'POST', diff --git a/ghost/admin/app/services/members-utils.js b/ghost/admin/app/services/members-utils.js index c2af1fc6e8..97df368357 100644 --- a/ghost/admin/app/services/members-utils.js +++ b/ghost/admin/app/services/members-utils.js @@ -7,15 +7,15 @@ export default class MembersUtilsService extends Service { @service store; get isMembersEnabled() { - return this.settings.get('membersEnabled'); + return this.settings.membersEnabled; } get paidMembersEnabled() { - return this.settings.get('paidMembersEnabled'); + return this.settings.paidMembersEnabled; } get isMembersInviteOnly() { - return this.settings.get('membersInviteOnly'); + return this.settings.membersInviteOnly; } /** @@ -24,8 +24,8 @@ export default class MembersUtilsService extends Service { get isStripeEnabled() { const stripeDirect = this.config.get('stripeDirect'); - const hasDirectKeys = !!this.settings.get('stripeSecretKey') && !!this.settings.get('stripePublishableKey'); - const hasConnectKeys = !!this.settings.get('stripeConnectSecretKey') && !!this.settings.get('stripeConnectPublishableKey'); + const hasDirectKeys = !!this.settings.stripeSecretKey && !!this.settings.stripePublishableKey; + const hasConnectKeys = !!this.settings.stripeConnectSecretKey && !!this.settings.stripeConnectPublishableKey; if (stripeDirect) { return hasDirectKeys; @@ -66,23 +66,23 @@ export default class MembersUtilsService extends Service { } get buttonIcon() { - return this.settings.get('portalButtonIcon') || this.defaultIconKeys[0]; + return this.settings.portalButtonIcon || this.defaultIconKeys[0]; } // Plan helpers ------------------------------------------------------------ get isFreeChecked() { - const allowedPlans = this.settings.get('portalPlans') || []; - return !!(this.settings.get('membersSignupAccess') === 'all' && allowedPlans.includes('free')); + const allowedPlans = this.settings.portalPlans || []; + return !!(this.settings.membersSignupAccess === 'all' && allowedPlans.includes('free')); } get isMonthlyChecked() { - const allowedPlans = this.settings.get('portalPlans') || []; + const allowedPlans = this.settings.portalPlans || []; return !!(this.isStripeConfigured && allowedPlans.includes('monthly')); } get isYearlyChecked() { - const allowedPlans = this.settings.get('portalPlans') || []; + const allowedPlans = this.settings.portalPlans || []; return !!(this.isStripeConfigured && allowedPlans.includes('yearly')); } @@ -92,17 +92,17 @@ export default class MembersUtilsService extends Service { let { disableBackground = false, page = 'signup', - button = this.settings.get('portalButton'), + button = this.settings.portalButton, buttonIcon = this.buttonIcon, isFreeChecked = this.isFreeChecked, isMonthlyChecked = this.isMonthlyChecked, isYearlyChecked = this.isYearlyChecked, monthlyPrice, yearlyPrice, - portalPlans = this.settings.get('portalPlans'), + portalPlans = this.settings.portalPlans, portalTiers, currency, - membersSignupAccess = this.settings.get('membersSignupAccess') + membersSignupAccess = this.settings.membersSignupAccess } = overrides; const tiers = this.store.peekAll('tier') || []; @@ -114,11 +114,11 @@ export default class MembersUtilsService extends Service { const baseUrl = this.config.get('blogUrl'); const portalBase = '/#/portal/preview'; const settingsParam = new URLSearchParams(); - const signupButtonText = this.settings.get('portalButtonSignupText') || ''; + const signupButtonText = this.settings.portalButtonSignupText || ''; const allowSelfSignup = membersSignupAccess === 'all' && (!this.isStripeEnabled || isFreeChecked); settingsParam.append('button', button); - settingsParam.append('name', this.settings.get('portalName')); + settingsParam.append('name', this.settings.portalName); settingsParam.append('isFree', isFreeChecked); settingsParam.append('isMonthly', isMonthlyChecked); settingsParam.append('isYearly', isYearlyChecked); @@ -136,11 +136,11 @@ export default class MembersUtilsService extends Service { settingsParam.append('portalProducts', encodeURIComponent(portalTiers)); } - if (this.settings.get('accentColor') === '' || this.settings.get('accentColor')) { - settingsParam.append('accentColor', encodeURIComponent(`${this.settings.get('accentColor')}`)); + if (this.settings.accentColor === '' || this.settings.accentColor) { + settingsParam.append('accentColor', encodeURIComponent(`${this.settings.accentColor}`)); } - if (this.settings.get('portalButtonStyle')) { - settingsParam.append('buttonStyle', encodeURIComponent(this.settings.get('portalButtonStyle'))); + if (this.settings.portalButtonStyle) { + settingsParam.append('buttonStyle', encodeURIComponent(this.settings.portalButtonStyle)); } if (monthlyPrice) { diff --git a/ghost/admin/app/services/navigation.js b/ghost/admin/app/services/navigation.js index e7c7499c83..cf80301c69 100644 --- a/ghost/admin/app/services/navigation.js +++ b/ghost/admin/app/services/navigation.js @@ -1,5 +1,5 @@ import Service, {inject as service} from '@ember/service'; -import {action, set} from '@ember/object'; +import {action} from '@ember/object'; import {observes} from '@ember-decorators/object'; import {tracked} from '@glimmer/tracking'; @@ -39,10 +39,7 @@ export default class NavigationService extends Service { this.settings.expanded = {}; } - // set is still needed here because we're not tracking deep keys - // and Ember picks up that our templates are dependent on them and - // complains. TODO: can we avoid set? - set(this.settings.expanded, key, !this.settings.expanded[key]); + this.settings.expanded[key] = !this.settings.expanded[key]; return await this._saveNavigationSettings(); } diff --git a/ghost/admin/app/services/settings.js b/ghost/admin/app/services/settings.js index 002b030575..5d45a7dd80 100644 --- a/ghost/admin/app/services/settings.js +++ b/ghost/admin/app/services/settings.js @@ -1,27 +1,28 @@ -import Ember from 'ember'; -import RSVP from 'rsvp'; import Service, {inject as service} from '@ember/service'; import ValidationEngine from 'ghost-admin/mixins/validation-engine'; -import classic from 'ember-classic-decorator'; -import {get} from '@ember/object'; +import {tracked} from '@glimmer/tracking'; -// ember-cli-shims doesn't export _ProxyMixin -const {_ProxyMixin} = Ember; - -@classic -export default class SettingsService extends Service.extend(_ProxyMixin, ValidationEngine) { +export default class SettingsService extends Service.extend(ValidationEngine) { @service store; // will be set to the single Settings model, it's a reference so any later // changes to the settings object in the store will be reflected - content = null; + settingsModel = null; validationType = 'setting'; _loadingPromise = null; // this is an odd case where we only want to react to changes that we get // back from the API rather than local updates - settledIcon = ''; + @tracked settledIcon = ''; + + get hasDirtyAttributes() { + return this.settingsModel?.hasDirtyAttributes || false; + } + + get mailgunIsConfigured() { + return this.mailgunApiKey && this.mailgunDomain && this.mailgunBaseUrl; + } // the settings API endpoint is a little weird as it's singular and we have // to pass in all types - if we ever fetch settings without all types then @@ -39,40 +40,56 @@ export default class SettingsService extends Service.extend(_ProxyMixin, Validat return this._loadingPromise; } - fetch() { - if (!this.content) { + async fetch() { + if (!this.settingsModel) { return this.reload(); } else { - return RSVP.resolve(this); + return this; } } - reload() { - return this._loadSettings().then((settings) => { - this.set('content', settings); - this.set('settledIcon', get(settings, 'icon')); - return this; + async reload() { + const settingsModel = await this._loadSettings(); + + this.settingsModel = settingsModel; + this.settledIcon = settingsModel.icon; + + settingsModel.eachAttribute((name) => { + if (!Object.prototype.hasOwnProperty.call(this, name)) { + Object.defineProperty(this, name, { + get() { + return this.settingsModel[name]; + }, + set(newValue) { + this.settingsModel[name] = newValue; + } + }); + } }); + + return this; } async save() { - let settings = this.content; + const {settingsModel} = this; - if (!settings) { + if (!settingsModel) { return false; } - await settings.save(); + await settingsModel.save(); await this.validate(); - this.set('settledIcon', settings.icon); - return settings; + + this.settledIcon = settingsModel.icon; + + return this; } rollbackAttributes() { - return this.content?.rollbackAttributes(); + return this.settingsModel?.rollbackAttributes(); } changedAttributes() { - return this.content?.changedAttributes(); + return this.settingsModel?.changedAttributes(); } } diff --git a/ghost/admin/app/services/theme-management.js b/ghost/admin/app/services/theme-management.js index e12e44cc03..24e4339bc8 100644 --- a/ghost/admin/app/services/theme-management.js +++ b/ghost/admin/app/services/theme-management.js @@ -193,11 +193,11 @@ export default class ThemeManagementService extends Service { get previewData() { const params = new URLSearchParams(); - params.append('c', this.settings.get('accentColor') || '#ffffff'); - params.append('d', this.settings.get('description')); - params.append('icon', this.settings.get('icon')); - params.append('logo', this.settings.get('logo')); - params.append('cover', this.settings.get('coverImage')); + params.append('c', this.settings.accentColor || '#ffffff'); + params.append('d', this.settings.description); + params.append('icon', this.settings.icon); + params.append('logo', this.settings.logo); + params.append('cover', this.settings.coverImage); params.append('custom', JSON.stringify(this.customThemeSettings.keyValueObject)); diff --git a/ghost/admin/app/services/ui.js b/ghost/admin/app/services/ui.js index 034087ce1c..92b5bfad82 100644 --- a/ghost/admin/app/services/ui.js +++ b/ghost/admin/app/services/ui.js @@ -70,7 +70,7 @@ export default class UiService extends Service { } get adjustedAccentColor() { - const accentColor = Color(this.settings.get('accentColor')); + const accentColor = Color(this.settings.accentColor); const backgroundColor = Color(this.backgroundColor); // WCAG contrast. 1 = lowest contrast, 21 = highest contrast diff --git a/ghost/admin/app/utils/publish-options.js b/ghost/admin/app/utils/publish-options.js index 8f320b6b4f..3a43fba62f 100644 --- a/ghost/admin/app/utils/publish-options.js +++ b/ghost/admin/app/utils/publish-options.js @@ -113,8 +113,8 @@ export default class PublishOptions { } get emailDisabledInSettings() { - return get(this.settings, 'editorDefaultEmailRecipients') === 'disabled' - || get(this.settings, 'membersSignupAccess') === 'none'; + return this.settings.editorDefaultEmailRecipients === 'disabled' + || this.settings.membersSignupAccess === 'none'; } // publish type dropdown is not shown at all @@ -130,7 +130,7 @@ export default class PublishOptions { } get mailgunIsConfigured() { - return get(this.settings, 'mailgunIsConfigured') + return this.settings.mailgunIsConfigured || get(this.config, 'mailgunIsConfigured'); } @@ -168,8 +168,8 @@ export default class PublishOptions { } get defaultRecipientFilter() { - const recipients = this.settings.get('editorDefaultEmailRecipients'); - const filter = this.settings.get('editorDefaultEmailRecipientsFilter'); + const recipients = this.settings.editorDefaultEmailRecipients; + const filter = this.settings.editorDefaultEmailRecipientsFilter; const usuallyNobody = recipients === 'filter' && filter === null; @@ -254,8 +254,8 @@ export default class PublishOptions { // Set publish type to "Publish" but keep email recipients matching post visibility // to avoid multiple clicks to turn on emailing if ( - this.settings.get('editorDefaultEmailRecipients') === 'filter' && - this.settings.get('editorDefaultEmailRecipientsFilter') === null + this.settings.editorDefaultEmailRecipients === 'filter' && + this.settings.editorDefaultEmailRecipientsFilter === null ) { this.publishType = 'publish'; } @@ -382,7 +382,7 @@ export default class PublishOptions { try { if (this.limit.limiter && this.limit.limiter.isLimited('emails')) { await this.limit.limiter.errorIfWouldGoOverLimit('emails'); - } else if (get(this.settings, 'emailVerificationRequired')) { + } else if (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) { diff --git a/ghost/admin/tests/integration/helpers/gh-format-post-time-test.js b/ghost/admin/tests/integration/helpers/gh-format-post-time-test.js index 6250ac3ae5..26ac760a12 100644 --- a/ghost/admin/tests/integration/helpers/gh-format-post-time-test.js +++ b/ghost/admin/tests/integration/helpers/gh-format-post-time-test.js @@ -16,8 +16,8 @@ describe('Integration: Helper: gh-format-post-time', function () { beforeEach(function () { let settings = this.owner.lookup('service:settings'); - settings.content = {}; - settings.set('timezone', timezoneForTest); + settings.settingsModel = {}; + settings.timezone = timezoneForTest; }); afterEach(function () { diff --git a/ghost/admin/tests/unit/controllers/settings/design-test.js b/ghost/admin/tests/unit/controllers/settings/design-test.js index e8faf14e99..543a0a2ac4 100644 --- a/ghost/admin/tests/unit/controllers/settings/design-test.js +++ b/ghost/admin/tests/unit/controllers/settings/design-test.js @@ -50,13 +50,13 @@ describe.skip('Unit: Controller: settings/design', function () { NavItem.create({label: 'Third', url: ''}) ]})); // blank item won't get added because the last item is incomplete - expect(ctrl.get('settings.navigation.length')).to.equal(3); + expect(ctrl.settings.navigation.length).to.equal(3); ctrl.get('save').perform().then(function passedValidation() { assert(false, 'navigationItems weren\'t validated on save'); done(); }).catch(function failedValidation() { - let navItems = ctrl.get('settings.navigation'); + let navItems = ctrl.settings.navigation; expect(navItems[0].get('errors').toArray()).to.be.empty; expect(navItems[1].get('errors.firstObject.attribute')).to.equal('label'); expect(navItems[2].get('errors.firstObject.attribute')).to.equal('url'); @@ -74,13 +74,13 @@ describe.skip('Unit: Controller: settings/design', function () { NavItem.create({label: '', url: ''}) ]})); - expect(ctrl.get('settings.navigation.length')).to.equal(2); + expect(ctrl.settings.navigation.length).to.equal(2); ctrl.get('save').perform().then(function passedValidation() { assert(false, 'navigationItems weren\'t validated on save'); done(); }).catch(function failedValidation() { - let navItems = ctrl.get('settings.navigation'); + let navItems = ctrl.settings.navigation; expect(navItems[0].get('errors').toArray()).to.be.empty; done(); }); @@ -96,7 +96,7 @@ describe.skip('Unit: Controller: settings/design', function () { ]})); }); - expect(ctrl.get('settings.navigation.length')).to.equal(1); + expect(ctrl.settings.navigation.length).to.equal(1); ctrl.set('newNavItem.label', 'New'); ctrl.set('newNavItem.url', '/new'); @@ -105,10 +105,10 @@ describe.skip('Unit: Controller: settings/design', function () { ctrl.send('addNavItem', ctrl.get('newNavItem')); }); - expect(ctrl.get('settings.navigation.length')).to.equal(2); - expect(ctrl.get('settings.navigation.lastObject.label')).to.equal('New'); - expect(ctrl.get('settings.navigation.lastObject.url')).to.equal('/new'); - expect(ctrl.get('settings.navigation.lastObject.isNew')).to.be.false; + expect(ctrl.settings.navigation.length).to.equal(2); + expect(ctrl.settings.navigation.lastObject.label).to.equal('New'); + expect(ctrl.settings.navigation.lastObject.url).to.equal('/new'); + expect(ctrl.settings.navigation.lastObject.isNew).to.be.false; expect(ctrl.get('newNavItem.label')).to.be.empty; expect(ctrl.get('newNavItem.url')).to.be.empty; expect(ctrl.get('newNavItem.isNew')).to.be.true; @@ -121,9 +121,9 @@ describe.skip('Unit: Controller: settings/design', function () { ctrl.set('settings', EmberObject.create({navigation: [ NavItem.create({label: '', url: '', last: true}) ]})); - expect(ctrl.get('settings.navigation.length')).to.equal(1); - ctrl.send('addNavItem', ctrl.get('settings.navigation.lastObject')); - expect(ctrl.get('settings.navigation.length')).to.equal(1); + expect(ctrl.settings.navigation.length).to.equal(1); + ctrl.send('addNavItem', ctrl.settings.navigation.lastObject); + expect(ctrl.settings.navigation.length).to.equal(1); }); }); @@ -136,9 +136,9 @@ describe.skip('Unit: Controller: settings/design', function () { run(() => { ctrl.set('settings', EmberObject.create({navigation: navItems})); - expect(ctrl.get('settings.navigation').mapBy('label')).to.deep.equal(['First', 'Second']); - ctrl.send('deleteNavItem', ctrl.get('settings.navigation.firstObject')); - expect(ctrl.get('settings.navigation').mapBy('label')).to.deep.equal(['Second']); + expect(ctrl.settings.navigation.mapBy('label')).to.deep.equal(['First', 'Second']); + ctrl.send('deleteNavItem', ctrl.settings.navigation.firstObject); + expect(ctrl.settings.navigation.mapBy('label')).to.deep.equal(['Second']); }); }); @@ -151,9 +151,9 @@ describe.skip('Unit: Controller: settings/design', function () { run(() => { ctrl.set('settings', EmberObject.create({navigation: navItems})); - expect(ctrl.get('settings.navigation').mapBy('url')).to.deep.equal(['/first', '/second']); - ctrl.send('updateUrl', '/new', ctrl.get('settings.navigation.firstObject')); - expect(ctrl.get('settings.navigation').mapBy('url')).to.deep.equal(['/new', '/second']); + expect(ctrl.settings.navigation.mapBy('url')).to.deep.equal(['/first', '/second']); + ctrl.send('updateUrl', '/new', ctrl.settings.navigation.firstObject); + expect(ctrl.settings.navigation.mapBy('url')).to.deep.equal(['/new', '/second']); }); }); });