Added live preview to members settings modal (#1622)

no issue

- Adds live preview of members.js modal UI to the new settings modal behind dev flag
- Uses `gh-site-iframe` to render site in preview mode with custom portal url
This commit is contained in:
Rishabh Garg 2020-06-26 02:15:47 +05:30 committed by GitHub
parent 56eea59463
commit 23537355b6
8 changed files with 231 additions and 132 deletions

View File

@ -394,5 +394,5 @@
stripeConnectIntegration=this.stripeConnectIntegration stripeConnectIntegration=this.stripeConnectIntegration
}} }}
@close={{action "closeMembersModalSettings"}} @close={{action "closeMembersModalSettings"}}
@modifier="action wide" /> @modifier="full-overlay portal-settings" />
{{/if}} {{/if}}

View File

@ -1,4 +1,4 @@
<iframe id="site-frame" class="site-frame" src="{{this.config.blogUrl}}/" frameborder="0" allowtransparency="true"></iframe> <iframe id="site-frame" class="site-frame" src="{{this.srcUrl}}" frameborder="0" allowtransparency="true"></iframe>
<style> <style>
.site-frame { .site-frame {

View File

@ -1,20 +1,23 @@
import Component from '@ember/component'; import Component from '@ember/component';
import {computed} from '@ember/object';
import {inject as service} from '@ember/service'; import {inject as service} from '@ember/service';
export default Component.extend({ export default Component.extend({
config: service(), config: service(),
tagName: '', tagName: '',
srcUrl: computed('src', function () {
return this.src || `${this.config.get('blogUrl')}/`;
}),
didReceiveAttrs() { didReceiveAttrs() {
// reset the src attribute each time the guid changes - allows for // reset the src attribute each time the guid changes - allows for
// a click on the navigation item to reset back to the homepage // a click on the navigation item to reset back to the homepage
if (this.guid !== this._lastGuid) { if ((this.guid !== this._lastGuid) || (this.src !== this._lastSrc)) {
let iframe = document.querySelector('#site-frame'); let iframe = document.querySelector('#site-frame');
if (iframe) { if (iframe) {
iframe.src = `${this.config.get('blogUrl')}/`; iframe.src = this.src || `${this.config.get('blogUrl')}/`;
} }
} }
this._lastGuid = this.guid; this._lastGuid = this.guid;
this._lastSrc = this.src;
} }
}); });

View File

@ -1,130 +1,151 @@
<header class="modal-header" data-test-modal="custom-view-form"> <div class="modal-body gh-ps-modal-body">
<h1>Members modal settings</h1> <div style="display:flex;padding: 0 20px 0 20px;flex-grow: 1">
</header> <div style="padding: 20px 0 0 0; margin-right: 20px">
{{!-- disable mouseDown so it doesn't trigger focus-out validations --}} <h2 class="f6 fw6">Modal Settings</h2>
<button class="close" href title="Close" {{action "closeModal"}} {{action (optional this.noop) on="mouseDown"}}> <fieldset>
{{svg-jar "close"}} <div class="pt3">
</button> <GhFormGroup @classNames="gh-members-subscribed-checkbox pb4 mb0">
<div class="flex justify-between items-center">
<div class="modal-body"> <div style="margin-right: 12px">
<fieldset> <h4 class="gh-setting-title">Display name in signup form</h4>
<div class="pt3"> </div>
<GhFormGroup @classNames="gh-members-subscribed-checkbox pb4 mb0"> <div class="for-switch">
<div class="flex justify-between items-center"> <label
class="switch"
for="signup-name-checkbox"
>
<input
type="checkbox"
checked={{this.settings.portalName}}
id="signup-name-checkbox"
name="signup-name-checkbox"
onclick={{action "togglePortalName" value="target.checked"}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
</GhFormGroup>
<div> <div>
<h4 class="gh-setting-title">Display name in signup form</h4> <div class="mb3">
</div> <h4 class="gh-setting-title">Plans available at signup</h4>
<div class="for-switch"> </div>
<label class="switch" for="signup-name-checkbox"> <div class="form-group mb0 for-checkbox">
<input <label
type="checkbox" class="checkbox"
checked={{this.settings.portalName}} for="free-plan"
id="signup-name-checkbox" >
name="signup-name-checkbox" onclick={{action "togglePortalName" value="target.checked"}}> <input
<span class="input-toggle-component"></span> type="checkbox"
</label> checked={{this.isFreeChecked}}
id="free-plan"
name="free-plan"
disabled={{not this.subscriptionSettings.allowSelfSignup}}
class="gh-input post-settings-featured"
onclick={{action "toggleFreePlan" value="target.checked"}}
data-test-checkbox="featured"
>
<span class="input-toggle-component"></span>
<p>Free</p>
</label>
</div>
<div class="form-group mb0 for-checkbox">
<label
class="checkbox"
for="monthly-plan"
>
<input
type="checkbox"
id="monthly-plan"
name="monthly-plan"
checked={{this.isMonthlyChecked}}
disabled={{not this.isStripeConfigured}}
class="gh-input post-settings-featured"
onclick={{action "toggleMonthlyPlan" value="target.checked"}}
data-test-checkbox="featured"
>
<span class="input-toggle-component"></span>
<p>Monthly</p>
</label>
</div>
<div class="form-group mb0 for-checkbox">
<label
class="checkbox"
for="yearly-plan"
>
<input
type="checkbox"
id="yearly-plan"
name="yearly-plan"
checked={{this.isYearlyChecked}}
disabled={{not this.isStripeConfigured}}
class="gh-input post-settings-featured"
onclick={{action "toggleYearlyPlan" value="target.checked"}}
data-test-checkbox="featured"
>
<span class="input-toggle-component"></span>
<p>Yearly</p>
</label>
</div>
</div> </div>
<GhFormGroup @classNames="gh-members-subscribed-checkbox mb0 bt pt3 b--whitegrey">
<div class="flex justify-between items-center">
<div>
<h4 class="gh-setting-title">Show beacon</h4>
</div>
<div class="for-switch">
<label
class="switch"
for="portal-button-checkbox"
>
<input
type="checkbox"
checked={{this.settings.portalButton}}
id="portal-button-checkbox"
name="portal-button-checkbox"
onclick={{action "togglePortalButton" value="target.checked"}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
</GhFormGroup>
</div> </div>
</GhFormGroup> </fieldset>
<div>
<div class="mb3">
<h4 class="gh-setting-title">Plans available at signup</h4>
</div>
<div class="form-group mb0 for-checkbox">
<label
class="checkbox"
for="free-plan"
>
<input
type="checkbox"
checked={{this.isFreeChecked}}
id="free-plan"
name="free-plan"
disabled={{not this.subscriptionSettings.allowSelfSignup}}
class="gh-input post-settings-featured"
onclick={{action "toggleFreePlan" value="target.checked"}}
data-test-checkbox="featured"
>
<span class="input-toggle-component"></span>
<p>Free</p>
</label>
</div>
<div class="form-group mb0 for-checkbox">
<label
class="checkbox"
for="monthly-plan"
>
<input
type="checkbox"
id="monthly-plan"
name="monthly-plan"
checked={{this.isMonthlyChecked}}
disabled={{not this.isStripeConfigured}}
class="gh-input post-settings-featured"
onclick={{action "toggleMonthlyPlan" value="target.checked"}}
data-test-checkbox="featured"
>
<span class="input-toggle-component"></span>
<p>Monthly</p>
</label>
</div>
<div class="form-group mb0 for-checkbox">
<label
class="checkbox"
for="yearly-plan"
>
<input
type="checkbox"
id="yearly-plan"
name="yearly-plan"
checked={{this.isYearlyChecked}}
disabled={{not this.isStripeConfigured}}
class="gh-input post-settings-featured"
onclick={{action "toggleYearlyPlan" value="target.checked"}}
data-test-checkbox="featured"
>
<span class="input-toggle-component"></span>
<p>Yearly</p>
</label>
</div>
</div>
<GhFormGroup @classNames="gh-members-subscribed-checkbox mb0 bt pt3 b--whitegrey">
<div class="flex justify-between items-center">
<div>
<h4 class="gh-setting-title">Show beacon</h4>
</div>
<div class="for-switch">
<label class="switch" for="portal-button-checkbox">
<input
type="checkbox"
checked={{this.settings.portalButton}}
id="portal-button-checkbox"
name="portal-button-checkbox" onclick={{action "togglePortalButton" value="target.checked"}}>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
</GhFormGroup>
</div> </div>
</fieldset> <div style="border-left: 1px solid black;margin: 0 3px 0 3px">
</div> </div>
<div style="display: flex; flex-direction: column; flex-grow: 1; padding: 20px 0 20px 0;">
<div style="padding-bottom: 12px;display: flex;justify-content: center;">
<span style="padding: 0 20px 0 20px; font-weight: bold"><a href="#" {{action "switchPreviewPage" "signup"}} data-test-link="switch-portal-preview-page">Signup</a></span>
<span style="padding: 0 20px 0 20px; font-weight: bold"><a href="#" {{action "switchPreviewPage" "accountHome"}} data-test-link="switch-portal-review-page">Account</a></span>
</div>
<div style="position: relative;flex-grow: 1">
<GhSiteIframe
@guid="test-site-portal"
@src={{this.portalPreviewUrl}}
></GhSiteIframe>
</div>
<div class="modal-footer">
<button
class="gh-btn"
{{action "closeModal"}}
{{!-- disable mouseDown so it doesn't trigger focus-out validations --}}
{{on "mousedown" (optional this.noop)}}
data-test-button="cancel-custom-view-form"
>
<span>Cancel</span>
</button>
<div class="modal-footer"> <GhTaskButton
<button @buttonText="Save and close"
class="gh-btn" @successText="Saved"
{{action "closeModal"}} @task={{this.saveTask}}
{{!-- disable mouseDown so it doesn't trigger focus-out validations --}} @idleClass="gh-btn-green"
{{on "mousedown" (optional this.noop)}} @class="gh-btn gh-btn-icon"
data-test-button="cancel-custom-view-form" data-test-button="save-members-modal-setting"
> />
<span>Cancel</span> </div>
</button> </div>
</div>
<GhTaskButton
@buttonText="Save and close"
@successText="Saved"
@task={{this.saveTask}}
@idleClass="gh-btn-green"
@class="gh-btn gh-btn-icon"
data-test-button="save-members-modal-setting" />
</div> </div>

View File

@ -6,11 +6,26 @@ import {task} from 'ember-concurrency';
export default ModalComponent.extend({ export default ModalComponent.extend({
settings: service(), settings: service(),
confirm() {}, config: service(),
page: 'signup',
confirm() {},
subscriptionSettings: alias('model.subscriptionSettings'), subscriptionSettings: alias('model.subscriptionSettings'),
stripeConnectIntegration: alias('model.stripeConnectIntegration'), stripeConnectIntegration: alias('model.stripeConnectIntegration'),
portalPreviewUrl: computed('page', 'isFreeChecked', 'isMonthlyChecked', 'isYearlyChecked', 'settings.{portalName,portalButton}', function () {
const baseUrl = this.config.get('blogUrl');
const portalBase = '/#/portal';
const settingsParam = new URLSearchParams();
settingsParam.append('button', this.settings.get('portalButton'));
settingsParam.append('name', this.settings.get('portalName'));
settingsParam.append('isFree', this.isFreeChecked);
settingsParam.append('isMonthly', this.isMonthlyChecked);
settingsParam.append('isYearly', this.isYearlyChecked);
settingsParam.append('page', this.page);
return `${baseUrl}${portalBase}?${settingsParam.toString()}`;
}),
isFreeChecked: computed('settings.{portalPlans.[],membersSubscriptionSettings}', function () { isFreeChecked: computed('settings.{portalPlans.[],membersSubscriptionSettings}', function () {
const allowSelfSignup = this.subscriptionSettings.allowSelfSignup; const allowSelfSignup = this.subscriptionSettings.allowSelfSignup;
const allowedPlans = this.settings.get('portalPlans') || []; const allowedPlans = this.settings.get('portalPlans') || [];
@ -62,6 +77,10 @@ export default ModalComponent.extend({
isPlanSelected(plan) { isPlanSelected(plan) {
const allowedPlans = this.settings.get('portalPlans'); const allowedPlans = this.settings.get('portalPlans');
return allowedPlans.includes(plan); return allowedPlans.includes(plan);
},
switchPreviewPage(page) {
this.set('page', page);
} }
}, },

View File

@ -60,6 +60,7 @@
@import "layouts/labs.css"; @import "layouts/labs.css";
@import "layouts/whats-new.css"; @import "layouts/whats-new.css";
@import "layouts/preview-email.css"; @import "layouts/preview-email.css";
@import "layouts/portal-settings.css";
@import "layouts/billing.css"; @import "layouts/billing.css";

View File

@ -60,6 +60,7 @@
@import "layouts/labs.css"; @import "layouts/labs.css";
@import "layouts/whats-new.css"; @import "layouts/whats-new.css";
@import "layouts/preview-email.css"; @import "layouts/preview-email.css";
@import "layouts/portal-settings.css";
@import "layouts/billing.css"; @import "layouts/billing.css";

View File

@ -0,0 +1,54 @@
.fullscreen-modal-portal-settings {
margin: 30px;
max-width: 100%;
}
.fullscreen-modal-portal-settings .modal-content {
position: relative;
overflow: scroll;
height: 100%;
padding: 0;
}
.fullscreen-modal-portal-settings .modal-body {
margin: 0;
}
.gh-ps-header {
position: sticky;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
padding: 18px 32px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
overflow: hidden;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
background: var(--white);
z-index: 9999;
}
.gh-ps-header h2 {
width: calc(50vw - 200px);
margin: 0;
}
.gh-ps-header-border {
border-bottom: 1px solid var(--whitegrey);
}
.gh-ps-close {
width: calc(50vw - 200px);
}
.gh-ps-modal-body {
height: 100%;
display: flex;
flex-direction: column;
}