// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); var BrowserStore = require('../stores/browser_store.jsx'); var constants = require('../utils/constants.jsx'); WelcomePage = React.createClass({ submitNext: function (e) { if (!BrowserStore.isLocalStorageSupported()) { this.setState({ storage_error: "This service requires local storage to be enabled. Please enable it or exit private browsing."} ); return; } e.preventDefault(); this.props.state.wizard = "team_display_name"; this.props.updateParent(this.props.state); }, handleDiffEmail: function (e) { e.preventDefault(); this.setState({ use_diff: true }); }, handleDiffSubmit: function (e) { e.preventDefault(); var state = { use_diff: true, server_error: "" }; var email = this.refs.email.getDOMNode().value.trim().toLowerCase(); if (!email || !utils.isEmail(email)) { state.email_error = "Please enter a valid email address"; this.setState(state); return; } else if (!BrowserStore.isLocalStorageSupported()) { state.email_error = "This service requires local storage to be enabled. Please enable it or exit private browsing."; this.setState(state); return; } else { state.email_error = ""; } client.signupTeam(email, function(data) { if (data["follow_link"]) { window.location.href = data["follow_link"]; } else { this.props.state.wizard = "finished"; this.props.updateParent(this.props.state); window.location.href = "/signup_team_confirm/?email=" + encodeURIComponent(team.email); } }.bind(this), function(err) { this.state.server_error = err.message; this.setState(this.state); }.bind(this) ); }, getInitialState: function() { return { use_diff: false }; }, handleKeyPress: function(event) { if (event.keyCode == 13) { this.submitNext(event); } }, componentWillMount: function() { document.addEventListener("keyup", this.handleKeyPress, false); }, componentWillUnmount: function() { document.removeEventListener("keyup", this.handleKeyPress, false); }, render: function() { client.track('signup', 'signup_team_01_welcome'); var storage_error = this.state.storage_error ? : null; var email_error = this.state.email_error ? : null; var server_error = this.state.server_error ?
: null; return (

Welcome to:

{config.SiteName}

Let's setup your new team

Please confirm your email address:

{ this.props.state.team.email }

Your account will administer the new team site.
You can add other administrators later.

{ storage_error }

{ email_error }
{ server_error }
Use a different email
); } }); TeamDisplayNamePage = React.createClass({ submitBack: function (e) { e.preventDefault(); this.props.state.wizard = "welcome"; this.props.updateParent(this.props.state); }, submitNext: function (e) { e.preventDefault(); var display_name = this.refs.name.getDOMNode().value.trim(); if (!display_name) { this.setState({name_error: "This field is required"}); return; } this.props.state.wizard = "team_url"; this.props.state.team.display_name = display_name; this.props.state.team.name = utils.cleanUpUrlable(display_name); this.props.updateParent(this.props.state); }, getInitialState: function() { return { }; }, handleFocus: function(e) { e.preventDefault(); e.currentTarget.select(); }, render: function() { client.track('signup', 'signup_team_02_name'); var name_error = this.state.name_error ? : null; return (

{utils.toTitleCase(strings.Team) + " Name"}

{ name_error }
{"Name your " + strings.Team + " in any language. Your " + strings.Team + " name shows in menus and headings."}
Back to previous step
); } }); TeamURLPage = React.createClass({ submitBack: function (e) { e.preventDefault(); this.props.state.wizard = "team_display_name"; this.props.updateParent(this.props.state); }, submitNext: function (e) { e.preventDefault(); var name = this.refs.name.getDOMNode().value.trim(); if (!name) { this.setState({name_error: "This field is required"}); return; } var cleaned_name = utils.cleanUpUrlable(name); var urlRegex = /^[a-z0-9]+([a-z\-0-9]+|(__)?)[a-z0-9]+$/g; if (cleaned_name != name || !urlRegex.test(name)) { this.setState({name_error: "Must be lowercase alphanumeric characters"}); return; } else if (cleaned_name.length <= 3 || cleaned_name.length > 15) { this.setState({name_error: "Name must be 4 or more characters up to a maximum of 15"}) return; } for (var index = 0; index < constants.RESERVED_TEAM_NAMES.length; index++) { if (cleaned_name.indexOf(constants.RESERVED_TEAM_NAMES[index]) == 0) { this.setState({name_error: "This team name is unavailable"}) return; } } client.findTeamByName(name, function(data) { if (!data) { if (config.AllowSignupDomainsWizard) { this.props.state.wizard = "allowed_domains"; } else { this.props.state.wizard = "send_invites"; this.props.state.team.type = 'O'; } this.props.state.team.name = name; this.props.updateParent(this.props.state); } else { this.state.name_error = "This URL is unavailable. Please try another."; this.setState(this.state); } }.bind(this), function(err) { this.state.name_error = err.message; this.setState(this.state); }.bind(this) ); }, getInitialState: function() { return { }; }, handleFocus: function(e) { e.preventDefault(); e.currentTarget.select(); }, render: function() { client.track('signup', 'signup_team_03_url'); var name_error = this.state.name_error ? : null; return (

{utils.toTitleCase(strings.Team) + " URL"}

{ utils.getWindowLocationOrigin() + "/" }
{ name_error }

{"Choose the web address of your new " + strings.Team + ":"}

Back to previous step
); } }); AllowedDomainsPage = React.createClass({ submitBack: function (e) { e.preventDefault(); this.props.state.wizard = "team_url"; this.props.updateParent(this.props.state); }, submitNext: function (e) { e.preventDefault(); if (this.refs.open_network.getDOMNode().checked) { this.props.state.wizard = "send_invites"; this.props.state.team.type = 'O'; this.props.updateParent(this.props.state); return; } if (this.refs.allow.getDOMNode().checked) { var name = this.refs.name.getDOMNode().value.trim(); var domainRegex = /^\w+\.\w+$/ if (!name) { this.setState({name_error: "This field is required"}); return; } if(!name.trim().match(domainRegex)) { this.setState({name_error: "The domain doesn't appear valid"}); return; } this.props.state.wizard = "send_invites"; this.props.state.team.allowed_domains = name; this.props.state.team.type = 'I'; this.props.updateParent(this.props.state); } else { this.props.state.wizard = "send_invites"; this.props.state.team.type = 'I'; this.props.updateParent(this.props.state); } }, getInitialState: function() { return { }; }, render: function() { client.track('signup', 'signup_team_04_allow_domains'); var name_error = this.state.name_error ? : null; return (

Email Domain

{"Check this box to allow your " + strings.Team + " members to sign up using their " + strings.Company + " email addresses if you share the same domain--otherwise, you need to invite everyone yourself."}

{"Your " + strings.Team + "'s domain for emails"}

@
{ name_error }

To allow signups from multiple domains, separate each with a comma.

 
); } }); EmailItem = React.createClass({ getInitialState: function() { return { }; }, getValue: function() { return this.refs.email.getDOMNode().value.trim() }, validate: function(teamEmail) { var email = this.refs.email.getDOMNode().value.trim().toLowerCase(); if (!email) { return true; } if (!utils.isEmail(email)) { this.state.email_error = "Please enter a valid email address"; this.setState(this.state); return false; } else if (email === teamEmail) { this.state.email_error = "Please use a different email than the one used at signup"; this.setState(this.state); return false; } else { this.state.email_error = ""; this.setState(this.state); return true; } }, render: function() { var email_error = this.state.email_error ? : null; return (
{ email_error }
); } }); SendInivtesPage = React.createClass({ submitBack: function (e) { e.preventDefault(); if (config.AllowSignupDomainsWizard) { this.props.state.wizard = "allowed_domains"; } else { this.props.state.wizard = "team_url"; } this.props.updateParent(this.props.state); }, submitNext: function (e) { e.preventDefault(); var valid = true; var emails = []; for (var i = 0; i < this.props.state.invites.length; i++) { if (!this.refs['email_' + i].validate(this.props.state.team.email)) { valid = false; } else { emails.push(this.refs['email_' + i].getValue()); } } if (!valid) { return; } this.props.state.wizard = "username"; this.props.state.invites = emails; this.props.updateParent(this.props.state); }, submitAddInvite: function (e) { e.preventDefault(); this.props.state.wizard = "send_invites"; if (this.props.state.invites == null || this.props.state.invites.length == 0) { this.props.state.invites = []; } this.props.state.invites.push(""); this.props.updateParent(this.props.state); }, submitSkip: function (e) { e.preventDefault(); this.props.state.wizard = "username"; this.props.updateParent(this.props.state); }, getInitialState: function() { return { }; }, render: function() { client.track('signup', 'signup_team_05_send_invites'); var name_error = this.state.name_error ? : null; var emails = []; for (var i = 0; i < this.props.state.invites.length; i++) { if (i == 0) { emails.push(); } else { emails.push(); } } return (

{"Invite " + utils.toTitleCase(strings.Team) + " Members"}

{ emails }
Add Invitation

{"if you prefer, you can invite " + strings.Team + " members later"}
and skip this step for now.

Back to previous step
); } }); UsernamePage = React.createClass({ submitBack: function (e) { e.preventDefault(); this.props.state.wizard = "send_invites"; this.props.updateParent(this.props.state); }, submitNext: function (e) { e.preventDefault(); var name = this.refs.name.getDOMNode().value.trim(); var username_error = utils.isValidUsername(name); if (username_error === "Cannot use a reserved word as a username.") { this.setState({name_error: "This username is reserved, please choose a new one." }); return; } else if (username_error) { this.setState({name_error: "Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'." }); return; } this.props.state.wizard = "password"; this.props.state.user.username = name; this.props.updateParent(this.props.state); }, getInitialState: function() { return { }; }, render: function() { client.track('signup', 'signup_team_06_username'); var name_error = this.state.name_error ? : null; return (

Your username

{"Select a memorable username that makes it easy for " + strings.Team + "mates to identify you:"}
Choose your username
Usernames must begin with a letter and contain 3 to 15 characters made up of lowercase letters, numbers, and the symbols '.', '-' and '_'
{ name_error }
Back to previous step
); } }); PasswordPage = React.createClass({ submitBack: function (e) { e.preventDefault(); this.props.state.wizard = "username"; this.props.updateParent(this.props.state); }, submitNext: function (e) { e.preventDefault(); var password = this.refs.password.getDOMNode().value.trim(); if (!password || password.length < 5) { this.setState({password_error: "Please enter at least 5 characters"}); return; } this.setState({password_error: null, server_error: null}); $('#finish-button').button('loading'); var teamSignup = JSON.parse(JSON.stringify(this.props.state)); teamSignup.user.password = password; teamSignup.user.allow_marketing = true; delete teamSignup.wizard; var ctl = this; client.createTeamFromSignup(teamSignup, function(data) { client.track('signup', 'signup_team_08_complete'); var props = this.props; setTimeout(function() { $('#sign-up-button').button('reset'); props.state.wizard = "finished"; props.updateParent(props.state, true); window.location.href = utils.getWindowLocationOrigin() + '/' + props.state.team.name + '/login?email=' + encodeURIComponent(teamSignup.team.email); // client.loginByEmail(teamSignup.team.domain, teamSignup.team.email, teamSignup.user.password, // function(data) { // TeamStore.setLastName(teamSignup.team.domain); // UserStore.setLastEmail(teamSignup.team.email); // UserStore.setCurrentUser(data); // window.location.href = '/channels/town-square'; // }.bind(ctl), // function(err) { // this.setState({name_error: err.message}); // }.bind(ctl) // ); }, 5000); }.bind(this), function(err) { this.setState({server_error: err.message}); $('#sign-up-button').button('reset'); }.bind(this) ); }, getInitialState: function() { return { }; }, render: function() { client.track('signup', 'signup_team_07_password'); var password_error = this.state.password_error ? : null; var server_error = this.state.server_error ? : null; return (

Your password

Select a password that you'll use to login with your email address:
Email
{this.props.state.team.email}
Choose your password
Passwords must contain 5 to 50 characters. Your password will be strongest if it contains a mix of symbols, numbers, and upper and lowercase characters.
{ password_error } { server_error }

By proceeding to create your account and use { config.SiteName }, you agree to our Terms of Service and Privacy Policy. If you do not agree, you cannot use {config.SiteName}.

Back to previous step
); } }); module.exports = React.createClass({ updateParent: function(state, skipSet) { BrowserStore.setGlobalItem(this.props.hash, state); if (!skipSet) { this.setState(state); } }, getInitialState: function() { var props = BrowserStore.getGlobalItem(this.props.hash); if (!props) { props = {}; props.wizard = "welcome"; props.team = {}; props.team.email = this.props.email; props.team.allowed_domains = ""; props.invites = []; props.invites.push(""); props.invites.push(""); props.invites.push(""); props.user = {}; props.hash = this.props.hash; props.data = this.props.data; } return props; }, render: function() { if (this.state.wizard == "welcome") { return } if (this.state.wizard == "team_display_name") { return } if (this.state.wizard == "team_url") { return } if (this.state.wizard == "allowed_domains") { return } if (this.state.wizard == "send_invites") { return } if (this.state.wizard == "username") { return } if (this.state.wizard == "password") { return } return (
You've already completed the signup process for this invitation or this invitation has expired.
); } });