diff --git a/client/coral-admin/src/components/SignIn.css b/client/coral-admin/src/components/SignIn.css index 88d8a452c..10ab54c09 100644 --- a/client/coral-admin/src/components/SignIn.css +++ b/client/coral-admin/src/components/SignIn.css @@ -12,3 +12,12 @@ font-weight: normal; text-decoration: none; } + +.recaptcha { + margin-top: 16px; + margin-bottom: 6px; +} + +.signInButton { + margin-top: 10px; +} diff --git a/client/coral-admin/src/components/SignIn.js b/client/coral-admin/src/components/SignIn.js index 85bfb9810..1525145a7 100644 --- a/client/coral-admin/src/components/SignIn.js +++ b/client/coral-admin/src/components/SignIn.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styles from './SignIn.css'; import { Button, TextField, Alert } from 'coral-ui'; +import cn from 'classnames'; import Recaptcha from 'coral-framework/components/Recaptcha'; class SignIn extends React.Component { @@ -27,9 +28,6 @@ class SignIn extends React.Component { handleRecaptchaRef = ref => { this.recaptcha = ref; - setTimeout(() => { - console.log(ref); - }, 1000) }; render() { @@ -50,9 +48,16 @@ class SignIn extends React.Component { onChange={this.handlePasswordChange} type="password" /> -
+ {requireRecaptcha && ( +
+ +
+ )} - {}} - parentCommentId={'commentID'} - currentUserId={{}} - /> -
-
- - -
- - -); diff --git a/plugins/talk-plugin-auth/client/components/ForgotContent.js b/plugins/talk-plugin-auth/client/components/ForgotContent.js deleted file mode 100644 index bfadbb001..000000000 --- a/plugins/talk-plugin-auth/client/components/ForgotContent.js +++ /dev/null @@ -1,81 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import styles from './styles.css'; -import { Button, TextField } from 'plugin-api/beta/client/components/ui'; -import t from 'coral-framework/services/i18n'; - -class ForgotContent extends React.Component { - state = { value: '' }; - - handleSubmit = e => { - e.preventDefault(); - this.props.fetchForgotPassword(this.state.value); - }; - - handleChangeEmail = e => { - const { value } = e.target; - this.setState({ value }); - }; - - render() { - const { changeView, auth } = this.props; - const { passwordRequestSuccess, passwordRequestFailure } = auth; - - return ( -
-
-

{t('sign_in.recover_password')}

-
-
-
- -
- - {passwordRequestSuccess ? ( -

- {passwordRequestSuccess} -

- ) : null} - {passwordRequestFailure ? ( -

- {passwordRequestFailure} -

- ) : null} -
-
- - {t('sign_in.need_an_account')}{' '} - changeView('SIGNUP')}>{t('sign_in.register')} - - - {t('sign_in.already_have_an_account')}{' '} - changeView('SIGNIN')}>{t('sign_in.sign_in')} - -
-
- ); - } -} - -ForgotContent.propTypes = { - auth: PropTypes.object, - changeView: PropTypes.func, - fetchForgotPassword: PropTypes.func, -}; - -export default ForgotContent; diff --git a/plugins/talk-plugin-auth/client/components/ResendVerification.css b/plugins/talk-plugin-auth/client/components/ResendVerification.css deleted file mode 100644 index dc59a9ff1..000000000 --- a/plugins/talk-plugin-auth/client/components/ResendVerification.css +++ /dev/null @@ -1,15 +0,0 @@ -.header { - margin-bottom: 20px; - text-align: center; - font-size: 1.2em; -} - -.notVerified { - padding: 10px; - margin-bottom: 20px; - border-radius: 2px; - border: solid 1px #dddd00; - background: #FFFF9C; - color: #777700; -} - diff --git a/plugins/talk-plugin-auth/client/components/ResendVerification.js b/plugins/talk-plugin-auth/client/components/ResendVerification.js deleted file mode 100644 index d2d71dd45..000000000 --- a/plugins/talk-plugin-auth/client/components/ResendVerification.js +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import { - Button, - Spinner, - Success, - Alert, -} from 'plugin-api/beta/client/components/ui'; -import PropTypes from 'prop-types'; -import styles from './ResendVerification.css'; -import t from 'coral-framework/services/i18n'; - -class ResendVerification extends React.Component { - render() { - const { resendVerification, error, loading, success, email } = this.props; - return ( -
-

{t('sign_in.email_verify_cta')}

- - {error && ( - - {error.translation_key - ? t(`error.${error.translation_key}`) - : error.toString()} - - )} -
- {t('error.email_not_verified', email)} -
-
- - {loading && } - {success && } -
-
- ); - } -} - -ResendVerification.propTypes = { - resendVerification: PropTypes.bool.isRequired, - error: PropTypes.object, - loading: PropTypes.bool, - success: PropTypes.bool, - email: PropTypes.string.isRequired, -}; - -export default ResendVerification; diff --git a/plugins/talk-plugin-auth/client/components/SignDialog.js b/plugins/talk-plugin-auth/client/components/SignDialog.js deleted file mode 100644 index a33baeb99..000000000 --- a/plugins/talk-plugin-auth/client/components/SignDialog.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { Dialog } from 'plugin-api/beta/client/components/ui'; -import styles from './styles.css'; - -import SignInContent from './SignInContent'; -import SignUpContent from './SignUpContent'; -import ForgotContent from './ForgotContent'; -import ResendVerification from './ResendVerification'; - -const SignDialog = ({ open, view, resetSignInDialog, ...props }) => ( - - {view !== 'SIGNIN' && ( - - × - - )} - {view === 'SIGNIN' && } - {view === 'SIGNUP' && } - {view === 'FORGOT' && } - {view === 'RESEND_VERIFICATION' && ( - - )} - -); - -export default SignDialog; diff --git a/plugins/talk-plugin-auth/client/components/SignInContainer.js b/plugins/talk-plugin-auth/client/components/SignInContainer.js deleted file mode 100644 index a184f3256..000000000 --- a/plugins/talk-plugin-auth/client/components/SignInContainer.js +++ /dev/null @@ -1,202 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import SignDialog from './SignDialog'; -import { bindActionCreators } from 'redux'; -import t from 'coral-framework/services/i18n'; -import errorMsj from 'coral-framework/helpers/error'; -import validate from 'coral-framework/helpers/validate'; - -import { - changeView, - fetchSignUp, - fetchSignIn, - hideSignInDialog, - fetchSignInFacebook, - fetchSignUpFacebook, - fetchForgotPassword, - requestConfirmEmail, - resetSignInDialog, - facebookCallback, - invalidForm, - validForm, -} from 'coral-embed-stream/src/actions/login'; - -class SignInContainer extends React.Component { - constructor(props) { - super(props); - - this.state = { - formData: { - email: '', - username: '', - password: '', - confirmPassword: '', - }, - errors: {}, - showErrors: false, - }; - } - - componentDidMount() { - this.listenToStorageChanges(); - const { formData } = this.state; - const errors = Object.keys(formData).reduce((map, prop) => { - map[prop] = t('sign_in.required_field'); - return map; - }, {}); - this.setState({ errors }); - } - - componentWillUnmount() { - this.unlisten(); - } - - listenToStorageChanges() { - window.addEventListener('storage', this.handleAuth); - } - - unlisten() { - window.removeEventListener('storage', this.handleAuth); - } - - handleAuth = e => { - // Listening to FB changes - // FB localStorage key is 'auth' - const authCallback = this.props.facebookCallback; - - if (e.key === 'auth') { - const { err, data } = JSON.parse(e.newValue); - authCallback(err, data); - this.unlisten(); - localStorage.removeItem('auth'); - } - }; - - handleChange = e => { - const { name, value } = e.target; - this.setState( - state => ({ - ...state, - formData: { - ...state.formData, - [name]: value, - }, - }), - () => { - this.validation(name, value); - } - ); - }; - - resendVerification = () => { - this.props.requestConfirmEmail(this.props.auth.email).then(() => { - setTimeout(() => { - // allow success UI to be shown for a second, and then close the modal - this.props.resetSignInDialog(); - }, 2500); - }); - }; - - addError = (name, error) => { - return this.setState(state => ({ - errors: { - ...state.errors, - [name]: error, - }, - })); - }; - - validation = (name, value) => { - const { addError } = this; - const { formData } = this.state; - - if (!value.length) { - addError(name, t('sign_in.required_field')); - } else if ( - name === 'confirmPassword' && - formData.confirmPassword !== formData.password - ) { - addError('confirmPassword', t('sign_in.passwords_dont_match')); - } else if (!validate[name](value)) { - addError(name, errorMsj[name]); - } else { - const {[name]: prop, ...errors} = this.state.errors; // eslint-disable-line - // Removes Error - this.setState(state => ({ ...state, errors })); - } - }; - - isCompleted = () => { - const { formData } = this.state; - return !Object.keys(formData).filter(prop => !formData[prop].length).length; - }; - - displayErrors = (show = true) => { - this.setState({ showErrors: show }); - }; - - handleSignUp = e => { - e.preventDefault(); - const { errors } = this.state; - const { fetchSignUp, validForm, invalidForm } = this.props; - this.displayErrors(); - if (this.isCompleted() && !Object.keys(errors).length) { - fetchSignUp(this.state.formData); - validForm(); - } else { - invalidForm(t('sign_in.check_the_form')); - } - }; - - handleSignIn = e => { - e.preventDefault(); - this.props.fetchSignIn(this.state.formData); - }; - - render() { - const { auth } = this.props; - const { - requireEmailConfirmation, - emailVerificationLoading, - emailVerificationSuccess, - } = auth; - - return ( - - ); - } -} - -const mapStateToProps = state => ({ - auth: state.auth, -}); - -const mapDispatchToProps = dispatch => - bindActionCreators( - { - facebookCallback, - fetchSignUp, - fetchSignIn, - fetchSignInFacebook, - fetchSignUpFacebook, - fetchForgotPassword, - requestConfirmEmail, - changeView, - hideSignInDialog, - resetSignInDialog, - invalidForm, - validForm, - }, - dispatch - ); - -export default connect(mapStateToProps, mapDispatchToProps)(SignInContainer); diff --git a/plugins/talk-plugin-auth/client/components/SignInContent.js b/plugins/talk-plugin-auth/client/components/SignInContent.js deleted file mode 100644 index e74de4ff2..000000000 --- a/plugins/talk-plugin-auth/client/components/SignInContent.js +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { - Button, - TextField, - Spinner, - Alert, -} from 'plugin-api/beta/client/components/ui'; -import styles from './styles.css'; -import t from 'coral-framework/services/i18n'; - -const SignInContent = ({ - handleChange, - formData, - changeView, - handleSignIn, - auth, - fetchSignInFacebook, -}) => { - return ( -
-
-

{t('sign_in.sign_in_to_join')}

-
- {auth.error && ( - - {auth.error.translation_key - ? t(`error.${auth.error.translation_key}`) - : auth.error.toString()} - - )} -
-
- -
-
-

{t('sign_in.or')}

-
-
- - -
- {!auth.isLoading ? ( - - ) : ( - - )} -
- -
-
- - changeView('FORGOT')}> - {t('sign_in.forgot_your_pass')} - - - - {t('sign_in.need_an_account')} - changeView('SIGNUP')} id="coralRegister"> - {t('sign_in.register')} - - -
-
- ); -}; - -SignInContent.propTypes = { - auth: PropTypes.shape({ - isLoading: PropTypes.bool.isRequired, - error: PropTypes.string, - emailVerificationFailure: PropTypes.bool, - }).isRequired, - fetchSignInFacebook: PropTypes.func.isRequired, - handleSignIn: PropTypes.func.isRequired, - handleChange: PropTypes.func.isRequired, - changeView: PropTypes.func.isRequired, - emailVerificationLoading: PropTypes.bool.isRequired, - emailVerificationSuccess: PropTypes.bool.isRequired, - resendVerification: PropTypes.func.isRequired, - formData: PropTypes.object, -}; - -export default SignInContent; diff --git a/plugins/talk-plugin-auth/client/components/SignUpContent.js b/plugins/talk-plugin-auth/client/components/SignUpContent.js deleted file mode 100644 index 845fe502c..000000000 --- a/plugins/talk-plugin-auth/client/components/SignUpContent.js +++ /dev/null @@ -1,143 +0,0 @@ -import styles from './styles.css'; -import React from 'react'; -import { - Button, - TextField, - Spinner, - Success, - Alert, -} from 'plugin-api/beta/client/components/ui'; -import t from 'coral-framework/services/i18n'; - -class SignUpContent extends React.Component { - componentWillReceiveProps(next) { - if ( - !this.props.emailVerificationEnabled && - !this.props.auth.successSignUp && - next.auth.successSignUp - ) { - setTimeout(() => { - this.props.changeView('SIGNIN'); - }, 2000); - } - } - - render() { - const { - handleChange, - formData, - emailVerificationEnabled, - auth, - errors, - showErrors, - changeView, - handleSignUp, - fetchSignUpFacebook, - } = this.props; - - return ( -
-
-

{t('sign_in.sign_up')}

-
- - {auth.error && {auth.error}} - {!auth.successSignUp && ( -
-
- -
-
-

{t('sign_in.or')}

-
-
- - - - {errors.password && ( - - {' '} - Password must be at least 8 characters.{' '} - - )} - -
- - {auth.isLoading && } -
- -
- )} - {auth.successSignUp && ( -
- - {emailVerificationEnabled && ( -

- {t('sign_in.verify_email')} -
-
- {t('sign_in.verify_email2')} -

- )} -
- )} -
- {t('sign_in.already_have_an_account')}{' '} - changeView('SIGNIN')}> - {t('sign_in.sign_in')} - -
-
- ); - } -} - -export default SignUpContent; diff --git a/plugins/talk-plugin-auth/client/components/UserBox.js b/plugins/talk-plugin-auth/client/components/UserBox.js deleted file mode 100644 index 09e4302b6..000000000 --- a/plugins/talk-plugin-auth/client/components/UserBox.js +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import styles from './styles.css'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import t from 'coral-framework/services/i18n'; -import { logout } from 'coral-framework/actions/auth'; - -const UserBox = ({ user, logout, onShowProfile }) => ( -
- {user ? ( -
- - {t('sign_in.logged_in_as')} - - {user.username}. {t('sign_in.not_you')} - logout()} - > - {t('sign_in.logout')} - -
- ) : null} -
-); - -const mapStateToProps = ({ auth }) => ({ - user: auth.user, -}); - -const mapDispatchToProps = dispatch => bindActionCreators({ logout }, dispatch); - -export default connect(mapStateToProps, mapDispatchToProps)(UserBox); diff --git a/plugins/talk-plugin-auth/client/components/styles.css b/plugins/talk-plugin-auth/client/components/styles.css deleted file mode 100644 index 735f34d31..000000000 --- a/plugins/talk-plugin-auth/client/components/styles.css +++ /dev/null @@ -1,167 +0,0 @@ -.dialog { - border: none; - box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2); - width: 280px; - top: 10px; -} - -.header { - margin-bottom: 20px; -} - -.header h1, .separator h1{ - text-align: center; - font-size: 1.2em; -} - -.footer { - margin: 20px auto 10px; - text-align: center; -} - -.footer span { - display: block; - margin-bottom: 5px; -} - -.footer a { - color: #2c69b6; - cursor: pointer; - margin: 0 5px; -} - -.socialConnections { - margin-bottom: 20px; -} - -.signInButton { - margin-top: 10px; - background-color: #2a2a2a; -} - -.close { - font-size: 20px; - line-height: 14px; - top: 10px; - right: 10px; - position: absolute; - display: block; - font-weight: bold; - color: #363636; - cursor: pointer; -} - -.close:hover { - color: #6b6b6b; -} - -input.error{ - border: solid 2px #f44336; -} - -.errorMsg, .hint { - color: grey; - font-weight: 600; - padding: 3px 0 16px; -} - -.userBox { - margin: 10px 0 20px; - letter-spacing: 0.1px; -} - -.userBoxLoggedIn { - font-weight: bold; -} - -.userBox a { - color: black; - font-weight: bold; - cursor: pointer; - margin: 0px; - margin-left: 4px; - padding-bottom: 2px; -} - -.userBox .logout { - border-bottom: solid 1px black; -} - -.attention { - display: inline-block; - width: 15px; - height: 15px; - background: #B71C1C; - color: #FFEBEE; - font-weight: bolder; - padding: 4px; - vertical-align: middle; - border-radius: 20px; - box-sizing: border-box; - font-size: 9px; - line-height: 7px; - text-align: center; - margin-right: 5px; -} - -.action { - margin-top: 0px; -} - -.passwordRequestSuccess { - border: 1px solid green; - background-color: lightgreen; - padding: 10px; -} - -.passwordRequestFailure { - border: 1px solid orange; - background-color: 1px solid coral; - padding: 10px; -} - -.emailConfirmDialog { - margin-top: 15px; -} - -.confirmLabel { - display: block; -} - -/* Change username Dialog*/ - -.dialogusername { - border: none; - box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2); - width: 400px; - top: 10px; -} - -.yourusername { - display: block; -} - -.example { - display: block; -} - -.ifyoudont { - display: block; - margin-top: 15px; -} - -.saveusername { - display: block; - width: 100%; -} - -.savebutton { - display: inline; - background-color: rgb(105,105,105); - color: white; -} - -.fakeComment { - display: block; - margin-bottom: 5px; -} diff --git a/plugins/talk-plugin-auth/client/index.js b/plugins/talk-plugin-auth/client/index.js index 12aa8ccd5..0c70cb112 100644 --- a/plugins/talk-plugin-auth/client/index.js +++ b/plugins/talk-plugin-auth/client/index.js @@ -1,13 +1,12 @@ -import UserBox from './components/UserBox'; -import SignInButton from './components/SignInButton'; -import SignInContainer from './components/SignInContainer'; -import ChangeUserNameContainer from './components/ChangeUsername'; +import UserBox from './stream/containers/UserBox'; +import SignInButton from './stream/containers/SignInButton'; import translations from './translations.yml'; +import Login from './login/containers/Main'; export default { translations, slots: { - stream: [UserBox, SignInButton, ChangeUserNameContainer], - login: [SignInContainer], + stream: [UserBox, SignInButton], + login: [Login], }, }; diff --git a/plugins/talk-plugin-auth/client/login/components/Main.css b/plugins/talk-plugin-auth/client/login/components/Main.css new file mode 100644 index 000000000..9d73e7403 --- /dev/null +++ b/plugins/talk-plugin-auth/client/login/components/Main.css @@ -0,0 +1,8 @@ +.dialog { + border: none; + box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2); + width: 280px; + top: 10px; + font-family: Helvetica, 'Helvetica Neue', Verdana, sans-serif; + font-size: 14px; +} diff --git a/plugins/talk-plugin-auth/client/login/components/Main.js b/plugins/talk-plugin-auth/client/login/components/Main.js new file mode 100644 index 000000000..e74a38b66 --- /dev/null +++ b/plugins/talk-plugin-auth/client/login/components/Main.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { Dialog } from 'plugin-api/beta/client/components/ui'; +import styles from './Main.css'; + +import SignIn from '../containers/SignIn'; + +const SignDialog = () => ( + + + +); + +export default SignDialog; diff --git a/plugins/talk-plugin-auth/client/login/components/SignIn.css b/plugins/talk-plugin-auth/client/login/components/SignIn.css new file mode 100644 index 000000000..e6442d6f3 --- /dev/null +++ b/plugins/talk-plugin-auth/client/login/components/SignIn.css @@ -0,0 +1,47 @@ +.header { + margin-bottom: 20px; +} + +.header h1, .separator h1{ + text-align: center; + font-size: 1.2em; +} + +.socialConnections { + margin-bottom: 20px; +} + +.separator h1{ + text-align: center; + font-size: 1.2em; +} + +.action { + margin-top: 0px; +} + +.signInButton { + margin-top: 10px; + background-color: #2a2a2a; +} + +.footer { + margin: 20px auto 10px; + text-align: center; +} + +.footer span { + display: block; + margin-bottom: 5px; +} + +.footer a { + color: #2c69b6; + cursor: pointer; + margin: 0 5px; +} + +.recaptcha { + margin-top: 16px; + margin-bottom: 16px; +} diff --git a/plugins/talk-plugin-auth/client/login/components/SignIn.js b/plugins/talk-plugin-auth/client/login/components/SignIn.js new file mode 100644 index 000000000..720a5aaf0 --- /dev/null +++ b/plugins/talk-plugin-auth/client/login/components/SignIn.js @@ -0,0 +1,140 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { + Button, + TextField, + Spinner, + Alert, +} from 'plugin-api/beta/client/components/ui'; +import styles from './SignIn.css'; +import t from 'coral-framework/services/i18n'; +import cn from 'classnames'; +import Recaptcha from 'coral-framework/components/Recaptcha'; + +class SignIn extends React.Component { + recaptcha = null; + + handleForgotPasswordLink = e => { + e.preventDefault(); + this.props.onForgotPasswordLink(); + }; + handleRegisterLink = e => { + e.preventDefault(); + this.props.onRegisterLink(); + }; + handleEmailChange = e => this.props.onEmailChange(e.target.value); + handlePasswordChange = e => this.props.onPasswordChange(e.target.value); + + handleSubmit = e => { + e.preventDefault(); + this.props.onSubmit(); + + // Reset recaptcha because each response can only + // be used once. + if (this.recaptcha) { + this.recaptcha.reset(); + } + }; + + handleRecaptchaRef = ref => { + this.recaptcha = ref; + }; + + render() { + const { + email, + password, + errorMessage, + requireRecaptcha, + loading, + } = this.props; + return ( +
+
+

{t('sign_in.sign_in_to_join')}

+
+ {errorMessage && {errorMessage}} +
+
+ Social +
+
+

{t('sign_in.or')}

+
+
+ + + {requireRecaptcha && ( +
+ +
+ )} +
+ {!loading ? ( + + ) : ( + + )} +
+ +
+
+ + + {t('sign_in.forgot_your_pass')} + + + + {t('sign_in.need_an_account')} + + {t('sign_in.register')} + + +
+
+ ); + } +} + +SignIn.propTypes = { + loading: PropTypes.bool.isRequired, + email: PropTypes.string.isRequired, + password: PropTypes.string.isRequired, + onEmailChange: PropTypes.func.isRequired, + onPasswordChange: PropTypes.func.isRequired, + onForgotPasswordLink: PropTypes.func.isRequired, + onRegisterLink: PropTypes.func.isRequired, + onRecaptchaVerify: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + errorMessage: PropTypes.string.isRequired, + requireRecaptcha: PropTypes.bool.isRequired, +}; + +export default SignIn; diff --git a/plugins/talk-plugin-auth/client/login/containers/Main.js b/plugins/talk-plugin-auth/client/login/containers/Main.js new file mode 100644 index 000000000..5baedcf08 --- /dev/null +++ b/plugins/talk-plugin-auth/client/login/containers/Main.js @@ -0,0 +1,10 @@ +import React from 'react'; +import Main from '../components/Main'; + +class MainContainer extends React.Component { + render() { + return
; + } +} + +export default MainContainer; diff --git a/plugins/talk-plugin-auth/client/login/containers/SignIn.js b/plugins/talk-plugin-auth/client/login/containers/SignIn.js new file mode 100644 index 000000000..14d87bf0f --- /dev/null +++ b/plugins/talk-plugin-auth/client/login/containers/SignIn.js @@ -0,0 +1,65 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { withSignIn } from 'coral-framework/hocs'; +import { compose } from 'recompose'; +import SignIn from '../components/SignIn'; + +class SignInContainer extends Component { + state = { + email: '', + password: '', + recaptchaResponse: '', + }; + + handleSubmit = () => { + this.props.signIn( + this.state.email, + this.state.password, + this.state.recaptchaResponse + ); + }; + + handleEmailChange = email => { + this.setState({ email }); + }; + + handlePasswordChange = password => { + this.setState({ password }); + }; + + handleRecaptchaVerify = recaptchaResponse => { + this.setState({ recaptchaResponse }); + }; + + componentWillReceiveProps(nextProps) { + if (nextProps.success) { + window.close(); + } + } + + render() { + return ( + + ); + } +} + +SignInContainer.propTypes = { + signIn: PropTypes.func.isRequired, + errorMessage: PropTypes.string.isRequired, + requireRecaptcha: PropTypes.bool.isRequired, + loading: PropTypes.bool.isRequired, + success: PropTypes.bool.isRequired, +}; + +export default compose(withSignIn)(SignInContainer); diff --git a/plugins/talk-plugin-auth/client/stream/components/SetUsernameDialog.css b/plugins/talk-plugin-auth/client/stream/components/SetUsernameDialog.css new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/talk-plugin-auth/client/components/CreateUsernameDialog.js b/plugins/talk-plugin-auth/client/stream/components/SetUsernameDialog.js similarity index 95% rename from plugins/talk-plugin-auth/client/components/CreateUsernameDialog.js rename to plugins/talk-plugin-auth/client/stream/components/SetUsernameDialog.js index 08ddc171e..681f444ee 100644 --- a/plugins/talk-plugin-auth/client/components/CreateUsernameDialog.js +++ b/plugins/talk-plugin-auth/client/stream/components/SetUsernameDialog.js @@ -10,7 +10,7 @@ import { import { FakeComment } from './FakeComment'; import t from 'coral-framework/services/i18n'; -const CreateUsernameDialog = ({ +const SetUsernameDialog = ({ open, handleClose, formData, @@ -70,7 +70,7 @@ const CreateUsernameDialog = ({ ); -CreateUsernameDialog.propTypes = { +SetUsernameDialog.propTypes = { open: PropTypes.bool, handleClose: PropTypes.func, formData: PropTypes.object, @@ -80,4 +80,4 @@ CreateUsernameDialog.propTypes = { errors: PropTypes.object, }; -export default CreateUsernameDialog; +export default SetUsernameDialog; diff --git a/plugins/talk-plugin-auth/client/stream/components/SignInButton.css b/plugins/talk-plugin-auth/client/stream/components/SignInButton.css new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/talk-plugin-auth/client/components/SignInButton.js b/plugins/talk-plugin-auth/client/stream/components/SignInButton.js similarity index 52% rename from plugins/talk-plugin-auth/client/components/SignInButton.js rename to plugins/talk-plugin-auth/client/stream/components/SignInButton.js index 9ad19599e..dcc6e5c4a 100644 --- a/plugins/talk-plugin-auth/client/components/SignInButton.js +++ b/plugins/talk-plugin-auth/client/stream/components/SignInButton.js @@ -1,8 +1,6 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Button } from 'plugin-api/beta/client/components/ui'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import { showSignInDialog } from 'coral-embed-stream/src/actions/login'; import t from 'coral-framework/services/i18n'; const SignInButton = ({ currentUser, showSignInDialog }) => ( @@ -15,11 +13,9 @@ const SignInButton = ({ currentUser, showSignInDialog }) => ( ); -const mapStateToProps = ({ auth }) => ({ - currentUser: auth.user, -}); +SignInButton.propTypes = { + currentUser: PropTypes.object, + showSignInDialog: PropTypes.func, +}; -const mapDispatchToProps = dispatch => - bindActionCreators({ showSignInDialog }, dispatch); - -export default connect(mapStateToProps, mapDispatchToProps)(SignInButton); +export default SignInButton; diff --git a/plugins/talk-plugin-auth/client/stream/components/UserBox.css b/plugins/talk-plugin-auth/client/stream/components/UserBox.css new file mode 100644 index 000000000..799468177 --- /dev/null +++ b/plugins/talk-plugin-auth/client/stream/components/UserBox.css @@ -0,0 +1,21 @@ +.userBox { + margin: 10px 0 20px; + letter-spacing: 0.1px; +} + +.userBoxLoggedIn { + font-weight: bold; +} + +.userBox a { + color: black; + font-weight: bold; + cursor: pointer; + margin: 0px; + margin-left: 4px; + padding-bottom: 2px; +} + +.userBox .logout { + border-bottom: solid 1px black; +} diff --git a/plugins/talk-plugin-auth/client/stream/components/UserBox.js b/plugins/talk-plugin-auth/client/stream/components/UserBox.js new file mode 100644 index 000000000..7f48513b8 --- /dev/null +++ b/plugins/talk-plugin-auth/client/stream/components/UserBox.js @@ -0,0 +1,32 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styles from './UserBox.css'; +import t from 'coral-framework/services/i18n'; +import cn from 'classnames'; + +const UserBox = ({ user, logout, onShowProfile }) => ( +
+ {user ? ( +
+ + {t('sign_in.logged_in_as')} + + {user.username}. {t('sign_in.not_you')} + logout()} + > + {t('sign_in.logout')} + +
+ ) : null} +
+); + +UserBox.propTypes = { + user: PropTypes.object, + logout: PropTypes.func, + onShowProfile: PropTypes.func, +}; + +export default UserBox; diff --git a/plugins/talk-plugin-auth/client/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/stream/containers/SetUsernameDialog.js similarity index 97% rename from plugins/talk-plugin-auth/client/components/ChangeUsername.js rename to plugins/talk-plugin-auth/client/stream/containers/SetUsernameDialog.js index 2eab273cc..cba032cd6 100644 --- a/plugins/talk-plugin-auth/client/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/stream/containers/SetUsernameDialog.js @@ -19,7 +19,7 @@ import { updateUsername, } from 'coral-embed-stream/src/actions/login'; -class ChangeUsernameContainer extends React.Component { +class SetUsernameDialog extends React.Component { constructor(props) { super(props); @@ -152,7 +152,7 @@ class ChangeUsernameContainer extends React.Component { } } -ChangeUsernameContainer.propTypes = { +SetUsernameDialog.propTypes = { auth: PropTypes.object, hideCreateUsernameDialog: PropTypes.func, validForm: PropTypes.func, @@ -180,4 +180,4 @@ const mapDispatchToProps = dispatch => export default compose( withSetUsername, connect(mapStateToProps, mapDispatchToProps) -)(ChangeUsernameContainer); +)(SetUsernameDialog); diff --git a/plugins/talk-plugin-auth/client/stream/containers/SignInButton.js b/plugins/talk-plugin-auth/client/stream/containers/SignInButton.js new file mode 100644 index 000000000..4fcd98ae3 --- /dev/null +++ b/plugins/talk-plugin-auth/client/stream/containers/SignInButton.js @@ -0,0 +1,13 @@ +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { showSignInDialog } from 'coral-embed-stream/src/actions/login'; +import SignInButton from '../components//SignInButton'; + +const mapStateToProps = ({ auth }) => ({ + currentUser: auth.user, +}); + +const mapDispatchToProps = dispatch => + bindActionCreators({ showSignInDialog }, dispatch); + +export default connect(mapStateToProps, mapDispatchToProps)(SignInButton); diff --git a/plugins/talk-plugin-auth/client/stream/containers/UserBox.js b/plugins/talk-plugin-auth/client/stream/containers/UserBox.js new file mode 100644 index 000000000..ca50c7b6e --- /dev/null +++ b/plugins/talk-plugin-auth/client/stream/containers/UserBox.js @@ -0,0 +1,12 @@ +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { logout } from 'coral-framework/actions/auth'; +import UserBox from '../components/UserBox'; + +const mapStateToProps = ({ auth }) => ({ + user: auth.user, +}); + +const mapDispatchToProps = dispatch => bindActionCreators({ logout }, dispatch); + +export default connect(mapStateToProps, mapDispatchToProps)(UserBox); diff --git a/views/login.ejs b/views/login.ejs index 634054074..04e64d93c 100644 --- a/views/login.ejs +++ b/views/login.ejs @@ -15,6 +15,7 @@
+ diff --git a/yarn.lock b/yarn.lock index d13397fee..62ebbc4f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7697,8 +7697,8 @@ react-portal@^4.1.2: prop-types "^15.5.8" react-recaptcha@^2.2.6: - version "2.3.5" - resolved "https://registry.yarnpkg.com/react-recaptcha/-/react-recaptcha-2.3.5.tgz#a5db337125bb00fb13c2fa2e4ebfbe8b0cd06bb7" + version "2.3.6" + resolved "https://registry.yarnpkg.com/react-recaptcha/-/react-recaptcha-2.3.6.tgz#afe07b5552f3ea4d37ecd22d9881c2776719ec2b" react-redux@^4.4.5: version "4.4.8"