From e803593fc7fb204b2a2bcd5a598e38772662f259 Mon Sep 17 00:00:00 2001 From: gaba Date: Mon, 30 Jan 2017 11:34:04 -0800 Subject: [PATCH] Move stuff around. --- client/coral-embed-stream/src/Embed.js | 11 +- client/coral-framework/actions/auth.js | 14 ++ .../components/CreateDisplayNameDialog.js | 44 ++++++ client/coral-framework/components/styles.css | 140 ++++++++++++++++++ client/coral-framework/constants/auth.js | 3 + .../containers/ChangeDisplayNameContainer.js | 140 ++++++++++++++++++ client/coral-framework/reducers/auth.js | 8 + client/coral-framework/translations.json | 15 ++ services/users.js | 12 ++ 9 files changed, 378 insertions(+), 9 deletions(-) create mode 100644 client/coral-framework/components/CreateDisplayNameDialog.js create mode 100644 client/coral-framework/components/styles.css create mode 100644 client/coral-framework/containers/ChangeDisplayNameContainer.js diff --git a/client/coral-embed-stream/src/Embed.js b/client/coral-embed-stream/src/Embed.js index 5922266fa..b6fee1184 100644 --- a/client/coral-embed-stream/src/Embed.js +++ b/client/coral-embed-stream/src/Embed.js @@ -19,6 +19,7 @@ import Count from 'coral-plugin-comment-count/CommentCount'; import CommentBox from 'coral-plugin-commentbox/CommentBox'; import UserBox from '../../coral-sign-in/components/UserBox'; import SignInContainer from '../../coral-sign-in/containers/SignInContainer'; +import ChangeDisplayNameContainer from '../../coral-framework/containers/ChangeDisplayNameContainer'; import SuspendedAccount from '../../coral-framework/components/SuspendedAccount'; import SettingsContainer from '../../coral-settings/containers/SettingsContainer'; import RestrictedContent from '../../coral-framework/components/RestrictedContent'; @@ -51,15 +52,6 @@ class Embed extends Component { } componentDidMount () { - - // stream id, logged in user, settings - - // Set up messaging between embedded Iframe an parent component - - // this.props.getStream(path || window.location); - // this.path = window.location.href.split('#')[0]; - // - pym.sendMessage('childReady'); pym.onMessage('DOMContentLoaded', hash => { @@ -138,6 +130,7 @@ class Embed extends Component { :

{asset.settings.closedMessage}

} {!loggedIn && } + {loggedIn && } ({type: actions.SHOW_SIGNIN_DIALOG, offset}); export const hideSignInDialog = () => ({type: actions.HIDE_SIGNIN_DIALOG}); +export const showCreateDisplayNameDialog = () => ({type: actions.SHOW_CREATEDISPLAYNAME_DIALOG}); +export const hideCreateDisplayNameDialog = () => ({type: actions.HIDE_CREATEDISPLAYNAME_DIALOG}); +export const createDisplayName = (formData) => (dispatch) => { + coralApi('/users', {method: 'POST', body: formData}) + .then(() => { + dispatch(createDisplayNameSuccess()); + dispatch(hideCreateDisplayNameDialog()); + }) + .catch(() => dispatch(createDisplayNameFailure(lang.t('createdisplay.errorCreate')))); +}; +const createDisplayNameSuccess = () => ({type: actions.CREATEDISPLAYNAME_SUCCESS}); +const createDisplayNameFailure = error => ({type: actions.CREATEDISPLAYNAME_FAILURE, error}); + export const changeView = view => dispatch => dispatch({ type: actions.CHANGE_VIEW, @@ -59,6 +72,7 @@ export const facebookCallback = (err, data) => dispatch => { const user = JSON.parse(data); dispatch(signInFacebookSuccess(user)); dispatch(hideSignInDialog()); + dispatch(showCreateDisplayNameDialog()); dispatch(addItem(user, 'users')); } catch (err) { dispatch(signInFacebookFailure(err)); diff --git a/client/coral-framework/components/CreateDisplayNameDialog.js b/client/coral-framework/components/CreateDisplayNameDialog.js new file mode 100644 index 000000000..8b61989aa --- /dev/null +++ b/client/coral-framework/components/CreateDisplayNameDialog.js @@ -0,0 +1,44 @@ +import React from 'react'; +import {Dialog} from 'coral-ui'; +import styles from './styles.css'; +import I18n from 'coral-framework/modules/i18n/i18n'; +import translations from '../translations'; +const lang = new I18n(translations); + +const CreateDisplayNameDialog = ({open, handleClose, offset, loggedIn}) => ( + + × +
+
+

+ {lang.t('createdisplay.writeyourusername')} +

+ Logged {loggedIn} +
+
+
+); + +//
+// +//
+// +//
+// + +export default CreateDisplayNameDialog; diff --git a/client/coral-framework/components/styles.css b/client/coral-framework/components/styles.css new file mode 100644 index 000000000..f9d0aec6d --- /dev/null +++ b/client/coral-framework/components/styles.css @@ -0,0 +1,140 @@ +.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; +} + +.formField { + margin-top: 15px; +} + +.formField label { + font-size: 1.08em; + font-weight: bold; + margin-bottom: 5px; +} + +.formField input { + width: 100%; + display: block; + border: none; + outline: none; + border: 1px solid rgba(0,0,0,.12); + padding: 10px 6px; + box-sizing: border-box; + border-radius: 2px; + margin: 5px auto; +} + +.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; +} + +.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; +} + +.alert { + padding: 10px; + margin-bottom: 20px; + border-radius: 2px; +} + +.alert--success { + border: solid 1px #1ec00e; + background: #cbf1b8; + color: #006900; +} + +.alert--error { + background: #FFEBEE; + color: #B71C1C; +} + +.userBox { + padding: 10px 0 20px; + letter-spacing: 0.1px; +} + +.userBox a { + color: black; + font-weight: bold; + cursor: pointer; + margin: 0px; + margin-left: 4px; + padding-bottom: 2px; + 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: 15px; +} diff --git a/client/coral-framework/constants/auth.js b/client/coral-framework/constants/auth.js index 5742adf75..27fa8890f 100644 --- a/client/coral-framework/constants/auth.js +++ b/client/coral-framework/constants/auth.js @@ -4,6 +4,9 @@ export const CLEAN_STATE = 'CLEAN_STATE'; export const SHOW_SIGNIN_DIALOG = 'SHOW_SIGNIN_DIALOG'; export const HIDE_SIGNIN_DIALOG = 'HIDE_SIGNIN_DIALOG'; +export const SHOW_CREATEDISPLAYNAME_DIALOG = 'SHOW_CREATEDISPLAYNAME_DIALOG'; +export const HIDE_CREATEDISPLAYNAME_DIALOG = 'HIDE_CREATEDISPLAYNAME_DIALOG'; + export const FETCH_SIGNUP_REQUEST = 'FETCH_SIGNUP_REQUEST'; export const FETCH_SIGNUP_FAILURE = 'FETCH_SIGNUP_FAILURE'; export const FETCH_SIGNUP_SUCCESS = 'FETCH_SIGNUP_SUCCESS'; diff --git a/client/coral-framework/containers/ChangeDisplayNameContainer.js b/client/coral-framework/containers/ChangeDisplayNameContainer.js new file mode 100644 index 000000000..17e681388 --- /dev/null +++ b/client/coral-framework/containers/ChangeDisplayNameContainer.js @@ -0,0 +1,140 @@ +import React, {Component} from 'react'; +import {connect} from 'react-redux'; + +import CreateDisplayNameDialog from '../components/CreateDisplayNameDialog'; + +// import validate from 'coral-framework/helpers/validate'; +// import errorMsj from 'coral-framework/helpers/error'; +import I18n from 'coral-framework/modules/i18n/i18n'; +import translations from '../translations'; +const lang = new I18n(translations); + +import { + showCreateDisplayNameDialog, + hideCreateDisplayNameDialog, + invalidForm, + validForm, + createDisplayName +} from '../../coral-framework/actions/auth'; + +class ChangeDisplayNameContainer extends Component { + initialState = { + formData: { + displayName: '', + }, + errors: {}, + showErrors: false + }; + + constructor(props) { + super(props); + this.state = this.initialState; + this.handleChange = this.handleChange.bind(this); + this.handleSubmitForm = this.handleSubmitForm.bind(this); + this.handleClose = this.handleClose.bind(this); + this.addError = this.addError.bind(this); + } + + componentDidMount() { + const {formData} = this.state; + const errors = Object.keys(formData).reduce((map, prop) => { + map[prop] = lang.t('createdisplay.requiredField'); + return map; + }, {}); + this.setState({errors}); + } + + handleChange(e) { + const {name, value} = e.target; + this.setState(state => ({ + ...state, + formData: { + ...state.formData, + [name]: value + } + }), () => { + this.validation(name, value); + }); + } + + addError(name, error) { + return this.setState(state => ({ + errors: { + ...state.errors, + [name]: error + } + })); + } + + validation(name, value) { + const {addError} = this; + + if (!value.length) { + addError(name, lang.t('displayName.requiredField')); + } 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}); + } + + handleSubmitForm(e) { + e.preventDefault(); + const {errors} = this.state; + const {validForm, invalidForm} = this.props; + this.displayErrors(); + if (this.isCompleted() && !Object.keys(errors).length) { + createDisplayName(this.state.formData); + validForm(); + } else { + invalidForm(lang.t('signIn.checkTheForm')); + } + } + + handleClose() { + this.props.hideCreateDisplayNameDialog(); + } + + render() { + const {loggedIn, auth, offset, user} = this.props; + return ( +
+ +
+ ); + } +} + +const mapStateToProps = state => ({ + auth: state.auth.toJS() +}); + +const mapDispatchToProps = dispatch => ({ + createDisplayName: formData => dispatch(createDisplayName(formData)), + showCreateDisplayNameDialog: () => dispatch(showCreateDisplayNameDialog()), + hideCreateDisplayNameDialog: () => dispatch(hideCreateDisplayNameDialog()), + invalidForm: error => dispatch(invalidForm(error)), + validForm: () => dispatch(validForm()) +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(ChangeDisplayNameContainer); diff --git a/client/coral-framework/reducers/auth.js b/client/coral-framework/reducers/auth.js index 36f8e0764..ff0f72b4a 100644 --- a/client/coral-framework/reducers/auth.js +++ b/client/coral-framework/reducers/auth.js @@ -7,6 +7,7 @@ const initialState = Map({ isAdmin: false, user: null, showSignInDialog: false, + showCreateDisplayNameDialog: false, view: 'SIGNIN', error: '', passwordRequestSuccess: null, @@ -35,6 +36,13 @@ export default function auth (state = initialState, action) { passwordRequestSuccess: null, successSignUp: false })); + case actions.SHOW_CREATEDISPLAYNAME_DIALOG : + return state + .set('showCreateDisplayNameDialog', true); + case actions.HIDE_CREATEDISPLAYNAME_DIALOG : + return state.merge(Map({ + showCreateDisplayNameDialog: false + })); case actions.CHANGE_VIEW : return state .set('error', '') diff --git a/client/coral-framework/translations.json b/client/coral-framework/translations.json index 5bf9b40a9..5900aad3e 100644 --- a/client/coral-framework/translations.json +++ b/client/coral-framework/translations.json @@ -4,6 +4,14 @@ "successBioUpdate": "Your Bio has been updated", "contentNotAvailable": "This content is not available", "suspendedAccountMsg": "Your account is currently suspended. This means that you cannot Like, Flag, or write comments. Please contact moderator@fakeurl.com for more information", + "createdisplay": { + "writeyourusername": "Write your username", + "yourusername": "Your username is publicly visible on all comments you post. A username is needed before you can post your first comment.", + "displayName": "Display Name", + "save": "Save", + "requiredField": "Required field", + "errorCreate": "Error when changing display name" + }, "error": { "email": "Not a valid E-Mail", "password": "Password must be at least 8 characters", @@ -26,6 +34,13 @@ "successBioUpdate": "Tu bio fue actualizada", "contentNotAvailable": "El contenido no se encuentra disponible", "suspendedAccountMsg": "Tu cuenta se encuentra suspendida. Esto significa que no puedes dar Like, Marcar o escribir commentarios. Por favor, contacta moderator@fakeurl for more information", + "createdisplay": { + "writeyourusername": "Escribe tu nombre", + "yourusername": "Tu nombre es visible publicamente en todos los comentarios que publiques. Es necesario tener un nombre de usuario antes de poder publicar tu primer comentario.", + "displayName": "Nombre", + "save": "Guardar", + "requiredField": "Campo necesario" + }, "error": { "email": "No es un email válido", "password": "La contraseña debe tener por lo menos 8 caracteres", diff --git a/services/users.js b/services/users.js index 0bf22e9e0..d1e7dce05 100644 --- a/services/users.js +++ b/services/users.js @@ -156,6 +156,18 @@ module.exports = class UsersService { }); } + static changeDisplayName(id, displayName) { + return UsersService.isValidDisplayName(displayName) + .then((displayName) => { // displayName is valid + return UserModel.update({id}, { + $inc: {__v: 1}, + $set: { + displayName: displayName + } + }); + }); + } + /** * Creates local users. * @param {Array} users Users to create