From 4310a1815008cbb316d8cbcc036973019459c121 Mon Sep 17 00:00:00 2001 From: Rish Date: Wed, 8 Apr 2020 22:36:28 +0530 Subject: [PATCH] Added basic signup/signin UI flow refs https://github.com/TryGhost/membersjs/issues/3 Adds signup/signin flow to theme when no member is logged in, uses api utils to send magic-link to member's email which can be used to signup/signin --- .../portal/src/components/ParentContainer.js | 37 +-- .../src/components/PopupMenuComponent.js | 218 +++++++++++++++--- 2 files changed, 208 insertions(+), 47 deletions(-) diff --git a/ghost/portal/src/components/ParentContainer.js b/ghost/portal/src/components/ParentContainer.js index 7d42a0a38d..d101435298 100644 --- a/ghost/portal/src/components/ParentContainer.js +++ b/ghost/portal/src/components/ParentContainer.js @@ -1,8 +1,8 @@ import TriggerComponent from './TriggerComponent'; import PopupMenuComponent from './PopupMenuComponent'; +const setupMembersApi = require('../utils/api'); const React = require("react"); const PropTypes = require("prop-types"); - export default class ParentContainer extends React.Component { static propTypes = { name: PropTypes.string, @@ -13,33 +13,35 @@ export default class ParentContainer extends React.Component { this.state = { showPopup: false }; + console.log("Initialized script with data", props.data); + const {blogUrl, adminUrl} = props.data.site; + this.MembersAPI = setupMembersApi({blogUrl, adminUrl}); } - componentDidMount() { - console.log("Loaded Members Data", this.props.data); + onSignout() { + this.MembersAPI.signout(); + } + + onSignin(data) { + this.MembersAPI.sendMagicLink(data); } onTriggerToggle() { let showPopup = !this.state.showPopup; this.setState({ showPopup - }, () => { - setTimeout(() => { - if (showPopup) { - // Trigger member signout method - const querySelector = document.querySelectorAll('iframe')[0] && document.querySelectorAll('iframe')[0].contentWindow.document.body.querySelectorAll('[data-members-signout]') - if (querySelector) { - window.handleMembersSignout && window.handleMembersSignout(querySelector); - } - } - }, 500 ) }); } renderPopupMenu() { if (this.state.showPopup) { return ( - + this.onSignout()} + onSignin={(data) => this.onSignin(data)} + /> ); } return null; @@ -47,7 +49,12 @@ export default class ParentContainer extends React.Component { renderTriggerComponent() { return ( - this.onTriggerToggle()} isPopupOpen={this.state.showPopup} data={this.props.data} /> + this.onTriggerToggle()} + isPopupOpen={this.state.showPopup} + data={this.props.data} + /> ) } diff --git a/ghost/portal/src/components/PopupMenuComponent.js b/ghost/portal/src/components/PopupMenuComponent.js index 25673b4b7a..ad4f5253a4 100644 --- a/ghost/portal/src/components/PopupMenuComponent.js +++ b/ghost/portal/src/components/PopupMenuComponent.js @@ -7,23 +7,156 @@ export default class PopupMenuComponent extends React.Component { name: PropTypes.string, }; - render() { - const hoverStyle = { - zIndex: '2147483000', - position: 'fixed', - bottom: '100px', - right: '20px', - width: '250px', - minHeight: '50px', - maxHeight: '116px', - boxShadow: 'rgba(0, 0, 0, 0.16) 0px 5px 40px', - opacity: '1', - height: 'calc(100% - 120px)', - borderRadius: '8px', - overflow: 'hidden', - backgroundColor: 'white' + constructor(props) { + super(props); + this.state = { + inputVal: '', + isLoading: false, + showSuccess: false + } + } + + handleSignout(e) { + e.preventDefault(); + this.props.onSignout(); + } + + handleSignin(e) { + e.preventDefault(); + const email = this.state.inputVal; + this.props.onSignin({email}); + this.setState({ + isLoading: true, + showSuccess: false + }); + setTimeout(() => { + this.setState({ + isLoading: false, + showSuccess: true + }) + }, 3000) + } + + handleInput(e) { + this.setState({ + inputVal: e.target.value, + showSuccess: false, + isLoading: false + }) + } + + isMemberLoggedIn() { + return !!this.props.data.member; + } + + getMemberEmail() { + if (this.isMemberLoggedIn()) { + return this.props.data.member.email; + } + + return ''; + } + + renderSignedOutContent() { + const inputStyle = { + display: 'block', + padding: '0 .6em', + width: '100%', + height: '44px', + outline: '0', + border: '1px solid #c5d2d9', + color: 'inherit', + textDecoration: 'none', + background: '#fff', + borderRadius: '5px', + fontSize: '14px', + marginBottom: '12px' }; - + + const blogTitle = (this.props.data.site && this.props.data.site.title) || 'Site Title'; + const blogDescription = (this.props.data.site && this.props.data.site.description) || 'Site Description'; + return ( +
+
+
+
Signup to {blogTitle}
+
{blogDescription}
+
+
+ { this.handleInput(e) }} + style={inputStyle} + /> + {this.renderSubmitButton()} + {this.renderSuccessMessage()} +
+ +
+
+ ); + } + + renderSuccessMessage() { + if (!this.state.isLoading && this.state.showSuccess) { + return ( +
Please check your email for magic link!
+ ) + } + return null; + } + + renderSubmitButton() { + const buttonStyle = { + display: 'inline-block', + padding: '0 1.8rem', + height: '44px', + border: '0', + fontSize: '1.5rem', + lineHeight: '42px', + fontWeight: '600', + textAlign: 'center', + textDecoration: 'none', + whiteSpace: 'nowrap', + borderRadius: '5px', + cursor: 'pointer', + transition: '.4s ease', + color: '#fff', + backgroundColor: '#3eb0ef', + boxShadow: 'none', + userSelect: 'none' + } + const label = this.state.isLoading ? 'Sending' : 'Continue'; + const disabled = this.state.isLoading ? true : false; + return ( + + ) + } + + renderSignedinContent() { + const memberEmail = (this.props.data.member && this.props.data.member.email) || "test@test.com"; + + return ( +
+
+ Signed in as +
+
+ {memberEmail} +
+
+
{ this.handleSignout(e) }}> Logout
+
+
+ ); + } + + renderPopupContent() { + const launcherStyle = { width: '100%', height: '100%', @@ -47,24 +180,45 @@ export default class PopupMenuComponent extends React.Component { paddingBottom: '18px', textAlign: 'left' }; - const memberEmail = (this.props.data && this.props.data.email) || "test@test.com"; + + return ( +
+
+ {this.isMemberLoggedIn() ? this.renderSignedinContent() : this.renderSignedOutContent()} +
+
+ ); + } + + render() { + let hoverStyle = { + zIndex: '2147483000', + position: 'fixed', + bottom: '100px', + right: '20px', + width: '250px', + minHeight: '50px', + maxHeight: '116px', + boxShadow: 'rgba(0, 0, 0, 0.16) 0px 5px 40px', + opacity: '1', + height: 'calc(100% - 120px)', + borderRadius: '8px', + overflow: 'hidden', + backgroundColor: 'white' + }; + + if (!this.isMemberLoggedIn()) { + hoverStyle = { + ...hoverStyle, + width: '450px', + minHeight: '200px', + maxHeight: '220px', + } + } + return ( -
-
-
-
- Signed in as -
-
- {memberEmail} -
-
-
Logout
-
-
-
-
+ {this.renderPopupContent()}
); }