mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
Moved members settings to new page (#1736)
no refs Moves members related settings in Labs to its own page to improve the overall UX and make it more consistent with the rest of the Admin.
This commit is contained in:
parent
f1bab33296
commit
6ecba355eb
@ -1,13 +1,29 @@
|
||||
<div class="flex flex-column b--whitegrey bt">
|
||||
<div class="flex flex-column b--whitegrey bt mb5">
|
||||
|
||||
<section class="bb b--whitegrey pa5">
|
||||
{{#if (and this.feature.labs.members (or (enable-developer-experiments) this.config.portal))}}
|
||||
<div class="gh-setting-header">Portal</div>
|
||||
<section class="flex flex-column br3 shadow-1 bg-grouped-table mt1 pa5 relative gh-settings-portal-section">
|
||||
<div class="gh-setting-last gh-setting-first relative">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Portal settings</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">Customize members modal signup flow</p>
|
||||
</div>
|
||||
<div class="gh-setting-action">
|
||||
<button type="button" class="gh-btn gh-btn-outline blue" {{action (toggle "showPortalSettings" this)}} data-test-toggle-membersFrom><span> Customize </span></button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
<div class="gh-setting-header">Payments</div>
|
||||
<section class="flex flex-column br3 shadow-1 bg-grouped-table mt1 pa5">
|
||||
{{#if this.stripeDirect}}
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<div class="gh-setting-first">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Connect to Stripe</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">Configure API keys to create subscriptions and take payments</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="gh-setting-action">
|
||||
<button type="button" class="gh-btn" {{action (toggle "membersStripeOpen" this)}} data-test-toggle-membersstripe><span>{{if this.membersStripeOpen "Close" "Expand"}}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
@ -52,8 +68,8 @@
|
||||
</div>
|
||||
{{/liquid-if}}
|
||||
{{else}}
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<div class="gh-setting-first">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Connect to Stripe</h4>
|
||||
{{#if this.stripeConnectAccountId}}
|
||||
{{#if this.hasActiveStripeSubscriptions}}
|
||||
@ -77,7 +93,7 @@
|
||||
<p class="gh-setting-desc pa0 ma0">Connect to Stripe to create subscriptions and take payments</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div>
|
||||
<div class="gh-setting-action">
|
||||
{{#if this.stripeConnectAccountId}}
|
||||
<button type="button" class="gh-btn" {{action "openDisconnectStripeModal"}}><span>Disconnect</span></button>
|
||||
{{else}}
|
||||
@ -87,7 +103,7 @@
|
||||
</div>
|
||||
|
||||
{{#liquid-if this.membersStripeOpen}}
|
||||
<div class="mb4 mt6">
|
||||
<div class="mt2">
|
||||
<div class="flex flex-column flex-row-l items-start justify-between">
|
||||
<div class="w-100 w-50-l">
|
||||
<label class="fw6 f8">Generate secure key</label>
|
||||
@ -138,29 +154,13 @@
|
||||
</div>
|
||||
{{/liquid-if}}
|
||||
{{/if}}
|
||||
</section>
|
||||
|
||||
{{#if (or (enable-developer-experiments) this.config.portal)}}
|
||||
<section class="bb b--whitegrey pa5">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<h4 class="gh-setting-title">Portal settings</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">Customize members modal signup flow</p>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="gh-btn" {{action (toggle "showPortalSettings" this)}} data-test-toggle-membersFrom><span> Customize </span></button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
<section class="bb b--whitegrey pa5">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<div class="gh-setting-last">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Subscription pricing</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">Set monthly and yearly recurring subscription prices</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="gh-setting-action">
|
||||
<button type="button" class="gh-btn" {{action (toggle "membersPricingOpen" this)}} data-test-toggle-memberspricing><span>{{if this.membersPricingOpen "Close" "Expand"}}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
@ -221,13 +221,14 @@
|
||||
{{/liquid-if}}
|
||||
</section>
|
||||
|
||||
<section class="bb b--whitegrey pa5">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<div class="gh-setting-header">Access</div>
|
||||
<section class="flex flex-column br3 shadow-1 bg-grouped-table mt1 pa5">
|
||||
<div class="gh-setting-first">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Allow free member signup</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">If disabled, members can only be signed up via payment checkout or API integration</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="gh-setting-action">
|
||||
<div class="for-switch">
|
||||
<label class="switch" for="members-allow-self-signup" {{action "toggleSelfSignup" bubbles="false"}}>
|
||||
<input type="checkbox" checked={{this.allowSelfSignup}} class="gh-input" onclick={{action "toggleSelfSignup"}} data-test-checkbox="members-allow-self-signup">
|
||||
@ -236,15 +237,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="bb b--whitegrey pa5">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<div class="gh-setting-last">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Default post access</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">When a new post is created, who should have access to it?</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="gh-setting-action">
|
||||
<button type="button" class="gh-btn" {{action (toggle "membersPostAccessOpen" this)}} data-test-toggle-memberspostaccess><span>{{if this.membersPostAccessOpen "Close" "Expand"}}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
@ -281,19 +280,20 @@
|
||||
{{/liquid-if}}
|
||||
</section>
|
||||
|
||||
<section class="bb b--whitegrey pa5">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<div class="gh-setting-header">Email</div>
|
||||
<section class="flex flex-column br3 shadow-1 bg-grouped-table mt1 pa5">
|
||||
<div class="gh-setting-first">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Email addresses</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">Contact information used for newsletters and member login emails</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="gh-setting-action">
|
||||
<button type="button" class="gh-btn" {{action (toggle "membersFromOpen" this)}} data-test-toggle-membersFrom><span>{{if this.membersFromOpen "Close" "Expand"}}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#liquid-if this.membersFromOpen}}
|
||||
<div class="mt8">
|
||||
<div class="mt2">
|
||||
<GhFormGroup>
|
||||
<label class="fw6 f8">Support email address</label>
|
||||
<div class="flex items-center justify-center mt1">
|
||||
@ -377,15 +377,14 @@
|
||||
</div>
|
||||
</div>
|
||||
{{/liquid-if}}
|
||||
</section>
|
||||
{{#unless this.mailgunIsConfigured}}
|
||||
<section class="bb b--whitegrey pa5">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
|
||||
{{#unless this.mailgunIsConfigured}}
|
||||
<div class="gh-setting-last">
|
||||
<div class="gh-setting-content">
|
||||
<h4 class="gh-setting-title">Email newsletter settings</h4>
|
||||
<p class="gh-setting-desc pa0 ma0">The <a href="https://www.mailgun.com/" target="_blank" rel="nofollow noopener">Mailgun API</a> is used for bulk email newsletter delivery. <a href="https://ghost.org/faq/mailgun-newsletters/" target="_blank" rel="noopener">Why is this required?</a></p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="gh-setting-action">
|
||||
<button type="button" class="gh-btn" {{action (toggle "membersEmailOpen" this)}} data-test-toggle-membersemail>
|
||||
<span>{{if this.membersEmailOpen "Close" "Expand"}}</span>
|
||||
</button>
|
||||
@ -394,54 +393,54 @@
|
||||
|
||||
{{#liquid-if this.membersEmailOpen}}
|
||||
<div class="flex flex-column w-100 w-50-l flex mt8">
|
||||
<div class="flex items-center">
|
||||
<GhFormGroup @class="gh-labs-mailgun-region">
|
||||
<label class="fw6 f8">Mailgun region</label>
|
||||
<div class="mt1">
|
||||
<PowerSelect
|
||||
@options={{this.mailgunRegions}}
|
||||
@selected={{this.mailgunRegion}}
|
||||
@onChange={{action "setMailgunRegion"}}
|
||||
@searchEnabled={{false}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
as |region|
|
||||
>
|
||||
{{region.flag}} {{region.name}}
|
||||
</PowerSelect>
|
||||
</div>
|
||||
</GhFormGroup>
|
||||
<GhFormGroup>
|
||||
<label class="fw6 f8">Mailgun domain</label>
|
||||
<GhTextInput
|
||||
@value={{readonly this.mailgunSettings.domain}}
|
||||
@input={{action "setMailgunDomain"}}
|
||||
@class="mt1"
|
||||
data-test-mailgun-domain-input={{true}}
|
||||
/>
|
||||
</GhFormGroup>
|
||||
</div>
|
||||
<div class="nt5 mb5">
|
||||
<a href="https://app.mailgun.com/app/sending/domains" target="_blank" class="mt1 fw4 f8">
|
||||
Find your Mailgun region and domain here »
|
||||
</a>
|
||||
</div>
|
||||
<GhFormGroup>
|
||||
<label class="fw6 f8">Mailgun API key</label>
|
||||
<GhTextInput
|
||||
@type="password"
|
||||
@value={{readonly this.mailgunSettings.apiKey}}
|
||||
@input={{action "setMailgunApiKey"}}
|
||||
@class="mt1 password" @autocomplete="new-password"
|
||||
data-test-mailgun-api-key-input={{true}}
|
||||
/>
|
||||
<a href="https://app.mailgun.com/app/account/security/api_keys" target="_blank" class="mt1 fw4 f8">
|
||||
Find your Mailgun API keys here »
|
||||
</a>
|
||||
<div class="flex items-center">
|
||||
<GhFormGroup @class="gh-labs-mailgun-region">
|
||||
<label class="fw6 f8">Mailgun region</label>
|
||||
<div class="mt1">
|
||||
<PowerSelect
|
||||
@options={{this.mailgunRegions}}
|
||||
@selected={{this.mailgunRegion}}
|
||||
@onChange={{action "setMailgunRegion"}}
|
||||
@searchEnabled={{false}}
|
||||
@triggerComponent="gh-power-select/trigger"
|
||||
as |region|
|
||||
>
|
||||
{{region.flag}} {{region.name}}
|
||||
</PowerSelect>
|
||||
</div>
|
||||
</GhFormGroup>
|
||||
<GhFormGroup>
|
||||
<label class="fw6 f8">Mailgun domain</label>
|
||||
<GhTextInput
|
||||
@value={{readonly this.mailgunSettings.domain}}
|
||||
@input={{action "setMailgunDomain"}}
|
||||
@class="mt1"
|
||||
data-test-mailgun-domain-input={{true}}
|
||||
/>
|
||||
</GhFormGroup>
|
||||
</div>
|
||||
<div class="nt5 mb5">
|
||||
<a href="https://app.mailgun.com/app/sending/domains" target="_blank" class="mt1 fw4 f8">
|
||||
Find your Mailgun region and domain here »
|
||||
</a>
|
||||
</div>
|
||||
<GhFormGroup>
|
||||
<label class="fw6 f8">Mailgun API key</label>
|
||||
<GhTextInput
|
||||
@type="password"
|
||||
@value={{readonly this.mailgunSettings.apiKey}}
|
||||
@input={{action "setMailgunApiKey"}}
|
||||
@class="mt1 password" @autocomplete="new-password"
|
||||
data-test-mailgun-api-key-input={{true}}
|
||||
/>
|
||||
<a href="https://app.mailgun.com/app/account/security/api_keys" target="_blank" class="mt1 fw4 f8">
|
||||
Find your Mailgun API keys here »
|
||||
</a>
|
||||
</GhFormGroup>
|
||||
</div>
|
||||
{{/liquid-if}}
|
||||
</section>
|
||||
{{/unless}}
|
||||
{{/unless}}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{{#if this.showDisconnectStripeConnectModal}}
|
||||
@ -456,6 +455,9 @@
|
||||
|
||||
{{#if this.showPortalSettings}}
|
||||
<GhFullscreenModal @modal="portal-settings"
|
||||
@model={{hash
|
||||
openStripeSettings=(action "openStripeSettings")
|
||||
}}
|
||||
@close={{action "closePortalSettings"}}
|
||||
@modifier="full-overlay portal-settings" />
|
||||
{{/if}}
|
||||
@ -464,4 +466,4 @@
|
||||
@confirm={{action "leavePortalSettings"}}
|
||||
@close={{action "closeLeaveSettingsModal"}}
|
||||
@modifier="action wide" />
|
||||
{{/if}}
|
||||
{{/if}}
|
@ -76,6 +76,8 @@ export default Component.extend({
|
||||
stripeConnectAccountName: reads('settings.stripeConnectDisplayName'),
|
||||
stripeConnectLivemode: reads('settings.stripeConnectLivemode'),
|
||||
|
||||
portalSettingsBorderColor: reads('settings.accentColor'),
|
||||
|
||||
selectedReplyAddress: computed('settings.membersReplyAddress', function () {
|
||||
return REPLY_ADDRESSES.findBy('value', this.get('settings.membersReplyAddress'));
|
||||
}),
|
||||
@ -306,6 +308,10 @@ export default Component.extend({
|
||||
this.settings.rollbackAttributes();
|
||||
this.set('showPortalSettings', false);
|
||||
this.set('showLeaveSettingsModal', false);
|
||||
},
|
||||
|
||||
openStripeSettings() {
|
||||
this.set('membersStripeOpen', true);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -90,6 +90,10 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="gh-portal-setting-no-stripe">
|
||||
You need to <button class="gh-btn gh-btn-link blue" {{action "openStripeSettings"}}>connect to Stripe</button> to take payments
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="gh-portal-setting-section divider-top" onclick={{action "switchToSignupPage"}}>
|
||||
|
@ -256,6 +256,11 @@ export default ModalComponent.extend({
|
||||
this.set('showLeaveSettingsModal', false);
|
||||
},
|
||||
|
||||
openStripeSettings() {
|
||||
this.model.openStripeSettings();
|
||||
this.closeModal();
|
||||
},
|
||||
|
||||
leaveSettings() {
|
||||
this.closeModal();
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
isRequestEntityTooLargeError,
|
||||
isUnsupportedMediaTypeError
|
||||
} from 'ghost-admin/services/ajax';
|
||||
import {computed} from '@ember/object';
|
||||
import {isBlank} from '@ember/utils';
|
||||
import {isArray as isEmberArray} from '@ember/array';
|
||||
import {run} from '@ember/runloop';
|
||||
@ -43,9 +42,6 @@ export default Controller.extend({
|
||||
session: service(),
|
||||
settings: service(),
|
||||
|
||||
queryParams: ['fromAddressUpdate', 'supportAddressUpdate'],
|
||||
fromAddressUpdate: null,
|
||||
supportAddressUpdate: null,
|
||||
importErrors: null,
|
||||
importSuccessful: false,
|
||||
showDeleteAllModal: false,
|
||||
@ -72,20 +68,6 @@ export default Controller.extend({
|
||||
this.yamlAccept = [...this.yamlMimeType, ...Array.from(this.yamlExtension, extension => '.' + extension)];
|
||||
},
|
||||
|
||||
fromAddress: computed(function () {
|
||||
return this.parseEmailAddress(this.settings.get('membersFromAddress'));
|
||||
}),
|
||||
|
||||
supportAddress: computed(function () {
|
||||
return this.parseEmailAddress(this.settings.get('membersSupportAddress'));
|
||||
}),
|
||||
|
||||
blogDomain: computed('config.blogDomain', function () {
|
||||
let blogDomain = this.config.blogDomain || '';
|
||||
const domainExp = blogDomain.replace('https://', '').replace('http://', '').match(new RegExp('^([^/:?#]+)(?:[/:?#]|$)', 'i'));
|
||||
return (domainExp && domainExp[1]) || '';
|
||||
}),
|
||||
|
||||
actions: {
|
||||
onUpload(file) {
|
||||
let formData = new FormData();
|
||||
@ -179,18 +161,6 @@ export default Controller.extend({
|
||||
.closest('.gh-setting-action')
|
||||
.find('input[type="file"]')
|
||||
.click();
|
||||
},
|
||||
|
||||
setDefaultContentVisibility(value) {
|
||||
this.set('settings.defaultContentVisibility', value);
|
||||
},
|
||||
|
||||
setStripeConnectIntegrationTokenSetting(stripeConnectIntegrationToken) {
|
||||
this.set('settings.stripeConnectIntegrationToken', stripeConnectIntegrationToken);
|
||||
},
|
||||
|
||||
setEmailAddress(type, emailAddress) {
|
||||
this.set(type, emailAddress);
|
||||
}
|
||||
},
|
||||
|
||||
@ -235,23 +205,6 @@ export default Controller.extend({
|
||||
return RSVP.resolve();
|
||||
},
|
||||
|
||||
parseEmailAddress(address) {
|
||||
const emailAddress = address || 'noreply';
|
||||
// Adds default domain as site domain
|
||||
if (emailAddress.indexOf('@') < 0 && this.blogDomain) {
|
||||
return `${emailAddress}@${this.blogDomain}`;
|
||||
}
|
||||
return emailAddress;
|
||||
},
|
||||
|
||||
saveSettings: task(function* () {
|
||||
const response = yield this.settings.save();
|
||||
// Reset from address value on save
|
||||
this.set('fromAddress', this.parseEmailAddress(this.settings.get('membersFromAddress')));
|
||||
this.set('supportAddress', this.parseEmailAddress(this.settings.get('membersSupportAddress')));
|
||||
return response;
|
||||
}).drop(),
|
||||
|
||||
redirectUploadResult: task(function* (success) {
|
||||
this.set('redirectSuccess', success);
|
||||
this.set('redirectFailure', !success);
|
||||
@ -277,10 +230,5 @@ export default Controller.extend({
|
||||
reset() {
|
||||
this.set('importErrors', null);
|
||||
this.set('importSuccessful', false);
|
||||
this.set('fromAddressUpdate', null);
|
||||
this.set('supportAddressUpdate', null);
|
||||
// stripeConnectIntegrationToken is not a persisted value so we don't want
|
||||
// to keep it around across transitions
|
||||
this.settings.set('stripeConnectIntegrationToken', undefined);
|
||||
}
|
||||
});
|
||||
|
89
ghost/admin/app/controllers/settings/labs/members.js
Normal file
89
ghost/admin/app/controllers/settings/labs/members.js
Normal file
@ -0,0 +1,89 @@
|
||||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import {computed} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
||||
export default Controller.extend({
|
||||
ajax: service(),
|
||||
config: service(),
|
||||
feature: service(),
|
||||
ghostPaths: service(),
|
||||
notifications: service(),
|
||||
session: service(),
|
||||
settings: service(),
|
||||
|
||||
queryParams: ['fromAddressUpdate', 'supportAddressUpdate'],
|
||||
fromAddressUpdate: null,
|
||||
supportAddressUpdate: null,
|
||||
importErrors: null,
|
||||
importSuccessful: false,
|
||||
showDeleteAllModal: false,
|
||||
submitting: false,
|
||||
uploadButtonText: 'Import',
|
||||
|
||||
importMimeType: null,
|
||||
jsonExtension: null,
|
||||
jsonMimeType: null,
|
||||
yamlExtension: null,
|
||||
yamlMimeType: null,
|
||||
|
||||
yamlAccept: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
},
|
||||
|
||||
fromAddress: computed(function () {
|
||||
return this.parseEmailAddress(this.settings.get('membersFromAddress'));
|
||||
}),
|
||||
|
||||
supportAddress: computed(function () {
|
||||
return this.parseEmailAddress(this.settings.get('membersSupportAddress'));
|
||||
}),
|
||||
|
||||
blogDomain: computed('config.blogDomain', function () {
|
||||
let blogDomain = this.config.blogDomain || '';
|
||||
const domainExp = blogDomain.replace('https://', '').replace('http://', '').match(new RegExp('^([^/:?#]+)(?:[/:?#]|$)', 'i'));
|
||||
return (domainExp && domainExp[1]) || '';
|
||||
}),
|
||||
|
||||
actions: {
|
||||
setDefaultContentVisibility(value) {
|
||||
this.set('settings.defaultContentVisibility', value);
|
||||
},
|
||||
|
||||
setStripeConnectIntegrationTokenSetting(stripeConnectIntegrationToken) {
|
||||
this.set('settings.stripeConnectIntegrationToken', stripeConnectIntegrationToken);
|
||||
},
|
||||
|
||||
setEmailAddress(type, emailAddress) {
|
||||
this.set(type, emailAddress);
|
||||
}
|
||||
},
|
||||
|
||||
parseEmailAddress(address) {
|
||||
const emailAddress = address || 'noreply';
|
||||
// Adds default domain as site domain
|
||||
if (emailAddress.indexOf('@') < 0 && this.blogDomain) {
|
||||
return `${emailAddress}@${this.blogDomain}`;
|
||||
}
|
||||
return emailAddress;
|
||||
},
|
||||
|
||||
saveSettings: task(function* () {
|
||||
const response = yield this.settings.save();
|
||||
// Reset from address value on save
|
||||
this.set('fromAddress', this.parseEmailAddress(this.settings.get('membersFromAddress')));
|
||||
this.set('supportAddress', this.parseEmailAddress(this.settings.get('membersSupportAddress')));
|
||||
return response;
|
||||
}).drop(),
|
||||
|
||||
reset() {
|
||||
this.set('fromAddressUpdate', null);
|
||||
this.set('supportAddressUpdate', null);
|
||||
// stripeConnectIntegrationToken is not a persisted value so we don't want
|
||||
// to keep it around across transitions
|
||||
this.settings.set('stripeConnectIntegrationToken', undefined);
|
||||
}
|
||||
});
|
@ -45,6 +45,7 @@ Router.map(function () {
|
||||
|
||||
this.route('settings.general', {path: '/settings/general'});
|
||||
this.route('settings.labs', {path: '/settings/labs'});
|
||||
this.route('settings.labs.members', {path: '/settings/labs/members'});
|
||||
this.route('settings.code-injection', {path: '/settings/code-injection'});
|
||||
this.route('settings.design', {path: '/settings/design'}, function () {
|
||||
this.route('uploadtheme');
|
||||
|
@ -5,14 +5,6 @@ import {inject as service} from '@ember/service';
|
||||
export default AuthenticatedRoute.extend(CurrentUserSettings, {
|
||||
settings: service(),
|
||||
notifications: service(),
|
||||
queryParams: {
|
||||
fromAddressUpdate: {
|
||||
replace: true
|
||||
},
|
||||
supportAddressUpdate: {
|
||||
replace: true
|
||||
}
|
||||
},
|
||||
|
||||
beforeModel() {
|
||||
this._super(...arguments);
|
||||
@ -25,20 +17,6 @@ export default AuthenticatedRoute.extend(CurrentUserSettings, {
|
||||
return this.settings.reload();
|
||||
},
|
||||
|
||||
setupController(controller) {
|
||||
if (controller.fromAddressUpdate === 'success') {
|
||||
this.notifications.showAlert(
|
||||
`Newsletter email address has been updated`.htmlSafe(),
|
||||
{type: 'success', key: 'members.settings.from-address.updated'}
|
||||
);
|
||||
} else if (controller.supportAddressUpdate === 'success') {
|
||||
this.notifications.showAlert(
|
||||
`Support email address has been updated`.htmlSafe(),
|
||||
{type: 'success', key: 'members.settings.support-address.updated'}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
resetController(controller, isExiting) {
|
||||
if (isExiting) {
|
||||
controller.reset();
|
||||
|
53
ghost/admin/app/routes/settings/labs/members.js
Normal file
53
ghost/admin/app/routes/settings/labs/members.js
Normal file
@ -0,0 +1,53 @@
|
||||
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
|
||||
import CurrentUserSettings from 'ghost-admin/mixins/current-user-settings';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default AuthenticatedRoute.extend(CurrentUserSettings, {
|
||||
settings: service(),
|
||||
notifications: service(),
|
||||
queryParams: {
|
||||
fromAddressUpdate: {
|
||||
replace: true
|
||||
},
|
||||
supportAddressUpdate: {
|
||||
replace: true
|
||||
}
|
||||
},
|
||||
|
||||
beforeModel() {
|
||||
this._super(...arguments);
|
||||
return this.get('session.user')
|
||||
.then(this.transitionAuthor())
|
||||
.then(this.transitionEditor());
|
||||
},
|
||||
|
||||
model() {
|
||||
return this.settings.reload();
|
||||
},
|
||||
|
||||
setupController(controller) {
|
||||
if (controller.fromAddressUpdate === 'success') {
|
||||
this.notifications.showAlert(
|
||||
`Newsletter email address has been updated`.htmlSafe(),
|
||||
{type: 'success', key: 'members.settings.from-address.updated'}
|
||||
);
|
||||
} else if (controller.supportAddressUpdate === 'success') {
|
||||
this.notifications.showAlert(
|
||||
`Support email address has been updated`.htmlSafe(),
|
||||
{type: 'success', key: 'members.settings.support-address.updated'}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
resetController(controller, isExiting) {
|
||||
if (isExiting) {
|
||||
controller.reset();
|
||||
}
|
||||
},
|
||||
|
||||
buildRouteInfoMetadata() {
|
||||
return {
|
||||
titleToken: 'Settings - Labs - Members'
|
||||
};
|
||||
}
|
||||
});
|
@ -141,7 +141,12 @@
|
||||
overflow-y: hidden;
|
||||
transition: all 0.2s ease-in-out;
|
||||
opacity: 0;
|
||||
margin-top: 18px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.gh-members-connect-savecontainer.expanded {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.gh-members-connect-savecontainer.expanded {
|
||||
|
@ -61,6 +61,7 @@
|
||||
|
||||
.gh-portal-settings-sidebar {
|
||||
padding: 0px 24px 20px;
|
||||
width: 342px;
|
||||
}
|
||||
|
||||
.gh-portal-settings-form {
|
||||
@ -500,3 +501,14 @@
|
||||
display: none;
|
||||
background: color-mod(var(--darkgrey) a(0.8));
|
||||
}
|
||||
|
||||
.gh-portal-setting-no-stripe {
|
||||
padding: 20px;
|
||||
margin-bottom: 28px;
|
||||
font-size: 1.3rem;
|
||||
text-align: center;
|
||||
background: var(--whitegrey-l2);
|
||||
border: 1px solid var(--whitegrey);
|
||||
border-radius: 4px;
|
||||
color: var(--midgrey);
|
||||
}
|
@ -71,6 +71,8 @@
|
||||
}
|
||||
|
||||
.gh-setting-action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
margin: 1px 0 0 0;
|
||||
}
|
||||
@ -94,6 +96,32 @@
|
||||
border: 1px solid var(--lightgrey);
|
||||
}
|
||||
|
||||
.gh-setting-liquid-section .liquid-container,
|
||||
.gh-setting-liquid-section .liquid-child {
|
||||
padding: 0 20px;
|
||||
margin: 0 -20px;
|
||||
}
|
||||
|
||||
.gh-settings-portal-section {
|
||||
box-shadow:
|
||||
0 0 1px rgba(0,0,0,.07),
|
||||
0 1.5px 1.2px -11px rgba(0, 0, 0, 0.028),
|
||||
0 5.1px 4px -11px rgba(0, 0, 0, 0.042),
|
||||
0 23px 18px -16px rgba(0, 0, 0, 0.07)
|
||||
;
|
||||
}
|
||||
|
||||
.gh-settings-portal-border {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
left: -5px;
|
||||
bottom: -5px;
|
||||
border: 1px solid var(--blue);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
/* Images */
|
||||
|
||||
@ -645,6 +673,10 @@
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.gh-setting-linkrow:hover {
|
||||
background: var(--whitegrey-l2);
|
||||
}
|
||||
|
||||
/* Themes
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
|
@ -385,11 +385,22 @@ svg.gh-btn-icon-right {
|
||||
color: color-mod(var(--yellow) l(-10%));
|
||||
}
|
||||
|
||||
.gh-btn-outline {
|
||||
.gh-btn-outline,
|
||||
.gh-btn-outline:hover {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.gh-btn-outline.blue {
|
||||
border-color: var(--blue);
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
.gh-btn-outline.blue:hover {
|
||||
border-color: color-mod(var(--blue) l(-10%));
|
||||
color: color-mod(var(--blue) l(-10%));
|
||||
}
|
||||
|
||||
.gh-btn-textfield-group span {
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
@ -485,6 +496,10 @@ Usage: CTA buttons grouped together horizontally.
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.gh-btn-link.blue {
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
|
||||
/* Spin Buttons!
|
||||
/* ---------------------------------------------------------- */
|
||||
|
@ -9,43 +9,25 @@
|
||||
<p class="gh-box gh-box-tip">{{svg-jar "idea"}}This is a testing ground for new or experimental features. They may change, break or inexplicably disappear at any time.</p>
|
||||
|
||||
{{#if this.session.user.isOwner}}
|
||||
<div class="gh-setting-header">Members (BETA) </div>
|
||||
<div class="flex flex-column br3 shadow-1 bg-grouped-table mt2">
|
||||
<div class="gh-setting-first gh-setting-last">
|
||||
<div class="gh-members-setting-content">
|
||||
<div class="flex">
|
||||
<div class="flex flex-column flex-grow-1">
|
||||
<div class="gh-setting-title pl5 pt5">Enable members</div>
|
||||
<div class="gh-setting-desc pl5 pb5">Create registered members and take subscription payments — <a href="https://ghost.org/docs/members/" target="_blank" rel="noopener">Find out more</a></div>
|
||||
</div>
|
||||
<div class="gh-setting-action">
|
||||
<div class="for-switch pa5">
|
||||
<GhFeatureFlag @flag="members" @testKey="enable-members"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gh-setting-header"></div>
|
||||
<LinkTo @route="settings.labs.members">
|
||||
<div class="flex flex-column br3 shadow-1 bg-grouped-table mt2 pa5 gh-setting-linkrow">
|
||||
<div class="gh-setting-first gh-setting-last">
|
||||
<div class="gh-setting-content">
|
||||
<div class="gh-setting-title">Members</div>
|
||||
<div class="gh-setting-desc">Create registered members and take subscription payments</div>
|
||||
</div>
|
||||
{{#liquid-if this.feature.labs.members}}
|
||||
<GhMembersLabSetting
|
||||
@settings={{this.settings}}
|
||||
@fromAddress={{this.fromAddress}}
|
||||
@supportAddress={{this.supportAddress}}
|
||||
@setDefaultContentVisibility={{action "setDefaultContentVisibility"}}
|
||||
@setStripeConnectIntegrationTokenSetting={{action "setStripeConnectIntegrationTokenSetting"}}
|
||||
@setEmailAddress={{action "setEmailAddress"}}
|
||||
/>
|
||||
<div class="mt5 pl5 pr5 pb5">
|
||||
<GhTaskButton @buttonText="Save members settings"
|
||||
@task={{this.saveSettings}}
|
||||
@successText="Saved"
|
||||
@runningText="Saving"
|
||||
@class="gh-btn gh-btn-blue gh-btn-icon"
|
||||
data-test-button="save-members-settings"
|
||||
/>
|
||||
<div class="gh-setting-action flex items-center midgrey">
|
||||
{{#if this.feature.labs.members}}
|
||||
<span class="gh-badge">Enabled</span>
|
||||
{{else}}
|
||||
<span>Configure</span>
|
||||
{{/if}}
|
||||
{{svg-jar "arrow-right" class="w6 h6 fill-midgrey pa1 nr2 ml2"}}
|
||||
</div>
|
||||
{{/liquid-if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
<div class="gh-setting-header">Migration options</div>
|
||||
<div class="flex flex-column br3 shadow-1 bg-grouped-table pa5 mt2">
|
||||
|
52
ghost/admin/app/templates/settings/labs/members.hbs
Normal file
52
ghost/admin/app/templates/settings/labs/members.hbs
Normal file
@ -0,0 +1,52 @@
|
||||
<section class="gh-canvas">
|
||||
<GhCanvasHeader class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>
|
||||
<LinkTo @route="settings.labs">Labs</LinkTo>
|
||||
<span>{{svg-jar "arrow-right"}}</span>
|
||||
Members
|
||||
</h2>
|
||||
<section class="view-actions">
|
||||
<GhTaskButton @buttonText="Save settings"
|
||||
@task={{this.saveSettings}}
|
||||
@successText="Saved"
|
||||
@runningText="Saving"
|
||||
@class="gh-btn gh-btn-blue gh-btn-icon"
|
||||
data-test-button="save-members-settings"
|
||||
/>
|
||||
</section>
|
||||
</GhCanvasHeader>
|
||||
|
||||
<section class="view-container settings-debug">
|
||||
|
||||
{{#if this.session.user.isOwner}}
|
||||
<div class="flex flex-column br3 shadow-1 bg-grouped-table mt2 pa5">
|
||||
<div class="gh-setting-first gh-setting-last">
|
||||
<div class="gh-members-setting-content">
|
||||
<div class="gh-setting-title">Enable members</div>
|
||||
<div class="gh-setting-desc">Create registered members and take subscription payments — <a href="https://ghost.org/docs/members/" target="_blank" rel="noopener">Find out more</a></div>
|
||||
</div>
|
||||
<div class="gh-setting-action">
|
||||
<div class="for-switch">
|
||||
<GhFeatureFlag @flag="members" @testKey="enable-members"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gh-setting-liquid-section">
|
||||
{{#liquid-if this.feature.labs.members}}
|
||||
<GhMembersLabSetting
|
||||
@settings={{this.settings}}
|
||||
@fromAddress={{this.fromAddress}}
|
||||
@supportAddress={{this.supportAddress}}
|
||||
@setDefaultContentVisibility={{action "setDefaultContentVisibility"}}
|
||||
@setStripeConnectIntegrationTokenSetting={{action "setStripeConnectIntegrationTokenSetting"}}
|
||||
@setEmailAddress={{action "setEmailAddress"}}
|
||||
/>
|
||||
{{/liquid-if}}
|
||||
</div>
|
||||
|
||||
{{/if}}
|
||||
|
||||
</section>
|
||||
</section>
|
@ -43,7 +43,7 @@ describe('Acceptance: Members', function () {
|
||||
});
|
||||
|
||||
it('shows sidebar link which navigates to members list', async function () {
|
||||
await visit('/settings/labs');
|
||||
await visit('/settings/labs/members');
|
||||
await click('#labs-members');
|
||||
await visit('/');
|
||||
|
||||
|
@ -314,7 +314,7 @@ describe('Acceptance: Settings - Labs', function () {
|
||||
});
|
||||
|
||||
it('sets the mailgunBaseUrl to the default', async function () {
|
||||
await visit('/settings/labs');
|
||||
await visit('/settings/labs/members');
|
||||
|
||||
await click('[data-test-toggle="enable-members"]');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user