From 9f4430eced6c12681c68c0d399e7b3280632819b Mon Sep 17 00:00:00 2001 From: Bouncey Date: Thu, 20 Sep 2018 12:29:31 +0100 Subject: [PATCH] feat(settings): Internet Settings --- client/src/client-only-routes/ShowSettings.js | 38 +++- client/src/components/settings/Internet.js | 164 ++++++++++++++++++ client/src/utils/index.js | 6 +- 3 files changed, 200 insertions(+), 8 deletions(-) create mode 100644 client/src/components/settings/Internet.js diff --git a/client/src/client-only-routes/ShowSettings.js b/client/src/client-only-routes/ShowSettings.js index 7da818380f..74814afd8c 100644 --- a/client/src/client-only-routes/ShowSettings.js +++ b/client/src/client-only-routes/ShowSettings.js @@ -16,11 +16,14 @@ import FullWidthRow from '../components/helpers/FullWidthRow'; import About from '../components/settings/About'; import Privacy from '../components/settings/Privacy'; import Email from '../components/settings/Email'; +import Internet from '../components/settings/Internet'; const propTypes = { about: PropTypes.string, email: PropTypes.string, + githubProfile: PropTypes.string, isEmailVerified: PropTypes.bool, + linkedin: PropTypes.string, location: PropTypes.string, name: PropTypes.string, picture: PropTypes.string, @@ -30,8 +33,11 @@ const propTypes = { submitNewAbout: PropTypes.func.isRequired, theme: PropTypes.string, toggleNightMode: PropTypes.func.isRequired, + twitter: PropTypes.string, + updateInternetSettings: PropTypes.func.isRequired, updateQuincyEmail: PropTypes.func.isRequired, - username: PropTypes.string + username: PropTypes.string, + website: PropTypes.string }; const mapStateToProps = createSelector( @@ -49,7 +55,11 @@ const mapStateToProps = createSelector( points, name, location, - theme + theme, + githubProfile, + linkedin, + twitter, + website } ) => ({ email, @@ -62,7 +72,11 @@ const mapStateToProps = createSelector( points, name, theme, - location + location, + githubProfile, + linkedin, + twitter, + website }) ); @@ -71,6 +85,7 @@ const mapDispatchToProps = dispatch => { submitNewAbout, toggleNightMode: theme => updateUserFlag({ theme }), + updateInternetSettings: updateUserFlag, updateQuincyEmail: sendQuincyEmail => updateUserFlag({ sendQuincyEmail }) }, dispatch @@ -91,7 +106,12 @@ function ShowSettings(props) { name, submitNewAbout, toggleNightMode, - updateQuincyEmail + updateQuincyEmail, + githubProfile, + linkedin, + twitter, + website, + updateInternetSettings } = props; if (showLoading) { @@ -154,9 +174,15 @@ function ShowSettings(props) { updateQuincyEmail={updateQuincyEmail} /> - {/* + - + {/* diff --git a/client/src/components/settings/Internet.js b/client/src/components/settings/Internet.js new file mode 100644 index 0000000000..fbb4fc1c8d --- /dev/null +++ b/client/src/components/settings/Internet.js @@ -0,0 +1,164 @@ +import React, { Fragment, Component } from 'react'; +import PropTypes from 'prop-types'; +import { + FormControl, + FormGroup, + ControlLabel +} from '@freecodecamp/react-bootstrap'; +import isURL from 'validator/lib/isURL'; + +import { maybeUrlRE } from '../../utils'; + +import SectionHeader from './SectionHeader'; +import { FullWidthRow } from '../helpers'; +import BlockSaveButton from '../helpers/form/BlockSaveButton'; + +const propTypes = { + githubProfile: PropTypes.string, + linkedin: PropTypes.string, + twitter: PropTypes.string, + updateInternetSettings: PropTypes.func.isRequired, + website: PropTypes.string +}; + +class InternetSettings extends Component { + constructor(props) { + super(props); + + const { + githubProfile = '', + linkedin = '', + twitter = '', + website = '' + } = props; + + this.state = { + formValues: { githubProfile, linkedin, twitter, website }, + originalValues: { githubProfile, linkedin, twitter, website } + }; + } + + getValidationStateFor(maybeURl = '') { + if (!maybeURl || !maybeUrlRE.test(maybeURl)) { + return null; + } + if (isURL(maybeURl)) { + return 'success'; + } + return 'error'; + } + + createHandleChange = key => e => { + const value = e.target.value.slice(0); + return this.setState(state => ({ + formValues: { + ...state.formValues, + [key]: value + } + })); + }; + + isFormPristine = () => { + const { formValues, originalValues } = this.state; + return Object.keys(originalValues) + .map(key => originalValues[key] === formValues[key]) + .every(bool => bool); + }; + + isFormValid = () => { + const { formValues } = this.state; + return Object.keys(formValues).reduce((bool, key) => { + const maybeUrl = formValues[key]; + return maybeUrl ? isURL(maybeUrl) : bool; + }, false); + }; + + handleSubmit = e => { + e.preventDefault(); + if (!this.isFormPristine() && this.isFormValid()) { + // Only submit the form if is has changed, and if it is valid + const { formValues } = this.state; + const { updateInternetSettings } = this.props; + return updateInternetSettings(formValues); + } + return null; + }; + + render() { + const { + formValues: { githubProfile, linkedin, twitter, website } + } = this.state; + return ( + + Your Internet Presence + +
+ + + GitHub + + + + + + LinkedIn + + + + + + Twitter + + + + + + Personal Website + + + + + +
+
+ ); + } +} + +InternetSettings.displayName = 'InternetSettings'; +InternetSettings.propTypes = propTypes; + +export default InternetSettings; diff --git a/client/src/utils/index.js b/client/src/utils/index.js index f46b749d05..32f22feef1 100644 --- a/client/src/utils/index.js +++ b/client/src/utils/index.js @@ -1,3 +1,5 @@ -// This regex is not for validation, it is purely to see -// if we are looking at something like an email before we try to validate +// These regex are not for validation, it is purely to see +// if we are looking at something like what we want to validate +// before we try to validate export const maybeEmailRE = /.*@.*\.\w\w/; +export const maybeUrlRE = /https?:\/\/.*\..*/;