summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--webapp/components/login/login_controller.jsx1
-rw-r--r--webapp/components/signup/components/signup_email.jsx507
-rw-r--r--webapp/components/signup/components/signup_ldap.jsx233
-rw-r--r--webapp/components/signup/signup_controller.jsx333
-rw-r--r--webapp/components/signup_user_complete.jsx840
-rw-r--r--webapp/i18n/en.json6
-rw-r--r--webapp/routes/route_root.jsx14
-rw-r--r--webapp/sass/routes/_signup.scss29
8 files changed, 1113 insertions, 850 deletions
diff --git a/webapp/components/login/login_controller.jsx b/webapp/components/login/login_controller.jsx
index f62464f37..5a5d0388a 100644
--- a/webapp/components/login/login_controller.jsx
+++ b/webapp/components/login/login_controller.jsx
@@ -520,6 +520,7 @@ export default class LoginController extends React.Component {
key='saml'
href={'/login/sso/saml' + this.props.location.search}
>
+ <span className='icon fa fa-lock fa--margin-top'/>
<span>
{window.mm_config.SamlLoginButtonText}
</span>
diff --git a/webapp/components/signup/components/signup_email.jsx b/webapp/components/signup/components/signup_email.jsx
new file mode 100644
index 000000000..2d4b3f277
--- /dev/null
+++ b/webapp/components/signup/components/signup_email.jsx
@@ -0,0 +1,507 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import LoadingScreen from 'components/loading_screen.jsx';
+
+import * as GlobalActions from 'actions/global_actions.jsx';
+import {track} from 'actions/analytics_actions.jsx';
+
+import BrowserStore from 'stores/browser_store.jsx';
+
+import * as Utils from 'utils/utils.jsx';
+import Client from 'client/web_client.jsx';
+import Constants from 'utils/constants.jsx';
+
+import React from 'react';
+import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
+import {browserHistory, Link} from 'react-router/es6';
+
+import logoImage from 'images/logo.png';
+
+export default class SignupEmail extends React.Component {
+ static get propTypes() {
+ return {
+ location: React.PropTypes.object
+ };
+ }
+
+ constructor(props) {
+ super(props);
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+
+ this.getInviteInfo = this.getInviteInfo.bind(this);
+ this.renderEmailSignup = this.renderEmailSignup.bind(this);
+ this.isUserValid = this.isUserValid.bind(this);
+
+ this.state = this.getInviteInfo();
+ }
+
+ getInviteInfo() {
+ let data = this.props.location.query.d;
+ let hash = this.props.location.query.h;
+ const inviteId = this.props.location.query.id;
+ let email = '';
+ let teamDisplayName = '';
+ let teamName = '';
+ let teamId = '';
+ let loading = true;
+ let serverError = '';
+ let noOpenServerError = false;
+
+ if (hash && hash.length > 0) {
+ const parsedData = JSON.parse(data);
+ email = parsedData.email;
+ teamDisplayName = parsedData.display_name;
+ teamName = parsedData.name;
+ teamId = parsedData.id;
+ loading = false;
+ } else if (inviteId && inviteId.length > 0) {
+ loading = true;
+ Client.getInviteInfo(
+ inviteId,
+ (inviteData) => {
+ if (!inviteData) {
+ return;
+ }
+
+ serverError = '';
+ teamDisplayName = inviteData.display_name;
+ teamName = inviteData.name;
+ teamId = inviteData.id;
+ },
+ () => {
+ noOpenServerError = true;
+ serverError = (
+ <FormattedMessage
+ id='signup_user_completed.invalid_invite'
+ defaultMessage='The invite link was invalid. Please speak with your Administrator to receive an invitation.'
+ />
+ );
+ }
+ );
+
+ loading = false;
+ data = null;
+ hash = null;
+ } else {
+ loading = false;
+ }
+
+ return {
+ data,
+ hash,
+ email,
+ teamDisplayName,
+ teamName,
+ teamId,
+ inviteId,
+ loading,
+ serverError,
+ noOpenServerError
+ };
+ }
+
+ finishSignup() {
+ GlobalActions.emitInitialLoad(
+ () => {
+ const query = this.props.location.query;
+ GlobalActions.loadDefaultLocale();
+ if (query.redirect_to) {
+ browserHistory.push(query.redirect_to);
+ } else {
+ browserHistory.push('/select_team');
+ }
+ }
+ );
+ }
+
+ handleSignupSuccess(user, data) {
+ track('signup', 'signup_user_02_complete');
+ Client.loginById(
+ data.id,
+ user.password,
+ '',
+ () => {
+ if (this.state.hash > 0) {
+ BrowserStore.setGlobalItem(this.state.hash, JSON.stringify({usedBefore: true}));
+ }
+
+ GlobalActions.emitInitialLoad(
+ () => {
+ const query = this.props.location.query;
+ if (query.redirect_to) {
+ browserHistory.push(query.redirect_to);
+ } else {
+ browserHistory.push('/select_team');
+ }
+ }
+ );
+ },
+ (err) => {
+ if (err.id === 'api.user.login.not_verified.app_error') {
+ browserHistory.push('/should_verify_email?email=' + encodeURIComponent(user.email) + '&teamname=' + encodeURIComponent(this.state.teamName));
+ } else {
+ this.setState({serverError: err.message});
+ }
+ }
+ );
+ }
+
+ isUserValid() {
+ const providedEmail = this.refs.email.value.trim();
+ if (!providedEmail) {
+ this.setState({
+ nameError: '',
+ emailError: (<FormattedMessage id='signup_user_completed.required'/>),
+ passwordError: '',
+ serverError: ''
+ });
+ return false;
+ }
+
+ if (!Utils.isEmail(providedEmail)) {
+ this.setState({
+ nameError: '',
+ emailError: (<FormattedMessage id='signup_user_completed.validEmail'/>),
+ passwordError: '',
+ serverError: ''
+ });
+ return false;
+ }
+
+ const providedUsername = this.refs.name.value.trim().toLowerCase();
+ if (!providedUsername) {
+ this.setState({
+ nameError: (<FormattedMessage id='signup_user_completed.required'/>),
+ emailError: '',
+ passwordError: '',
+ serverError: ''
+ });
+ return false;
+ }
+
+ const usernameError = Utils.isValidUsername(providedUsername);
+ if (usernameError === 'Cannot use a reserved word as a username.') {
+ this.setState({
+ nameError: (<FormattedMessage id='signup_user_completed.reserved'/>),
+ emailError: '',
+ passwordError: '',
+ serverError: ''
+ });
+ return false;
+ } else if (usernameError) {
+ this.setState({
+ nameError: (
+ <FormattedMessage
+ id='signup_user_completed.usernameLength'
+ values={{
+ min: Constants.MIN_USERNAME_LENGTH,
+ max: Constants.MAX_USERNAME_LENGTH
+ }}
+ />
+ ),
+ emailError: '',
+ passwordError: '',
+ serverError: ''
+ });
+ return false;
+ }
+
+ const providedPassword = this.refs.password.value;
+ const pwdError = Utils.isValidPassword(providedPassword);
+ if (pwdError) {
+ this.setState({
+ nameError: '',
+ emailError: '',
+ passwordError: pwdError,
+ serverError: ''
+ });
+ return false;
+ }
+
+ return true;
+ }
+
+ handleSubmit(e) {
+ e.preventDefault();
+
+ if (this.isUserValid()) {
+ this.setState({
+ nameError: '',
+ emailError: '',
+ passwordError: '',
+ serverError: ''
+ });
+
+ const user = {
+ email: this.refs.email.value.trim(),
+ username: this.refs.name.value.trim().toLowerCase(),
+ password: this.refs.password.value,
+ allow_marketing: true
+ };
+
+ Client.createUserWithInvite(user,
+ this.state.data,
+ this.state.hash,
+ this.state.inviteId,
+ this.handleSignupSuccess.bind(this, user),
+ (err) => {
+ this.setState({serverError: err.message});
+ }
+ );
+ }
+ }
+
+ renderEmailSignup() {
+ let emailError = null;
+ let emailHelpText = (
+ <span className='help-block'>
+ <FormattedMessage
+ id='signup_user_completed.emailHelp'
+ defaultMessage='Valid email required for sign-up'
+ />
+ </span>
+ );
+ let emailDivStyle = 'form-group';
+ if (this.state.emailError) {
+ emailError = (<label className='control-label'>{this.state.emailError}</label>);
+ emailHelpText = '';
+ emailDivStyle += ' has-error';
+ }
+
+ let nameError = null;
+ let nameHelpText = (
+ <span className='help-block'>
+ <FormattedMessage
+ id='signup_user_completed.userHelp'
+ defaultMessage="Username must begin with a letter, and contain between {min} to {max} lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'"
+ values={{
+ min: Constants.MIN_USERNAME_LENGTH,
+ max: Constants.MAX_USERNAME_LENGTH
+ }}
+ />
+ </span>
+ );
+ let nameDivStyle = 'form-group';
+ if (this.state.nameError) {
+ nameError = <label className='control-label'>{this.state.nameError}</label>;
+ nameHelpText = '';
+ nameDivStyle += ' has-error';
+ }
+
+ let passwordError = null;
+ let passwordDivStyle = 'form-group';
+ if (this.state.passwordError) {
+ passwordError = <label className='control-label'>{this.state.passwordError}</label>;
+ passwordDivStyle += ' has-error';
+ }
+
+ let yourEmailIs = null;
+ if (this.state.email) {
+ yourEmailIs = (
+ <FormattedHTMLMessage
+ id='signup_user_completed.emailIs'
+ defaultMessage="Your email address is <strong>{email}</strong>. You'll use this address to sign in to {siteName}."
+ values={{
+ email: this.state.email,
+ siteName: global.window.mm_config.SiteName
+ }}
+ />
+ );
+ }
+
+ let emailContainerStyle = 'margin--extra';
+ if (this.state.email) {
+ emailContainerStyle = 'hidden';
+ }
+
+ return (
+ <form>
+ <div className='inner__content'>
+ <div className={emailContainerStyle}>
+ <h5><strong>
+ <FormattedMessage
+ id='signup_user_completed.whatis'
+ defaultMessage="What's your email address?"
+ />
+ </strong></h5>
+ <div className={emailDivStyle}>
+ <input
+ type='email'
+ ref='email'
+ className='form-control'
+ defaultValue={this.state.email}
+ placeholder=''
+ maxLength='128'
+ autoFocus={true}
+ spellCheck='false'
+ autoCapitalize='off'
+ />
+ {emailError}
+ {emailHelpText}
+ </div>
+ </div>
+ {yourEmailIs}
+ <div className='margin--extra'>
+ <h5><strong>
+ <FormattedMessage
+ id='signup_user_completed.chooseUser'
+ defaultMessage='Choose your username'
+ />
+ </strong></h5>
+ <div className={nameDivStyle}>
+ <input
+ type='text'
+ ref='name'
+ className='form-control'
+ placeholder=''
+ maxLength={Constants.MAX_USERNAME_LENGTH}
+ spellCheck='false'
+ autoCapitalize='off'
+ />
+ {nameError}
+ {nameHelpText}
+ </div>
+ </div>
+ <div className='margin--extra'>
+ <h5><strong>
+ <FormattedMessage
+ id='signup_user_completed.choosePwd'
+ defaultMessage='Choose your password'
+ />
+ </strong></h5>
+ <div className={passwordDivStyle}>
+ <input
+ type='password'
+ ref='password'
+ className='form-control'
+ placeholder=''
+ maxLength='128'
+ spellCheck='false'
+ />
+ {passwordError}
+ </div>
+ </div>
+ <p className='margin--extra'>
+ <button
+ type='submit'
+ onClick={this.handleSubmit}
+ className='btn-primary btn'
+ >
+ <FormattedMessage
+ id='signup_user_completed.create'
+ defaultMessage='Create Account'
+ />
+ </button>
+ </p>
+ </div>
+ </form>
+ );
+ }
+
+ render() {
+ track('signup', 'signup_user_01_welcome');
+
+ let serverError = null;
+ if (this.state.serverError) {
+ serverError = (
+ <div className={'form-group has-error'}>
+ <label className='control-label'>{this.state.serverError}</label>
+ </div>
+ );
+ }
+
+ if (this.state.loading) {
+ return (<LoadingScreen/>);
+ }
+
+ let emailSignup;
+ if (global.window.mm_config.EnableSignUpWithEmail === 'true') {
+ emailSignup = this.renderEmailSignup();
+ } else {
+ return null;
+ }
+
+ let terms = null;
+ if (!this.state.noOpenServerError && emailSignup) {
+ terms = (
+ <p>
+ <FormattedHTMLMessage
+ id='create_team.agreement'
+ defaultMessage="By proceeding to create your account and use {siteName}, you agree to our <a href='/static/help/terms.html'>Terms of Service</a> and <a href='/static/help/privacy.html'>Privacy Policy</a>. If you do not agree, you cannot use {siteName}."
+ values={{
+ siteName: global.window.mm_config.SiteName
+ }}
+ />
+ </p>
+ );
+ }
+
+ if (this.state.noOpenServerError) {
+ emailSignup = null;
+ }
+
+ let description = null;
+ if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true' && global.window.mm_config.EnableCustomBrand === 'true') {
+ description = global.window.mm_config.CustomDescriptionText;
+ } else {
+ description = (
+ <FormattedMessage
+ id='web.root.signup_info'
+ defaultMessage='All team communication in one place, searchable and accessible anywhere'
+ />
+ );
+ }
+
+ return (
+ <div>
+ <div className='signup-header'>
+ <Link to='/signup_user_complete'>
+ <span className='fa fa-chevron-left'/>
+ <FormattedMessage
+ id='web.header.back'
+ />
+ </Link>
+ </div>
+ <div className='col-sm-12'>
+ <div className='signup-team__container padding--less'>
+ <img
+ className='signup-team-logo'
+ src={logoImage}
+ />
+ <h1>{global.window.mm_config.SiteName}</h1>
+ <h4 className='color--light'>
+ {description}
+ </h4>
+ <h4 className='color--light'>
+ <FormattedMessage
+ id='signup_user_completed.lets'
+ defaultMessage="Let's create your account"
+ />
+ </h4>
+ <span className='color--light'>
+ <FormattedMessage
+ id='signup_user_completed.haveAccount'
+ defaultMessage='Already have an account?'
+ />
+ {' '}
+ <Link
+ to={'/login'}
+ query={this.props.location.query}
+ >
+ <FormattedMessage
+ id='signup_user_completed.signIn'
+ defaultMessage='Click here to sign in.'
+ />
+ </Link>
+ </span>
+ {emailSignup}
+ {serverError}
+ {terms}
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/webapp/components/signup/components/signup_ldap.jsx b/webapp/components/signup/components/signup_ldap.jsx
new file mode 100644
index 000000000..92089f2f7
--- /dev/null
+++ b/webapp/components/signup/components/signup_ldap.jsx
@@ -0,0 +1,233 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import FormError from 'components/form_error.jsx';
+
+import * as GlobalActions from 'actions/global_actions.jsx';
+import {track} from 'actions/analytics_actions.jsx';
+
+import * as Utils from 'utils/utils.jsx';
+import Client from 'client/web_client.jsx';
+
+import React from 'react';
+import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
+import {browserHistory, Link} from 'react-router/es6';
+
+import logoImage from 'images/logo.png';
+
+export default class SignupLdap extends React.Component {
+ static get propTypes() {
+ return {
+ location: React.PropTypes.object
+ };
+ }
+
+ constructor(props) {
+ super(props);
+
+ this.handleLdapSignup = this.handleLdapSignup.bind(this);
+ this.handleLdapSignupSuccess = this.handleLdapSignupSuccess.bind(this);
+
+ this.state = ({
+ ldapError: ''
+ });
+ }
+
+ handleLdapSignup(e) {
+ e.preventDefault();
+
+ this.setState({ldapError: ''});
+
+ Client.webLoginByLdap(
+ this.refs.id.value.trim(),
+ this.refs.password.value,
+ null,
+ this.handleLdapSignupSuccess,
+ (err) => {
+ this.setState({
+ ldapError: err.message
+ });
+ }
+ );
+ }
+
+ handleLdapSignupSuccess() {
+ if (this.props.location.query.id || this.props.location.query.h) {
+ Client.addUserToTeamFromInvite(
+ this.props.location.query.d,
+ this.props.location.query.h,
+ this.props.location.query.id,
+ () => {
+ this.finishSignup();
+ },
+ () => {
+ // there's not really a good way to deal with this, so just let the user log in like normal
+ this.finishSignup();
+ }
+ );
+ } else {
+ this.finishSignup();
+ }
+ }
+
+ finishSignup() {
+ GlobalActions.emitInitialLoad(
+ () => {
+ GlobalActions.loadDefaultLocale();
+ browserHistory.push('/select_team');
+ }
+ );
+ }
+
+ render() {
+ track('signup', 'signup_user_01_welcome');
+
+ let ldapIdPlaceholder;
+ if (global.window.mm_config.LdapLoginFieldName) {
+ ldapIdPlaceholder = global.window.mm_config.LdapLoginFieldName;
+ } else {
+ ldapIdPlaceholder = Utils.localizeMessage('login.ldap_username', 'LDAP Username');
+ }
+
+ let errorClass = '';
+ if (this.state.ldapError) {
+ errorClass += ' has-error';
+ }
+
+ let ldapSignup;
+ if (global.window.mm_config.EnableLdap === 'true' && global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.LDAP) {
+ ldapSignup = (
+ <div className='inner__content'>
+ <h5>
+ <strong>
+ <FormattedMessage
+ id='signup.ldap'
+ defaultMessage='LDAP Credentials'
+ />
+ </strong>
+ </h5>
+ <form
+ onSubmit={this.handleLdapSignup}
+ >
+ <div className='signup__email-container'>
+ <FormError
+ error={this.state.ldapError}
+ margin={true}
+ />
+ <div className={'form-group' + errorClass}>
+ <input
+ className='form-control'
+ name='ldapId'
+ ref='id'
+ placeholder={ldapIdPlaceholder}
+ spellCheck='false'
+ autoCapitalize='off'
+ />
+ </div>
+ <div className={'form-group' + errorClass}>
+ <input
+ type='password'
+ className='form-control'
+ name='password'
+ ref='password'
+ placeholder={Utils.localizeMessage('login.password', 'Password')}
+ spellCheck='false'
+ />
+ </div>
+ <div className='form-group'>
+ <button
+ type='submit'
+ className='btn btn-primary'
+ disabled={!this.state.ldapId || !this.state.ldapPassword}
+ >
+ <FormattedMessage
+ id='login.signIn'
+ defaultMessage='Sign in'
+ />
+ </button>
+ </div>
+ </div>
+ </form>
+ </div>
+ );
+ } else {
+ return null;
+ }
+
+ let terms = null;
+ if (ldapSignup) {
+ terms = (
+ <p>
+ <FormattedHTMLMessage
+ id='create_team.agreement'
+ defaultMessage="By proceeding to create your account and use {siteName}, you agree to our <a href='/static/help/terms.html'>Terms of Service</a> and <a href='/static/help/privacy.html'>Privacy Policy</a>. If you do not agree, you cannot use {siteName}."
+ values={{
+ siteName: global.window.mm_config.SiteName
+ }}
+ />
+ </p>
+ );
+ }
+
+ let description = null;
+ if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true' && global.window.mm_config.EnableCustomBrand === 'true') {
+ description = global.window.mm_config.CustomDescriptionText;
+ } else {
+ description = (
+ <FormattedMessage
+ id='web.root.signup_info'
+ defaultMessage='All team communication in one place, searchable and accessible anywhere'
+ />
+ );
+ }
+
+ return (
+ <div>
+ <div className='signup-header'>
+ <Link to='/signup_user_complete'>
+ <span className='fa fa-chevron-left'/>
+ <FormattedMessage
+ id='web.header.back'
+ />
+ </Link>
+ </div>
+ <div className='col-sm-12'>
+ <div className='signup-team__container padding--less'>
+ <img
+ className='signup-team-logo'
+ src={logoImage}
+ />
+ <h1>{global.window.mm_config.SiteName}</h1>
+ <h4 className='color--light'>
+ {description}
+ </h4>
+ <h4 className='color--light'>
+ <FormattedMessage
+ id='signup_user_completed.lets'
+ defaultMessage="Let's create your account"
+ />
+ </h4>
+ <span className='color--light'>
+ <FormattedMessage
+ id='signup_user_completed.haveAccount'
+ defaultMessage='Already have an account?'
+ />
+ {' '}
+ <Link
+ to={'/login'}
+ query={this.props.location.query}
+ >
+ <FormattedMessage
+ id='signup_user_completed.signIn'
+ defaultMessage='Click here to sign in.'
+ />
+ </Link>
+ </span>
+ {ldapSignup}
+ {terms}
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/webapp/components/signup/signup_controller.jsx b/webapp/components/signup/signup_controller.jsx
new file mode 100644
index 000000000..a0587bba9
--- /dev/null
+++ b/webapp/components/signup/signup_controller.jsx
@@ -0,0 +1,333 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import React from 'react';
+
+import FormError from 'components/form_error.jsx';
+import LoadingScreen from 'components/loading_screen.jsx';
+
+import UserStore from 'stores/user_store.jsx';
+import BrowserStore from 'stores/browser_store.jsx';
+
+import * as AsyncClient from 'utils/async_client.jsx';
+import Client from 'client/web_client.jsx';
+import * as GlobalActions from 'actions/global_actions.jsx';
+
+import logoImage from 'images/logo.png';
+import ErrorBar from 'components/error_bar.jsx';
+
+import {FormattedMessage} from 'react-intl';
+import {browserHistory, Link} from 'react-router/es6';
+
+export default class SignupController extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.renderSignupControls = this.renderSignupControls.bind(this);
+
+ let loading = false;
+ let serverError = '';
+ let noOpenServerError = false;
+ let usedBefore = false;
+
+ if (props.location.query) {
+ loading = true;
+ const hash = props.location.query.h;
+
+ if (hash && hash.length > 0 && !UserStore.getCurrentUser()) {
+ usedBefore = BrowserStore.getGlobalItem(hash);
+ loading = false;
+ } else if (global.window.mm_config.EnableOpenServer !== 'true' && !UserStore.getNoAccounts()) {
+ noOpenServerError = true;
+ loading = false;
+ serverError = (
+ <FormattedMessage
+ id='signup_user_completed.no_open_server'
+ defaultMessage='This server does not allow open signups. Please speak with your Administrator to receive an invitation.'
+ />
+ );
+ }
+ }
+
+ this.state = {
+ loading,
+ serverError,
+ noOpenServerError,
+ usedBefore
+ };
+ }
+
+ componentDidMount() {
+ AsyncClient.checkVersion();
+
+ if (this.props.location.query) {
+ const hash = this.props.location.query.h;
+ const data = this.props.location.query.d;
+ const inviteId = this.props.location.query.id;
+
+ if ((inviteId && inviteId.length > 0) || (hash && hash.length > 0)) {
+ if (UserStore.getCurrentUser()) {
+ Client.addUserToTeamFromInvite(
+ data,
+ hash,
+ inviteId,
+ (team) => {
+ GlobalActions.emitInitialLoad(
+ () => {
+ browserHistory.push('/' + team.name + '/channels/town-square');
+ }
+ );
+ },
+ (err) => {
+ this.setState({ // eslint-disable-line react/no-did-mount-set-state
+ serverError: err.message
+ });
+ }
+ );
+ } else if (!this.state.usedBefore) {
+ Client.getInviteInfo(
+ inviteId,
+ (inviteData) => {
+ if (!inviteData) {
+ return;
+ }
+
+ this.setState({ // eslint-disable-line react/no-did-mount-set-state
+ serverError: '',
+ loading: false
+ });
+ },
+ () => {
+ this.setState({ // eslint-disable-line react/no-did-mount-set-state
+ noOpenServerError: true,
+ loading: false,
+ serverError: (
+ <FormattedMessage
+ id='signup_user_completed.invalid_invite'
+ defaultMessage='The invite link was invalid. Please speak with your Administrator to receive an invitation.'
+ />
+ )
+ });
+ }
+ );
+ }
+ } else if (UserStore.getCurrentUser()) {
+ browserHistory.push('/select_team');
+ } else {
+ this.setState({ // eslint-disable-line react/no-did-mount-set-state
+ loading: false
+ });
+ }
+ }
+ }
+
+ renderSignupControls() {
+ let signupControls = [];
+
+ if (global.window.mm_config.EnableSignUpWithEmail === 'true') {
+ signupControls.push(
+ <Link
+ className='btn btn-custom-login btn--full email'
+ key='email'
+ to={'/signup_email' + window.location.search}
+ >
+
+ <span className='icon fa fa-envelope'/>
+ <span>
+ <FormattedMessage
+ id='signup.email'
+ defaultMessage='Email and Password'
+ />
+ </span>
+ </Link>
+ );
+ }
+
+ if (global.window.mm_config.EnableSignUpWithGitLab === 'true') {
+ signupControls.push(
+ <a
+ className='btn btn-custom-login btn--full gitlab'
+ key='gitlab'
+ href={Client.getOAuthRoute() + '/gitlab/signup' + window.location.search}
+ >
+ <span className='icon'/>
+ <span>
+ <FormattedMessage
+ id='signup.gitlab'
+ defaultMessage='GitLab Single-Sign-On'
+ />
+ </span>
+ </a>
+ );
+ }
+
+ if (global.window.mm_config.EnableSignUpWithGoogle === 'true') {
+ signupControls.push(
+ <a
+ className='btn btn-custom-login btn--full google'
+ key='google'
+ href={Client.getOAuthRoute() + '/google/signup' + window.location.search}
+ >
+ <span className='icon'/>
+ <span>
+ <FormattedMessage
+ id='signup.google'
+ defaultMessage='Google Account'
+ />
+ </span>
+ </a>
+ );
+ }
+
+ if (global.window.mm_config.EnableSignUpWithOffice365 === 'true') {
+ signupControls.push(
+ <a
+ className='btn btn-custom-login btn--full office365'
+ key='office365'
+ href={Client.getOAuthRoute() + '/office365/signup' + window.location.search}
+ >
+ <span className='icon'/>
+ <span>
+ <FormattedMessage
+ id='signup.office365'
+ defaultMessage='Office 365'
+ />
+ </span>
+ </a>
+ );
+ }
+
+ if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_config.EnableLdap === 'true') {
+ signupControls.push(
+ <Link
+ className='btn btn-custom-login btn--full ldap'
+ key='ldap'
+ to={'/signup_ldap'}
+ >
+ <span className='icon fa fa-folder-open fa--margin-top'/>
+ <span>
+ <FormattedMessage
+ id='signup.ldap'
+ defaultMessage='LDAP Credentials'
+ />
+ </span>
+ </Link>
+ );
+ }
+
+ if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_config.EnableSaml === 'true') {
+ let query = '';
+ if (window.location.search) {
+ query = '&action=signup';
+ } else {
+ query = '?action=signup';
+ }
+
+ signupControls.push(
+ <a
+ className='btn btn-custom-login btn--full saml'
+ key='saml'
+ href={'/login/sso/saml' + window.location.search + query}
+ >
+ <span className='icon fa fa-lock fa--margin-top'/>
+ <span>
+ {global.window.mm_config.SamlLoginButtonText}
+ </span>
+ </a>
+ );
+ }
+
+ if (signupControls.length === 0) {
+ const signupDisabledError = (
+ <FormattedMessage
+ id='signup_user_completed.none'
+ defaultMessage='No user creation method has been enabled. Please contact an administrator for access.'
+ />
+ );
+ signupControls = (
+ <FormError
+ error={signupDisabledError}
+ margin={true}
+ />
+ );
+ }
+
+ return signupControls;
+ }
+
+ render() {
+ if (this.state.loading) {
+ return (<LoadingScreen/>);
+ }
+
+ if (this.state.usedBefore) {
+ return (
+ <div>
+ <FormattedMessage
+ id='signup_user_completed.expired'
+ defaultMessage="You've already completed the signup process for this invitation or this invitation has expired."
+ />
+ </div>
+ );
+ }
+
+ let signupControls = this.renderSignupControls();
+
+ let serverError = null;
+ if (this.state.serverError) {
+ serverError = (
+ <div className={'form-group has-error'}>
+ <label className='control-label'>{this.state.serverError}</label>
+ </div>
+ );
+ }
+
+ if (this.state.noOpenServerError || this.state.usedBefore) {
+ signupControls = null;
+ }
+
+ return (
+ <div>
+ <ErrorBar/>
+ <div className='signup-header'>
+ <Link to='/'>
+ <span className='fa fa-chevron-left'/>
+ <FormattedMessage
+ id='web.header.back'
+ />
+ </Link>
+ </div>
+ <div className='col-sm-12'>
+ <div className='signup-team__container'>
+ <img
+ className='signup-team-logo'
+ src={logoImage}
+ />
+ <div className='signup__content'>
+ <h1>{global.window.mm_config.SiteName}</h1>
+ <h4 className='color--light'>
+ <FormattedMessage
+ id='web.root.signup_info'
+ />
+ </h4>
+ <div className='margin--extra'>
+ <h5><strong>
+ <FormattedMessage
+ id='signup.title'
+ defaultMessage='Create an account with:'
+ />
+ </strong></h5>
+ </div>
+ {signupControls}
+ {serverError}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
+
+SignupController.propTypes = {
+ location: React.PropTypes.object
+}; \ No newline at end of file
diff --git a/webapp/components/signup_user_complete.jsx b/webapp/components/signup_user_complete.jsx
deleted file mode 100644
index 9bb208c84..000000000
--- a/webapp/components/signup_user_complete.jsx
+++ /dev/null
@@ -1,840 +0,0 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import FormError from 'components/form_error.jsx';
-import LoadingScreen from 'components/loading_screen.jsx';
-
-import * as GlobalActions from 'actions/global_actions.jsx';
-import {track} from 'actions/analytics_actions.jsx';
-
-import BrowserStore from 'stores/browser_store.jsx';
-import UserStore from 'stores/user_store.jsx';
-
-import * as Utils from 'utils/utils.jsx';
-import Client from 'client/web_client.jsx';
-import Constants from 'utils/constants.jsx';
-
-import React from 'react';
-import ReactDOM from 'react-dom';
-import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
-import {browserHistory, Link} from 'react-router/es6';
-
-import logoImage from 'images/logo.png';
-
-export default class SignupUserComplete extends React.Component {
- static get propTypes() {
- return {
- location: React.PropTypes.object
- };
- }
-
- constructor(props) {
- super(props);
-
- this.handleSubmit = this.handleSubmit.bind(this);
- this.handleLdapSignup = this.handleLdapSignup.bind(this);
-
- this.handleLdapIdChange = this.handleLdapIdChange.bind(this);
- this.handleLdapPasswordChange = this.handleLdapPasswordChange.bind(this);
-
- this.state = {
- data: '',
- hash: '',
- usedBefore: false,
- email: '',
- teamDisplayName: '',
- signupDisabledError: '',
- teamName: '',
- teamId: '',
- openServer: false,
- loading: true,
- inviteId: '',
- ldapId: '',
- ldapPassword: ''
- };
- }
-
- componentWillMount() {
- let data = this.props.location.query.d;
- let hash = this.props.location.query.h;
- const inviteId = this.props.location.query.id;
- let usedBefore = false;
- let email = '';
- let teamDisplayName = '';
- let teamName = '';
- let teamId = '';
- let openServer = false;
- let loading = true;
-
- if ((inviteId && inviteId.length > 0) || (hash && hash.length > 0)) {
- // if we are already logged in then attempt to just join the team
- if (UserStore.getCurrentUser()) {
- Client.addUserToTeamFromInvite(
- data,
- hash,
- inviteId,
- (team) => {
- loading = true;
- GlobalActions.emitInitialLoad(
- () => {
- browserHistory.push('/' + team.name + '/channels/town-square');
- }
- );
- },
- (err) => {
- this.setState({
- noOpenServerError: true,
- serverError: err.message,
- loading: false
- });
- }
- );
- } else if (hash) {
- // If we have a hash in the url then we are attempting to access a private team
- const parsedData = JSON.parse(data);
- usedBefore = BrowserStore.getGlobalItem(hash);
- email = parsedData.email;
- teamDisplayName = parsedData.display_name;
- teamName = parsedData.name;
- teamId = parsedData.id;
- loading = false;
- } else {
- loading = true;
- Client.getInviteInfo(
- inviteId,
- (inviteData) => {
- if (!inviteData) {
- return;
- }
-
- this.setState({
- serverError: null,
- teamDisplayName: inviteData.display_name,
- teamName: inviteData.name,
- teamId: inviteData.id
- });
- },
- () => {
- this.setState({
- noOpenServerError: true,
- serverError:
- <FormattedMessage
- id='signup_user_completed.invalid_invite'
- defaultMessage='The invite link was invalid. Please speak with your Administrator to receive an invitation.'
- />
- });
- }
- );
-
- loading = false;
- data = '';
- hash = '';
- }
- } else if (global.window.mm_config.EnableOpenServer === 'true' || UserStore.getNoAccounts()) {
- // If this is the first account then let them create an account anyway.
- // The server will verify it's the first account before allowing creation.
- // Of if the server is open then we don't care.
- openServer = true;
- loading = false;
- } else {
- loading = false;
- this.setState({
- noOpenServerError: true,
- serverError:
- <FormattedMessage
- id='signup_user_completed.no_open_server'
- defaultMessage='This server does not allow open signups. Please speak with your Administrator to receive an invitation.'
- />
- });
- }
-
- this.setState({
- data,
- hash,
- usedBefore,
- email,
- teamDisplayName,
- teamName,
- teamId,
- openServer,
- inviteId,
- loading
- });
-
- this.setState({
- signupDisabledError: (
- <FormattedMessage
- id='signup_user_completed.none'
- defaultMessage='No user creation method has been enabled. Please contact an administrator for access.'
- />
- )
- });
- }
-
- handleLdapSignup(e) {
- e.preventDefault();
-
- this.setState({ldapError: ''});
-
- Client.webLoginByLdap(
- this.state.ldapId,
- this.state.ldapPassword,
- null,
- () => {
- if (this.props.location.query.id || this.props.location.query.h) {
- Client.addUserToTeamFromInvite(
- this.props.location.query.d,
- this.props.location.query.h,
- this.props.location.query.id,
- () => {
- this.finishSignup();
- },
- () => {
- // there's not really a good way to deal with this, so just let the user log in like normal
- this.finishSignup();
- }
- );
-
- return;
- }
-
- this.finishSignup();
- },
- (err) => {
- if (err.id === 'ent.ldap.do_login.user_not_registered.app_error' || err.id === 'ent.ldap.do_login.user_filtered.app_error') {
- this.setState({
- ldapError: (
- <FormattedMessage
- id='login.userNotFound'
- defaultMessage="We couldn't find an account matching your login credentials."
- />
- )
- });
- } else if (err.id === 'ent.ldap.do_login.invalid_password.app_error') {
- this.setState({
- ldapError: (
- <FormattedMessage
- id='login.invalidPassword'
- defaultMessage='Your password is incorrect.'
- />
- )
- });
- } else {
- this.setState({ldapError: err.message});
- }
- }
- );
- }
-
- finishSignup() {
- GlobalActions.emitInitialLoad(
- () => {
- const query = this.props.location.query;
- GlobalActions.loadDefaultLocale();
- if (query.redirect_to) {
- browserHistory.push(query.redirect_to);
- } else {
- browserHistory.push('/select_team');
- }
- }
- );
- }
-
- handleUserCreated(user, data) {
- track('signup', 'signup_user_02_complete');
- Client.loginById(
- data.id,
- user.password,
- '',
- () => {
- if (this.state.hash > 0) {
- BrowserStore.setGlobalItem(this.state.hash, JSON.stringify({usedBefore: true}));
- }
-
- GlobalActions.emitInitialLoad(
- () => {
- const query = this.props.location.query;
- if (query.redirect_to) {
- browserHistory.push(query.redirect_to);
- } else {
- browserHistory.push('/select_team');
- }
- }
- );
- },
- (err) => {
- if (err.id === 'api.user.login.not_verified.app_error') {
- browserHistory.push('/should_verify_email?email=' + encodeURIComponent(user.email) + '&teamname=' + encodeURIComponent(this.state.teamName));
- } else {
- this.setState({serverError: err.message});
- }
- }
- );
- }
-
- handleSubmit(e) {
- e.preventDefault();
-
- const providedEmail = ReactDOM.findDOMNode(this.refs.email).value.trim();
- if (!providedEmail) {
- this.setState({
- nameError: '',
- emailError: (<FormattedMessage id='signup_user_completed.required'/>),
- passwordError: '',
- serverError: ''
- });
- return;
- }
-
- if (!Utils.isEmail(providedEmail)) {
- this.setState({
- nameError: '',
- emailError: (<FormattedMessage id='signup_user_completed.validEmail'/>),
- passwordError: '',
- serverError: ''
- });
- return;
- }
-
- const providedUsername = ReactDOM.findDOMNode(this.refs.name).value.trim().toLowerCase();
- if (!providedUsername) {
- this.setState({
- nameError: (<FormattedMessage id='signup_user_completed.required'/>),
- emailError: '',
- passwordError: '',
- serverError: ''
- });
- return;
- }
-
- const usernameError = Utils.isValidUsername(providedUsername);
- if (usernameError === 'Cannot use a reserved word as a username.') {
- this.setState({
- nameError: (<FormattedMessage id='signup_user_completed.reserved'/>),
- emailError: '',
- passwordError: '',
- serverError: ''
- });
- return;
- } else if (usernameError) {
- this.setState({
- nameError: (
- <FormattedMessage
- id='signup_user_completed.usernameLength'
- values={{
- min: Constants.MIN_USERNAME_LENGTH,
- max: Constants.MAX_USERNAME_LENGTH
- }}
- />
- ),
- emailError: '',
- passwordError: '',
- serverError: ''
- });
- return;
- }
-
- const providedPassword = ReactDOM.findDOMNode(this.refs.password).value;
- const pwdError = Utils.isValidPassword(providedPassword);
- if (pwdError != null) {
- this.setState({
- nameError: '',
- emailError: '',
- passwordError: pwdError,
- serverError: ''
- });
- }
-
- this.setState({
- nameError: '',
- emailError: '',
- passwordError: '',
- serverError: ''
- });
-
- const user = {
- email: providedEmail,
- username: providedUsername,
- password: providedPassword,
- allow_marketing: true
- };
-
- Client.createUserWithInvite(user,
- this.state.data,
- this.state.hash,
- this.state.inviteId,
- this.handleUserCreated.bind(this, user),
- (err) => {
- this.setState({serverError: err.message});
- }
- );
- }
-
- handleLdapIdChange(e) {
- e.preventDefault();
-
- this.setState({
- ldapId: e.target.value
- });
- }
-
- handleLdapPasswordChange(e) {
- e.preventDefault();
-
- this.setState({
- ldapPassword: e.target.value
- });
- }
-
- renderLdapLogin() {
- let ldapIdPlaceholder;
- if (global.window.mm_config.LdapLoginFieldName) {
- ldapIdPlaceholder = global.window.mm_config.LdapLoginFieldName;
- } else {
- ldapIdPlaceholder = Utils.localizeMessage('login.ldap_username', 'LDAP Username');
- }
-
- let errorClass = '';
- if (this.state.ldapError) {
- errorClass += ' has-error';
- }
-
- return (
- <form
- onSubmit={this.handleLdapSignup}
- >
- <div className='signup__email-container'>
- <FormError
- error={this.state.ldapError}
- margin={true}
- />
- <div className={'form-group' + errorClass}>
- <input
- className='form-control'
- name='ldapId'
- value={this.state.ldapId}
- onChange={this.handleLdapIdChange}
- placeholder={ldapIdPlaceholder}
- spellCheck='false'
- autoCapitalize='off'
- />
- </div>
- <div className={'form-group' + errorClass}>
- <input
- type='password'
- className='form-control'
- name='password'
- value={this.state.ldapPassword}
- onChange={this.handleLdapPasswordChange}
- placeholder={Utils.localizeMessage('login.password', 'Password')}
- spellCheck='false'
- />
- </div>
- <div className='form-group'>
- <button
- type='submit'
- className='btn btn-primary'
- disabled={!this.state.ldapId || !this.state.ldapPassword}
- >
- <FormattedMessage
- id='login.signIn'
- defaultMessage='Sign in'
- />
- </button>
- </div>
- </div>
- </form>
- );
- }
-
- render() {
- track('signup', 'signup_user_01_welcome');
-
- // If we have been used then just display a message
- if (this.state.usedBefore) {
- return (
- <div>
- <FormattedMessage
- id='signup_user_completed.expired'
- defaultMessage="You've already completed the signup process for this invitation or this invitation has expired."
- />
- </div>
- );
- }
-
- if (this.state.loading) {
- return (<LoadingScreen/>);
- }
-
- // set up error labels
- var emailError = null;
- var emailHelpText = (
- <span className='help-block'>
- <FormattedMessage
- id='signup_user_completed.emailHelp'
- defaultMessage='Valid email required for sign-up'
- />
- </span>
- );
- var emailDivStyle = 'form-group';
- if (this.state.emailError) {
- emailError = (<label className='control-label'>{this.state.emailError}</label>);
- emailHelpText = '';
- emailDivStyle += ' has-error';
- }
-
- var nameError = null;
- var nameHelpText = (
- <span className='help-block'>
- <FormattedMessage
- id='signup_user_completed.userHelp'
- defaultMessage="Username must begin with a letter, and contain between {min} to {max} lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'"
- values={{
- min: Constants.MIN_USERNAME_LENGTH,
- max: Constants.MAX_USERNAME_LENGTH
- }}
- />
- </span>
- );
- var nameDivStyle = 'form-group';
- if (this.state.nameError) {
- nameError = <label className='control-label'>{this.state.nameError}</label>;
- nameHelpText = '';
- nameDivStyle += ' has-error';
- }
-
- var passwordError = null;
- var passwordDivStyle = 'form-group';
- if (this.state.passwordError) {
- passwordError = <label className='control-label'>{this.state.passwordError}</label>;
- passwordDivStyle += ' has-error';
- }
-
- var serverError = null;
- if (this.state.serverError) {
- serverError = (
- <div className={'form-group has-error'}>
- <label className='control-label'>{this.state.serverError}</label>
- </div>
- );
- }
-
- // set up the email entry and hide it if an email was provided
- var yourEmailIs = '';
- if (this.state.email) {
- yourEmailIs = (
- <FormattedHTMLMessage
- id='signup_user_completed.emailIs'
- defaultMessage="Your email address is <strong>{email}</strong>. You'll use this address to sign in to {siteName}."
- values={{
- email: this.state.email,
- siteName: global.window.mm_config.SiteName
- }}
- />
- );
- }
-
- var emailContainerStyle = 'margin--extra';
- if (this.state.email) {
- emailContainerStyle = 'hidden';
- }
-
- var email = (
- <div className={emailContainerStyle}>
- <h5><strong>
- <FormattedMessage
- id='signup_user_completed.whatis'
- defaultMessage="What's your email address?"
- />
- </strong></h5>
- <div className={emailDivStyle}>
- <input
- type='email'
- ref='email'
- className='form-control'
- defaultValue={this.state.email}
- placeholder=''
- maxLength='128'
- autoFocus={true}
- spellCheck='false'
- autoCapitalize='off'
- />
- {emailError}
- {emailHelpText}
- </div>
- </div>
- );
-
- let signupMessage = [];
- if (global.window.mm_config.EnableSignUpWithGitLab === 'true') {
- signupMessage.push(
- <a
- className='btn btn-custom-login gitlab'
- key='gitlab'
- href={Client.getOAuthRoute() + '/gitlab/signup' + window.location.search}
- >
- <span className='icon'/>
- <span>
- <FormattedMessage
- id='signup_user_completed.gitlab'
- defaultMessage='with GitLab'
- />
- </span>
- </a>
- );
- }
-
- if (global.window.mm_config.EnableSignUpWithGoogle === 'true') {
- signupMessage.push(
- <a
- className='btn btn-custom-login google'
- key='google'
- href={Client.getOAuthRoute() + '/google/signup' + window.location.search}
- >
- <span className='icon'/>
- <span>
- <FormattedMessage
- id='signup_user_completed.google'
- defaultMessage='with Google'
- />
- </span>
- </a>
- );
- }
-
- if (global.window.mm_config.EnableSignUpWithOffice365 === 'true') {
- signupMessage.push(
- <a
- className='btn btn-custom-login office365'
- key='office365'
- href={Client.getOAuthRoute() + '/office365/signup' + window.location.search}
- >
- <span className='icon'/>
- <span>
- <FormattedMessage
- id='signup_user_completed.office365'
- defaultMessage='with Office 365'
- />
- </span>
- </a>
- );
- }
-
- if (global.window.mm_config.EnableSaml === 'true' && global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.SAML === 'true') {
- signupMessage.push(
- <a
- className='btn btn-custom-login saml'
- key='saml'
- href={`/login/sso/saml${window.location.search}${window.location.search ? '&' : '?'}action=signup`}
- >
- <span>
- {global.window.mm_config.SamlLoginButtonText}
- </span>
- </a>
- );
- }
-
- let ldapSignup;
- if (global.window.mm_config.EnableLdap === 'true' && global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.LDAP) {
- ldapSignup = (
- <div className='inner__content'>
- <h5>
- <strong>
- <FormattedMessage
- id='signup_user_completed.withLdap'
- defaultMessage='With your LDAP credentials'
- />
- </strong>
- </h5>
- {this.renderLdapLogin()}
- </div>
- );
- }
-
- let emailSignup;
- if (global.window.mm_config.EnableSignUpWithEmail === 'true') {
- emailSignup = (
- <form>
- <div className='inner__content'>
- {email}
- {yourEmailIs}
- <div className='margin--extra'>
- <h5><strong>
- <FormattedMessage
- id='signup_user_completed.chooseUser'
- defaultMessage='Choose your username'
- />
- </strong></h5>
- <div className={nameDivStyle}>
- <input
- type='text'
- ref='name'
- className='form-control'
- placeholder=''
- maxLength={Constants.MAX_USERNAME_LENGTH}
- spellCheck='false'
- autoCapitalize='off'
- />
- {nameError}
- {nameHelpText}
- </div>
- </div>
- <div className='margin--extra'>
- <h5><strong>
- <FormattedMessage
- id='signup_user_completed.choosePwd'
- defaultMessage='Choose your password'
- />
- </strong></h5>
- <div className={passwordDivStyle}>
- <input
- type='password'
- ref='password'
- className='form-control'
- placeholder=''
- maxLength='128'
- spellCheck='false'
- />
- {passwordError}
- </div>
- </div>
- <p className='margin--extra'>
- <button
- type='submit'
- onClick={this.handleSubmit}
- className='btn-primary btn'
- >
- <FormattedMessage
- id='signup_user_completed.create'
- defaultMessage='Create Account'
- />
- </button>
- </p>
- </div>
- </form>
- );
- }
-
- if (signupMessage.length > 0 && (emailSignup || ldapSignup)) {
- signupMessage = (
- <div>
- {signupMessage}
- <div className='or__container'>
- <FormattedMessage
- id='signup_user_completed.or'
- defaultMessage='or'
- />
- </div>
- </div>
- );
- }
-
- if (ldapSignup && emailSignup) {
- ldapSignup = (
- <div>
- {ldapSignup}
- <div className='or__container'>
- <FormattedMessage
- id='signup_user_completed.or'
- defaultMessage='or'
- />
- </div>
- </div>
- );
- }
-
- let terms = null;
- if (!this.state.noOpenServerError && (emailSignup || ldapSignup)) {
- terms = (
- <p>
- <FormattedHTMLMessage
- id='create_team.agreement'
- defaultMessage="By proceeding to create your account and use {siteName}, you agree to our <a href='/static/help/terms.html'>Terms of Service</a> and <a href='/static/help/privacy.html'>Privacy Policy</a>. If you do not agree, you cannot use {siteName}."
- values={{
- siteName: global.window.mm_config.SiteName
- }}
- />
- </p>
- );
- }
-
- if (signupMessage.length === 0 && !emailSignup && !ldapSignup) {
- emailSignup = (
- <FormError
- error={this.state.signupDisabledError}
- margin={true}
- />
- );
- }
-
- if (this.state.noOpenServerError) {
- signupMessage = null;
- emailSignup = null;
- ldapSignup = null;
- }
-
- let description = null;
- if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true' && global.window.mm_config.EnableCustomBrand === 'true') {
- description = global.window.mm_config.CustomDescriptionText;
- } else {
- description = (
- <FormattedMessage
- id='web.root.signup_info'
- defaultMessage='All team communication in one place, searchable and accessible anywhere'
- />
- );
- }
-
- return (
- <div>
- <div className='signup-header'>
- <Link to='/'>
- <span className='fa fa-chevron-left'/>
- <FormattedMessage
- id='web.header.back'
- />
- </Link>
- </div>
- <div className='col-sm-12'>
- <div className='signup-team__container padding--less'>
- <img
- className='signup-team-logo'
- src={logoImage}
- />
- <h1>{global.window.mm_config.SiteName}</h1>
- <h4 className='color--light'>
- {description}
- </h4>
- <h4 className='color--light'>
- <FormattedMessage
- id='signup_user_completed.lets'
- defaultMessage="Let's create your account"
- />
- </h4>
- <span className='color--light'>
- <FormattedMessage
- id='signup_user_completed.haveAccount'
- defaultMessage='Already have an account?'
- />
- {' '}
- <Link
- to={'/login'}
- query={this.props.location.query}
- >
- <FormattedMessage
- id='signup_user_completed.signIn'
- defaultMessage='Click here to sign in.'
- />
- </Link>
- </span>
- {signupMessage}
- {ldapSignup}
- {emailSignup}
- {serverError}
- {terms}
- </div>
- </div>
- </div>
- );
- }
-}
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index b26e33cd6..5c636716b 100644
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -1597,6 +1597,12 @@
"sidebar_right_menu.switch_team": "Team Selection",
"sidebar_right_menu.teamLink": "Get Team Invite Link",
"sidebar_right_menu.teamSettings": "Team Settings",
+ "signup.title": "Create an account with:",
+ "signup.ldap": "LDAP Credentials",
+ "signup.google": "Google Account",
+ "signup.office365": "Office 365",
+ "signup.gitlab": "GitLab Single-Sign-On",
+ "signup.email": "Email and Password",
"signup_team.choose": "Your teams: ",
"signup_team.createTeam": "Or Create a Team",
"signup_team.disabled": "Team creation has been disabled. Please contact an administrator for access.",
diff --git a/webapp/routes/route_root.jsx b/webapp/routes/route_root.jsx
index 52eb5c757..9d64c6012 100644
--- a/webapp/routes/route_root.jsx
+++ b/webapp/routes/route_root.jsx
@@ -66,7 +66,19 @@ export default {
{
path: 'signup_user_complete',
getComponents: (location, callback) => {
- System.import('components/signup_user_complete.jsx').then(RouteUtils.importComponentSuccess(callback));
+ System.import('components/signup/signup_controller.jsx').then(RouteUtils.importComponentSuccess(callback));
+ }
+ },
+ {
+ path: 'signup_email',
+ getComponents: (location, callback) => {
+ System.import('components/signup/components/signup_email.jsx').then(RouteUtils.importComponentSuccess(callback));
+ }
+ },
+ {
+ path: 'signup_ldap',
+ getComponents: (location, callback) => {
+ System.import('components/signup/components/signup_ldap.jsx').then(RouteUtils.importComponentSuccess(callback));
}
},
{
diff --git a/webapp/sass/routes/_signup.scss b/webapp/sass/routes/_signup.scss
index 8315f8890..106cdc372 100644
--- a/webapp/sass/routes/_signup.scss
+++ b/webapp/sass/routes/_signup.scss
@@ -203,6 +203,11 @@
.fa {
font-size: 17px;
margin-right: 8px;
+
+ &.fa--margin-top {
+ position: relative;
+ top: 2px;
+ }
}
.icon {
@@ -210,6 +215,7 @@
display: inline-block;
height: 18px;
margin-right: 8px;
+ text-align: center;
width: 18px;
}
@@ -218,10 +224,11 @@
color: $white;
display: block;
height: 40px;
- line-height: 34px;
+ line-height: 36px;
margin: 1em 0;
min-width: 200px;
- padding: 0 1em;
+ padding: 0 1em 0 2em;
+ text-align: left;
width: 200px;
&.gitlab {
@@ -268,16 +275,15 @@
}
.icon {
- margin-left:-10px;
background-image: url('../images/office365Logo.png');
}
}
&.ldap {
- background: #dd4b39;
+ background: #3AA1CF;
&:hover {
- background: darken(#dd4b39, 10%);
+ background: darken(#3AA1CF, 10%);
}
span {
@@ -298,10 +304,10 @@
}
&.saml {
- background: #dd4b39;
+ background: #34a28b;
&:hover {
- background: darken(#dd4b39, 10%);
+ background: darken(#34a28b, 10%);
}
span {
@@ -309,11 +315,16 @@
}
}
- &.btn-full {
+ &.btn--full {
+ max-width: 350px;
padding-left: 35px;
text-align: left;
width: 100%;
}
+
+ &.btn--large {
+ width: 300px;
+ }
}
&.btn-default {
@@ -502,4 +513,4 @@
.verify_panel {
margin: 60px auto auto;
max-width: 380px;
-}
+} \ No newline at end of file