summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--STYLE-GUIDE.md167
-rw-r--r--api/team.go7
-rw-r--r--web/react/.eslintrc139
-rw-r--r--web/react/components/delete_post_modal.jsx2
-rw-r--r--web/react/components/file_preview.jsx2
-rw-r--r--web/react/components/login.jsx14
-rw-r--r--web/react/components/post_body.jsx4
-rw-r--r--web/react/components/post_right.jsx4
-rw-r--r--web/react/components/sidebar_header.jsx4
-rw-r--r--web/react/components/signup_team.jsx20
-rw-r--r--web/react/components/signup_team_complete.jsx144
-rw-r--r--web/react/components/signup_user_complete.jsx52
-rw-r--r--web/react/components/view_image.jsx6
-rw-r--r--web/react/package.json4
-rw-r--r--web/react/pages/signup_team_complete.jsx4
-rw-r--r--web/react/pages/signup_user_complete.jsx2
-rw-r--r--web/react/stores/team_store.jsx8
-rw-r--r--web/react/utils/client.jsx4
-rw-r--r--web/react/utils/utils.jsx11
-rw-r--r--web/sass-files/sass/partials/_responsive.scss6
-rw-r--r--web/sass-files/sass/partials/_signup.scss151
-rw-r--r--web/templates/signup_team.html4
-rw-r--r--web/templates/signup_team_complete.html2
-rw-r--r--web/templates/signup_user_complete.html2
-rw-r--r--web/web.go1
26 files changed, 597 insertions, 176 deletions
diff --git a/Makefile b/Makefile
index 222d4ffe4..14a6ffc7d 100644
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@ GOFLAGS ?= $(GOFLAGS:)
BUILD_NUMBER ?= $(BUILD_NUMBER:)
GO=$(GOPATH)/bin/godep go
+ESLINT=web/react/node_modules/eslint/bin/eslint.js
ifeq ($(BUILD_NUMBER),)
BUILD_NUMBER := dev
@@ -62,6 +63,14 @@ install:
@cd web/react/ && npm install
+check: install
+ @echo Running ESLint...
+ @$(ESLINT) web/react/components/*
+ @$(ESLINT) web/react/dispatcher/*
+ @$(ESLINT) web/react/pages/*
+ @$(ESLINT) web/react/stores/*
+ @$(ESLINT) web/react/utils/*
+
test: install
@mkdir -p logs
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1
diff --git a/STYLE-GUIDE.md b/STYLE-GUIDE.md
new file mode 100644
index 000000000..e3fe2addf
--- /dev/null
+++ b/STYLE-GUIDE.md
@@ -0,0 +1,167 @@
+# Mattermost Style Guide
+
+1. [GO](#go)
+2. [Javascript](#javascript)
+3. [React-JSX](#react-jsx)
+
+
+## Go
+
+All go code must follow the golang official [Style Guide](https://golang.org/doc/effective_go.html)
+
+In addition all code must be run though the official go formatter tool [gofmt](https://golang.org/cmd/gofmt/)
+
+
+## Javascript
+
+Part of the build process is running ESLint. ESLint is the final authority on all style issues. PRs will not be accepted unless there are no errors or warnings running ESLint. The ESLint configuration file can be found in: [web/react/.eslintrc](https://github.com/mattermost/platform/blob/master/web/react/.eslintrc.json)
+
+Instructions on how to use ESLint with your favourite editor can be found here: [http://eslint.org/docs/user-guide/integrations](http://eslint.org/docs/user-guide/integrations)
+
+The following is an abridged version of the [Airbnb Javascript Style Guide](https://github.com/airbnb/javascript/blob/master/README.md#airbnb-javascript-style-guide-), with modifications. Anything that is unclear here follow that guide. If there is a conflict, follow what is said below.
+
+### Whitespace
+
+- Indentation is four spaces
+- Use a space before the leading brace
+- Use one space between the comma and the next argument in a bracketed list. No other space.
+- Use whitespace to make code more readable.
+- Do not use more than one newline to separate code blocks.
+- Do not use a newline as the first line of a function
+
+```javascript
+// Correct
+function myFunction(parm1, parm2) {
+ stuff...;
+
+ morestuff;
+}
+
+// Incorrect
+function myFunction ( parm1, parm2 ){
+ stuff...;
+
+
+ morestuff;
+}
+
+```
+
+### Semicolons
+
+- You must use them always
+
+```javascript
+// Correct
+var x = 1;
+
+// Incorrect
+var x = 1
+```
+
+### Variables
+
+- Declarations must always use var, let or const.
+- Prefer let or const over var.
+- camelCase for all variable names.
+
+```javascript
+// Correct
+let myVariable = 4;
+
+// OK
+var myVariable = 4;
+
+// Incorrect
+myVariable = 4;
+var my_variable = 4;
+```
+
+### Blocks
+
+- Braces must be used on all blocks.
+- Braces must start on the same line as the statement starting the block.
+- Else and else if must be on the same line as the if block closing brace.
+
+```javascript
+// Correct
+if (somthing) {
+ stuff...;
+} else if (otherthing) {
+ stuff...;
+}
+
+// Incorrect
+if (somthing)
+{
+ stuff...;
+}
+else
+{
+ stuff...;
+}
+
+// Incorrect
+if (somthing) stuff...;
+if (somthing)
+ stuff...;
+
+```
+
+### Strings
+
+- Use template strings instead of concatenation.
+
+```javascript
+// Correct
+function getStr(stuff) {
+ return "This is the ${stuff} string";
+}
+
+// Incorrect
+function wrongGetStr(stuff) {
+ return "This is the " + stuff + " string";
+}
+```
+
+## React-JSX
+
+Part of the build process is running ESLint. ESLint is the final authority on all style issues. PRs will not be accepted unless there are no errors or warnings running ESLint. The ESLint configuration file can be found in: [web/react/.eslintrc](https://github.com/mattermost/platform/blob/master/web/react/.eslintrc.json)
+
+Instructions on how to use ESLint with your favourite editor can be found here: [http://eslint.org/docs/user-guide/integrations](http://eslint.org/docs/user-guide/integrations)
+
+This is an abridged version of the [Airbnb React/JSX Style Guide](https://github.com/airbnb/javascript/tree/master/react#airbnb-reactjsx-style-guide). Anything that is unclear here follow that guide. If there is a conflict, follow what is said below.
+
+### General
+
+- Include only one React component per file.
+- Use class \<name\> extends React.Component over React.createClass unless you need mixins
+- CapitalCamelCase with .jsx extension for component filenames.
+- Filenames should be the component name.
+
+### Alignment
+
+- Follow alignment styles shown below:
+```xml
+// Correct
+<Tag
+ propertyOne="1"
+ propertyTwo="2"
+>
+ <Child />
+</Tag>
+
+// Correct
+<Tag propertyOne="1" />
+```
+
+### Naming
+
+- Property names use camelCase.
+- React component names use CapitalCamelCase.
+- Do not use an understore for internal methods in a react component.
+
+```xml
+// Correct
+<ReactComponent propertyOne="value" />
+```
diff --git a/api/team.go b/api/team.go
index 1145e6e81..c9fe42ecc 100644
--- a/api/team.go
+++ b/api/team.go
@@ -35,25 +35,18 @@ func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
m := model.MapFromJson(r.Body)
email := strings.ToLower(strings.TrimSpace(m["email"]))
- displayName := strings.TrimSpace(m["display_name"])
if len(email) == 0 {
c.SetInvalidParam("signupTeam", "email")
return
}
- if len(displayName) == 0 {
- c.SetInvalidParam("signupTeam", "display_name")
- return
- }
-
subjectPage := NewServerTemplatePage("signup_team_subject", c.GetSiteURL())
bodyPage := NewServerTemplatePage("signup_team_body", c.GetSiteURL())
bodyPage.Props["TourUrl"] = utils.Cfg.TeamSettings.TourLink
props := make(map[string]string)
props["email"] = email
- props["display_name"] = displayName
props["time"] = fmt.Sprintf("%v", model.GetMillis())
data := model.MapToJson(props)
diff --git a/web/react/.eslintrc b/web/react/.eslintrc
new file mode 100644
index 000000000..d8b36f6ca
--- /dev/null
+++ b/web/react/.eslintrc
@@ -0,0 +1,139 @@
+{
+ "ecmaFeatures": {
+ "jsx": true,
+ "blockBindings": true,
+ "modules": true
+ },
+ "plugins": [
+ "react"
+ ],
+ "env": {
+ "browser": true,
+ "node": true,
+ "jquery": true,
+ "es6": true
+ },
+ "globals": {
+ "React": false
+ },
+ "rules": {
+ "comma-dangle": [2, "never"],
+ "no-cond-assign": [2, "except-parens"],
+ "no-console": 1,
+ "no-constant-condition": 1,
+ "no-debugger": 1,
+ "no-dupe-args": 2,
+ "no-dupe-keys": 2,
+ "no-duplicate-case": 2,
+ "no-empty": 1,
+ "no-ex-assign": 1,
+ "no-extra-semi": 2,
+ "no-func-assign": 1,
+ "no-inner-declarations": 0,
+ "no-invalid-regexp": 2,
+ "no-irregular-whitespace": 2,
+ "no-unreachable": 2,
+ "valid-typeof": 2,
+ "no-unexpected-multiline": 2,
+
+ "block-scoped-var": 1,
+ "complexity": [1, 8],
+ "consistent-return": 2,
+ "curly": [2, "all"],
+ "dot-notation": 2,
+ "dot-location": [2, "object"],
+ "eqeqeq": [2, "smart"],
+ "guard-for-in": 1,
+ "no-alert": 1,
+ "no-caller": 2,
+ "no-div-regex": 1,
+ "no-else-return": 1,
+ "no-eval": 2,
+ "no-extend-native": 2,
+ "no-floating-decimal": 2,
+ "no-labels": 2,
+ "no-lone-blocks": 1,
+ "no-multi-spaces": [2, { "exceptions": { "Property": false } }],
+ "no-multi-str": 0,
+ "no-param-reassign": 2,
+ "no-process-env": 2,
+ "no-redeclare": 2,
+ "no-return-assign": [2, "always"],
+ "no-script-url": 2,
+ "no-self-compare": 2,
+ "no-sequences": 2,
+ "no-throw-literal": 2,
+ "no-unused-expressions": 2,
+ "no-void": 2,
+ "no-warning-comments": 0,
+ "no-with": 2,
+ "radix": 2,
+ "vars-on-top": 0,
+ "wrap-iife": [2, "outside"],
+ "yoda": [2, "never", {"exceptRange": false, "onlyEquality": false}],
+
+ "no-undefined": 2,
+ "no-shadow": [2, {"hoist": "functions"}],
+ "no-unused-vars": [2, {"vars": "all", "args": "all"}],
+ "no-use-before-define": [2, "nofunc"],
+
+ // Style
+ "array-bracket-spacing": [2, "never"],
+ "brace-style": [2, "1tbs", { "allowSingleLine": false }],
+ "camelcase": [2, {"properties": "always"}],
+ "comma-spacing": [2, {"before": false, "after": true}],
+ "comma-style": [2, "last"],
+ "computed-property-spacing": [2, "never"],
+ "consistent-this": [2, "self"],
+ "func-names": 2,
+ "func-style": [2, "declaration"],
+ "indent": [2, 4, {"indentSwitchCase": false}],
+ "key-spacing": [2, {"beforeColon": false, "afterColon": true}],
+ "lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }],
+ "linebreak-style": 2,
+ "new-cap": 2,
+ "new-parens": 2,
+ "no-lonely-if": 2,
+ "no-mixed-spaces-and-tabs": 2,
+ "no-multiple-empty-lines": [2, {"max": 1}],
+ "no-spaced-func": 2,
+ "no-ternary": 2,
+ "no-trailing-spaces": [2, { "skipBlankLines": false }],
+ "no-underscore-dangle": 2,
+ "no-unneeded-ternary": 2,
+ "object-curly-spacing": [2, "never"],
+ "one-var": [2, "never"],
+ "operator-linebreak": [2, "after"],
+ "padded-blocks": [2, "never"],
+ "quote-props": [2, "as-needed"],
+ "quotes": [2, "single", "avoid-escape"],
+ "semi-spacing": [2, {"before": false, "after": true}],
+ "semi": [2, "always"],
+ "space-after-keywords": [2, "always"],
+ "space-before-blocks": [2, "always"],
+ "space-before-function-paren": [2, "never"],
+ "space-in-parens": [2, "never"],
+ "space-infix-ops": 2,
+ "space-return-throw-case": 2,
+ "space-unary-ops": [2, { "words": true, "nonwords": false }],
+ "wrap-regex": 2,
+
+ // React Specific
+ "react/display-name": [2, { "acceptTranspilerName": true }],
+ "react/jsx-boolean-value": [2, "always"],
+ "react/jsx-curly-spacing": [2, "never"],
+ "react/jsx-no-duplicate-props": [2, { "ignoreCase": false }],
+ "react/jsx-no-undef": 2,
+ "react/jsx-quotes": [2, "single", "avoid-escape"],
+ "react/jsx-uses-react": 2,
+ "react/jsx-uses-vars": 2,
+ "react/no-danger": 0,
+ "react/no-did-mount-set-state": 2,
+ "react/no-did-update-set-state": 2,
+ "react/no-multi-comp": 2,
+ "react/no-unknown-property": 2,
+ "react/prop-types": 2,
+ "react/sort-comp": 0,
+ "react/wrap-multilines": 2
+ }
+}
diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx
index 11970bc2b..f0cb809af 100644
--- a/web/react/components/delete_post_modal.jsx
+++ b/web/react/components/delete_post_modal.jsx
@@ -98,7 +98,7 @@ module.exports = React.createClass({
: "" }
</div>
<div className="modal-footer">
- <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
+ <button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" className="btn btn-danger" data-dismiss="modal" onClick={this.handleDelete}>Delete</button>
</div>
</div>
diff --git a/web/react/components/file_preview.jsx b/web/react/components/file_preview.jsx
index fdd12feec..7c1db3e10 100644
--- a/web/react/components/file_preview.jsx
+++ b/web/react/components/file_preview.jsx
@@ -24,7 +24,7 @@ module.exports = React.createClass({
if (filename.indexOf("/api/v1/files/get") != -1) {
filename = filename.split("/api/v1/files/get")[1];
}
- filename = window.location.origin + "/api/v1/files/get" + filename;
+ filename = utils.getWindowLocationOrigin() + "/api/v1/files/get" + filename;
if (type === "image") {
previews.push(
diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx
index 05918650b..fe0a47777 100644
--- a/web/react/components/login.jsx
+++ b/web/react/components/login.jsx
@@ -103,13 +103,9 @@ module.exports = React.createClass({
return (
<div className="signup-team__container">
- <div>
- <span className="signup-team__name">{ teamDisplayName }</span>
- <br/>
- <span className="signup-team__subdomain">/{ teamName }/</span>
- <br/>
- <br/>
- </div>
+ <h5 className="margin--less">Sign in to:</h5>
+ <h2 className="signup-team__name">{ teamDisplayName }</h2>
+ <h2 className="signup-team__subdomain">on { config.SiteName }</h2>
<form onSubmit={this.handleSubmit}>
<div className={server_error ? 'form-group has-error' : 'form-group'}>
{ server_error }
@@ -124,13 +120,13 @@ module.exports = React.createClass({
<button type="submit" className="btn btn-primary">Sign in</button>
</div>
{ login_message }
- <div className="form-group form-group--small">
+ <div className="form-group margin--extra form-group--small">
<span><a href="/find_team">{"Find other " + strings.TeamPlural}</a></span>
</div>
<div className="form-group">
<a href={"/" + teamName + "/reset_password"}>I forgot my password</a>
</div>
- <div className="external-link">
+ <div className="margin--extra">
<span>{"Want to create your own " + strings.Team + "?"} <a href="/" className="signup-team-login">Sign up now</a></span>
</div>
</form>
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index 9f598ecb3..641ffeef2 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -32,7 +32,7 @@ module.exports = React.createClass({
if (fileInfo.path.indexOf("/api/v1/files/get") != -1) {
fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1];
}
- fileInfo.path = window.location.origin + "/api/v1/files/get" + fileInfo.path;
+ fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path;
if (type === "image") {
$('<img/>').attr('src', fileInfo.path+'_thumb.jpg').load(function(path, name){ return function() {
@@ -112,7 +112,7 @@ module.exports = React.createClass({
if (fileInfo.path.indexOf("/api/v1/files/get") != -1) {
fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1];
}
- fileInfo.path = window.location.origin + "/api/v1/files/get" + fileInfo.path;
+ fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path;
if (type === "image") {
if (i < Constants.MAX_DISPLAY_FILES) {
diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx
index 567be1962..8097a181e 100644
--- a/web/react/components/post_right.jsx
+++ b/web/react/components/post_right.jsx
@@ -98,7 +98,7 @@ RootPost = React.createClass({
if (fileInfo.path.indexOf("/api/v1/files/get") != -1) {
fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1];
}
- fileInfo.path = window.location.origin + "/api/v1/files/get" + fileInfo.path;
+ fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path;
if (ftype === "image") {
var url = fileInfo.path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29');
@@ -208,7 +208,7 @@ CommentPost = React.createClass({
if (fileInfo.path.indexOf("/api/v1/files/get") != -1) {
fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1];
}
- fileInfo.path = window.location.origin + "/api/v1/files/get" + fileInfo.path;
+ fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path;
if (type === "image") {
var url = fileInfo.path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29');
diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx
index 5b442aeac..e7512934a 100644
--- a/web/react/components/sidebar_header.jsx
+++ b/web/react/components/sidebar_header.jsx
@@ -68,10 +68,10 @@ var NavbarDropdown = React.createClass({
for (var i = 0; i < this.state.teams.length; i++) {
var teamName = this.state.teams[i];
- teams.push(<li key={ teamName }><a href={window.location.origin + "/" + teamName }>Switch to { teamName }</a></li>);
+ teams.push(<li key={ teamName }><a href={utils.getWindowLocationOrigin() + "/" + teamName }>Switch to { teamName }</a></li>);
}
}
- teams.push(<li><a href={window.location.origin + "/signup_team" }>Create a New Team</a></li>);
+ teams.push(<li><a href={utils.getWindowLocationOrigin() + "/signup_team" }>Create a New Team</a></li>);
return (
<ul className="nav navbar-nav navbar-right">
diff --git a/web/react/components/signup_team.jsx b/web/react/components/signup_team.jsx
index 362f79163..edd48e0b9 100644
--- a/web/react/components/signup_team.jsx
+++ b/web/react/components/signup_team.jsx
@@ -20,21 +20,12 @@ module.exports = React.createClass({
state.email_error = "";
}
- team.display_name = this.refs.name.getDOMNode().value.trim();
- if (!team.display_name) {
- state.name_error = "This field is required";
- state.inValid = true;
- }
- else {
- state.name_error = "";
- }
-
if (state.inValid) {
this.setState(state);
return;
}
- client.signupTeam(team.email, team.display_name,
+ client.signupTeam(team.email,
function(data) {
if (data["follow_link"]) {
window.location.href = data["follow_link"];
@@ -55,7 +46,6 @@ module.exports = React.createClass({
render: function() {
var email_error = this.state.email_error ? <label className='control-label'>{ this.state.email_error }</label> : null;
- var name_error = this.state.name_error ? <label className='control-label'>{ this.state.name_error }</label> : null;
var server_error = this.state.server_error ? <div className={ "form-group has-error" }><label className='control-label'>{ this.state.server_error }</label></div> : null;
return (
@@ -64,15 +54,11 @@ module.exports = React.createClass({
<input autoFocus={true} type="email" ref="email" className="form-control" placeholder="Email Address" maxLength="128" />
{ email_error }
</div>
- <div className={ name_error ? "form-group has-error" : "form-group" }>
- <input type="text" ref="name" className="form-control" placeholder={utils.toTitleCase(strings.Company) + " Name"} maxLength="64" />
- { name_error }
- </div>
{ server_error }
<div className="form-group">
- <button className="btn btn-md btn-primary" type="submit">Sign up for Free</button>
+ <button className="btn btn-md btn-primary" type="submit">Sign up</button>
</div>
- <div className="form-group form-group--small">
+ <div className="form-group margin--extra-2x">
<span><a href="/find_team">{"Find my " + strings.Team}</a></span>
</div>
</form>
diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx
index 3e8a57308..21f9edef1 100644
--- a/web/react/components/signup_team_complete.jsx
+++ b/web/react/components/signup_team_complete.jsx
@@ -42,11 +42,15 @@ WelcomePage = React.createClass({
state.email_error = "";
}
- client.signupTeam(email, this.props.state.team.name,
+ client.signupTeam(email,
function(data) {
- this.props.state.wizard = "finished";
- this.props.updateParent(this.props.state);
- window.location.href = "/signup_team_confirm/?email=" + encodeURI(email);
+ 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;
@@ -80,19 +84,25 @@ WelcomePage = React.createClass({
<div>
<p>
<img className="signup-team-logo" src="/static/images/logo.png" />
- <h2>Welcome!</h2>
- <h3>{"Let's set up your " + strings.Team + " on " + config.SiteName + "."}</h3>
+ <h3 className="sub-heading">Welcome to:</h3>
+ <h1 className="margin--top-none">{config.SiteName}</h1>
</p>
+ <p className="margin--less">Let's setup your new team</p>
<p>
Please confirm your email address:<br />
- <span className="black">{ this.props.state.team.email }</span><br />
+ <div className="inner__content">
+ <div className="block--gray">{ this.props.state.team.email }</div>
+ </div>
+ </p>
+ <p className="margin--extra color--light">
+ Your account will administer the new team site. <br />
+ You can add other administrators later.
</p>
<div className="form-group">
<button className="btn-primary btn form-group" type="submit" onClick={this.submitNext}><i className="glyphicon glyphicon-ok"></i>Yes, this address is correct</button>
{ storage_error }
</div>
<hr />
- <p>If this is not correct, you can switch to a different email. We'll send you a new invite right away.</p>
<div className={ this.state.use_diff ? "" : "hidden" }>
<div className={ email_error ? "form-group has-error" : "form-group" }>
<div className="row">
@@ -105,7 +115,7 @@ WelcomePage = React.createClass({
{ server_error }
<button className="btn btn-md btn-primary" type="button" onClick={this.handleDiffSubmit} type="submit">Use this instead</button>
</div>
- <button type="button" onClick={this.handleDiffEmail} className={ this.state.use_diff ? "btn-default btn hidden" : "btn-default btn" }>Use a different address</button>
+ <a href="#" onClick={this.handleDiffEmail} className={ this.state.use_diff ? "hidden" : "" }>Use a different email</a>
</div>
);
}
@@ -128,6 +138,7 @@ TeamDisplayNamePage = React.createClass({
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() {
@@ -158,9 +169,11 @@ TeamDisplayNamePage = React.createClass({
</div>
{ name_error }
</div>
- <p>{"Your " + strings.Team + " name shows in menus and headings. It may include the name of your " + strings.Company + ", but it's not required."}</p>
- <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button>&nbsp;
- <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button>
+ <div>{"Name your " + strings.Team + " in any language. Your " + strings.Team + " name shows in menus and headings."}</div>
+ <button type="submit" className="btn btn-primary margin--extra" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button>
+ <div className="margin--extra">
+ <a href="#" onClick={this.submitBack}>Back to previous step</a>
+ </div>
</form>
</div>
);
@@ -248,17 +261,23 @@ TeamURLPage = React.createClass({
<div className="row">
<div className="col-sm-11">
<div className="input-group">
- <span className="input-group-addon">{ window.location.origin + "/" }</span>
+ <span className="input-group-addon">{ utils.getWindowLocationOrigin() + "/" }</span>
<input type="text" ref="name" className="form-control" placeholder="" maxLength="128" defaultValue={this.props.state.team.name} autoFocus={true} onFocus={this.handleFocus}/>
</div>
</div>
</div>
{ name_error }
</div>
- <p className="black">{"Pick something short and memorable for your " + strings.Team + "'s web address."}</p>
- <p>{"Your " + strings.Team + " URL can only contain lowercase letters, numbers and dashes. Also, it needs to start with a letter and cannot end in a dash."}</p>
- <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button>&nbsp;
- <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button>
+ <p>{"Choose the web address of your new " + strings.Team + ":"}</p>
+ <ul className="color--light">
+ <li>Short and memorable is best</li>
+ <li>Use lower case letters, numbers and dashes</li>
+ <li>Must start with a letter and can't end in a dash</li>
+ </ul>
+ <button type="submit" className="btn btn-primary margin--extra" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button>
+ <div className="margin--extra">
+ <a href="#" onClick={this.submitBack}>Back to previous step</a>
+ </div>
</form>
</div>
);
@@ -461,14 +480,16 @@ SendInivtesPage = React.createClass({
return (
<div>
<form>
- <img className="signup-team-logo" src="/static/images/logo.png" />
- <h2>Send Invitations</h2>
- { emails }
- <div className="form-group"><button type="button" className="btn-default btn" onClick={this.submitAddInvite}>Add Invitation</button></div>
- <div className="form btn-default-group"><button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button>&nbsp;<button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button></div>
- </form>
- <p>{"If you'd prefer, you can send invitations after you finish setting up the "+ strings.Team + "."}</p>
- <div><a href="#" onClick={this.submitSkip}>Skip this step</a></div>
+ <img className="signup-team-logo" src="/static/images/logo.png" />
+ <h2>{"Invite " + utils.toTitleCase(strings.Team) + " Members"}</h2>
+ { emails }
+ <div className="form-group text-right"><a href="#" onClick={this.submitAddInvite}>Add Invitation</a></div>
+ <div className="form-group"><button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button></div>
+ </form>
+ <p className="color--light">{"if you prefer, you can invite " + strings.Team + " members later"}<br /> and <a href="#" onClick={this.submitSkip}>skip this step</a> for now.</p>
+ <div className="margin--extra">
+ <a href="#" onClick={this.submitBack}>Back to previous step</a>
+ </div>
</div>
);
}
@@ -512,19 +533,24 @@ UsernamePage = React.createClass({
<div>
<form>
<img className="signup-team-logo" src="/static/images/logo.png" />
- <h2>Choose a username</h2>
- <div className={ name_error ? "form-group has-error" : "form-group" }>
- <div className="row">
- <div className="col-sm-9">
- <input autoFocus={true} type="text" ref="name" className="form-control" placeholder="" defaultValue={this.props.state.user.username} maxLength="128" />
+ <h2 className="margin--less">Your username</h2>
+ <h5 className="color--light">{"Select a memorable username that makes it easy for " + strings.Team + "mates to identify you:"}</h5>
+ <div className="inner__content margin--extra">
+ <div className={ name_error ? "form-group has-error" : "form-group" }>
+ <div className="row">
+ <div className="col-sm-11">
+ <h5><strong>Choose your username</strong></h5>
+ <input autoFocus={true} type="text" ref="name" className="form-control" placeholder="" defaultValue={this.props.state.user.username} maxLength="128" />
+ <div className="color--light form__hint">Usernames must begin with a letter and contain 3 to 15 characters made up of lowercase letters, numbers, and the symbols '.', '-' and '_'</div>
+ </div>
+ </div>
+ { name_error }
</div>
</div>
- { name_error }
+ <button type="submit" className="btn btn-primary margin--extra" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button>
+ <div className="margin--extra">
+ <a href="#" onClick={this.submitBack}>Back to previous step</a>
</div>
- <p>{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others."}</p>
- <p>It can be made of lowercase letters and numbers.</p>
- <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button>&nbsp;
- <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button>
</form>
</div>
);
@@ -542,15 +568,15 @@ PasswordPage = React.createClass({
var password = this.refs.password.getDOMNode().value.trim();
if (!password || password.length < 5) {
- this.setState({name_error: "Please enter at least 5 characters"});
+ this.setState({password_error: "Please enter at least 5 characters"});
return;
}
- this.setState({name_error: ""});
+ 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 = this.refs.email_service.getDOMNode().checked;
+ teamSignup.user.allow_marketing = true;
delete teamSignup.wizard;
var ctl = this;
@@ -566,7 +592,7 @@ PasswordPage = React.createClass({
props.state.wizard = "finished";
props.updateParent(props.state, true);
- window.location.href = window.location.origin + '/' + props.state.team.name + '/login?email=' + encodeURIComponent(teamSignup.team.email);
+ 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) {
@@ -582,7 +608,7 @@ PasswordPage = React.createClass({
}, 5000);
}.bind(this),
function(err) {
- this.setState({name_error: err.message});
+ this.setState({server_error: err.message});
$('#sign-up-button').button('reset');
}.bind(this)
);
@@ -594,30 +620,37 @@ PasswordPage = React.createClass({
client.track('signup', 'signup_team_07_password');
- var name_error = this.state.name_error ? <label className="control-label">{ this.state.name_error }</label> : null;
+ var password_error = this.state.password_error ? <label className="control-label">{ this.state.password_error }</label> : null;
+ var server_error = this.state.server_error ? <label className="control-label">{ this.state.server_error }</label> : null;
return (
<div>
<form>
<img className="signup-team-logo" src="/static/images/logo.png" />
- <h2>Choose a password</h2>
- <p>You'll use your email address ({this.props.state.team.email}) and password to log into {config.SiteName}.</p>
- <div className={ name_error ? "form-group has-error" : "form-group" }>
- <div className="row">
- <div className="col-sm-9">
- <input autoFocus={true} type="password" ref="password" className="form-control" placeholder="" maxLength="128" />
+ <h2 className="margin--less">Your password</h2>
+ <h5 className="color--light">Select a password that you'll use to login with your email address:</h5>
+ <div className="inner__content margin--extra">
+ <h5><strong>Email</strong></h5>
+ <div className="block--gray form-group">{this.props.state.team.email}</div>
+ <div className={ password_error ? "form-group has-error" : "form-group" }>
+ <div className="row">
+ <div className="col-sm-11">
+ <h5><strong>Choose your password</strong></h5>
+ <input autoFocus={true} type="password" ref="password" className="form-control" placeholder="" maxLength="128" />
+ <div className="color--light form__hint">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.</div>
+ </div>
+ </div>
+ { password_error }
+ { server_error }
</div>
- </div>
- { name_error }
- </div>
- <div className="form-group checkbox">
- <label><input type="checkbox" ref="email_service" /> It's ok to send me occassional email with updates about the {config.SiteName} service.</label>
</div>
<div className="form-group">
- <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button>&nbsp;
- <button type="submit" className="btn-primary btn" id="finish-button" data-loading-text={"<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> Creating "+strings.Team+"..."} onClick={this.submitNext}>Finish</button>
+ <button type="submit" className="btn btn-primary margin--extra" id="finish-button" data-loading-text={"<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> Creating "+strings.Team+"..."} onClick={this.submitNext}>Finish</button>
</div>
<p>By proceeding to create your account and use { config.SiteName }, you agree to our <a href={ config.TermsLink }>Terms of Service</a> and <a href={ config.PrivacyLink }>Privacy Policy</a>. If you do not agree, you cannot use {config.SiteName}.</p>
+ <div className="margin--extra">
+ <a href="#" onClick={this.submitBack}>Back to previous step</a>
+ </div>
</form>
</div>
);
@@ -640,9 +673,6 @@ module.exports = React.createClass({
props.wizard = "welcome";
props.team = {};
props.team.email = this.props.email;
- props.team.display_name = this.props.name;
- props.team.company_name = this.props.name;
- props.team.name = utils.cleanUpUrlable(this.props.name);
props.team.allowed_domains = "";
props.invites = [];
props.invites.push("");
diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx
index bbf1f670c..670aab943 100644
--- a/web/react/components/signup_user_complete.jsx
+++ b/web/react/components/signup_user_complete.jsx
@@ -40,7 +40,7 @@ module.exports = React.createClass({
this.setState({name_error: "", email_error: "", password_error: "", server_error: ""});
- this.state.user.allow_marketing = this.refs.email_service.getDOMNode().checked;
+ this.state.user.allow_marketing = true;
client.createUser(this.state.user, this.state.data, this.state.hash,
function(data) {
@@ -104,8 +104,8 @@ module.exports = React.createClass({
var yourEmailIs = this.state.user.email == "" ? "" : <span>Your email address is { this.state.user.email }. </span>
var email = (
- <div className={ this.state.original_email == "" ? "" : "hidden"} >
- <label className="control-label">Email</label>
+ <div className={ this.state.original_email == "" ? "margin--extra" : "hidden"} >
+ <h5><strong>What's your email address?</strong></h5>
<div className={ email_error ? "form-group has-error" : "form-group" }>
<input type="email" ref="email" className="form-control" defaultValue={ this.state.user.email } placeholder="" maxLength="128" />
{ email_error }
@@ -124,29 +124,33 @@ module.exports = React.createClass({
return (
<div>
<img className="signup-team-logo" src="/static/images/logo.png" />
- <h3 className="text-center extra-margin">Signup to { config.SiteName }</h3>
- <div className="form-group form-group--small">
- <span></span>
- </div>
+ <h5 className="margin--less">Welcome to:</h5>
+ <h2 className="signup-team__name">{ this.props.teamDisplayName }</h2>
+ <h2 className="signup-team__subdomain">on { config.SiteName }</h2>
+ <h4 className="color--light">Let's create your account</h4>
{ signup_message }
- <label className="control-label">Username</label>
- <div className={ name_error ? "form-group has-error" : "form-group" }>
- <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" />
- { name_error }
- <p className="form__hint">Your username can be made of lowercase letters and numbers.</p>
- <p className="form__hint">{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others"}</p>
- </div>
- { email }
- <label className="control-label">Password</label>
- <div className={ password_error ? "form-group has-error" : "form-group" }>
- <input type="password" ref="password" className="form-control" placeholder="" maxLength="128" />
- { password_error }
- </div>
- <p className={ this.state.original_email == "" ? "hidden" : ""}>{ yourEmailIs } You’ll use this address to sign in to {config.SiteName}.</p>
- <div className="checkbox"><label><input type="checkbox" ref="email_service" /> It's ok to send me occassional email with updates about the {config.SiteName} service. </label></div>
- <p><button onClick={this.handleSubmit} className="btn-primary btn">Create Account</button></p>
+ <div className="inner__content">
+ { email }
+ <p className={ this.state.original_email == "" ? "hidden" : ""}>{ yourEmailIs } You’ll use this address to sign in to {config.SiteName}.</p>
+ <div className="margin--extra">
+ <h5><strong>Choose your username</strong></h5>
+ <div className={ name_error ? "form-group has-error" : "form-group" }>
+ <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" />
+ { name_error }
+ <p className="form__hint">Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'"</p>
+ </div>
+ </div>
+ <div className="margin--extra">
+ <h5><strong>Choose your password</strong></h5>
+ <div className={ password_error ? "form-group has-error" : "form-group" }>
+ <input type="password" ref="password" className="form-control" placeholder="" maxLength="128" />
+ { password_error }
+ </div>
+ </div>
+ </div>
+ <p className="margin--extra"><button onClick={this.handleSubmit} className="btn-primary btn">Create Account</button></p>
{ server_error }
- <p>By proceeding to create your account and use { config.SiteName }, you agree to our <a href={ config.TermsLink }>Terms of Service</a> and <a href={ config.PrivacyLink }>Privacy Policy</a>. If you do not agree, you cannot use {config.SiteName}.</p>
+ <p>By creating an account and using Mattermost you are agreeing to our <a href={ config.TermsLink }>Terms of Service</a>. If you do not agree, you cannot use this service.</p>
</div>
);
}
diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx
index c107de4d7..7b096c629 100644
--- a/web/react/components/view_image.jsx
+++ b/web/react/components/view_image.jsx
@@ -40,7 +40,7 @@ module.exports = React.createClass({
if (fileInfo.path.indexOf("/api/v1/files/get") !== -1) {
fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1];
}
- fileInfo.path = window.location.origin + "/api/v1/files/get" + fileInfo.path;
+ fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path;
src = fileInfo['path'] + '_preview.jpg';
}
@@ -148,7 +148,7 @@ module.exports = React.createClass({
if (info.path.indexOf("/api/v1/files/get") !== -1) {
info.path = info.path.split("/api/v1/files/get")[1];
}
- info.path = window.location.origin + "/api/v1/files/get" + info.path;
+ info.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + info.path;
preview_filename = info['path'] + '_preview.jpg';
}
@@ -166,7 +166,7 @@ module.exports = React.createClass({
if (download_link.indexOf("/api/v1/files/get") !== -1) {
download_link = download_link.split("/api/v1/files/get")[1];
}
- download_link = window.location.origin + "/api/v1/files/get" + download_link;
+ download_link = utils.getWindowLocationOrigin() + "/api/v1/files/get" + download_link;
return (
<div className="modal fade image_modal" ref="modal" id={this.props.modalId} tabIndex="-1" role="dialog" aria-hidden="true">
diff --git a/web/react/package.json b/web/react/package.json
index 8d9d57fab..2bba29e2b 100644
--- a/web/react/package.json
+++ b/web/react/package.json
@@ -16,7 +16,9 @@
"jest-cli": "~0.1.17",
"reactify": "^0.15.2",
"uglify-js": "~2.4.15",
- "watchify": "^2.1.1"
+ "watchify": "^2.1.1",
+ "eslint": "^0.24.1",
+ "eslint-plugin-react": "^3.0.0"
},
"scripts": {
"start": "watchify --extension=jsx -o ../static/js/bundle.js -v -d ./**/*.jsx",
diff --git a/web/react/pages/signup_team_complete.jsx b/web/react/pages/signup_team_complete.jsx
index 346f2ab5a..71806c2ea 100644
--- a/web/react/pages/signup_team_complete.jsx
+++ b/web/react/pages/signup_team_complete.jsx
@@ -3,9 +3,9 @@
var SignupTeamComplete =require('../components/signup_team_complete.jsx');
-global.window.setup_signup_team_complete_page = function(email, name, data, hash) {
+global.window.setup_signup_team_complete_page = function(email, data, hash) {
React.render(
- <SignupTeamComplete name={name} email={email} hash={hash} data={data}/>,
+ <SignupTeamComplete email={email} hash={hash} data={data}/>,
document.getElementById('signup-team-complete')
);
};
diff --git a/web/react/pages/signup_user_complete.jsx b/web/react/pages/signup_user_complete.jsx
index 60c3a609a..8f9be1f94 100644
--- a/web/react/pages/signup_user_complete.jsx
+++ b/web/react/pages/signup_user_complete.jsx
@@ -1,7 +1,7 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
-var SignupUserComplete =require('../components/signup_user_complete.jsx');
+var SignupUserComplete = require('../components/signup_user_complete.jsx');
global.window.setup_signup_user_complete_page = function(email, name, ui_name, id, data, hash, auth_services) {
React.render(
diff --git a/web/react/stores/team_store.jsx b/web/react/stores/team_store.jsx
index 3f12725f8..e6380d19e 100644
--- a/web/react/stores/team_store.jsx
+++ b/web/react/stores/team_store.jsx
@@ -11,6 +11,12 @@ var BrowserStore = require('../stores/browser_store.jsx');
var CHANGE_EVENT = 'change';
+var utils;
+function getWindowLocationOrigin() {
+ if (!utils) utils = require('../utils/utils.jsx');
+ return utils.getWindowLocationOrigin();
+}
+
var TeamStore = assign({}, EventEmitter.prototype, {
emitChange: function() {
this.emit(CHANGE_EVENT);
@@ -58,7 +64,7 @@ var TeamStore = assign({}, EventEmitter.prototype, {
return null;
},
getCurrentTeamUrl: function() {
- return window.location.origin + "/" + this.getCurrent().name;
+ return getWindowLocationOrigin() + "/" + this.getCurrent().name;
},
storeTeam: function(team) {
var teams = this._getTeams();
diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx
index 1c31dc5ed..b8eda0075 100644
--- a/web/react/utils/client.jsx
+++ b/web/react/utils/client.jsx
@@ -341,13 +341,13 @@ module.exports.updateTeamDisplayName = function(data, success, error) {
module.exports.track('api', 'api_teams_update_name');
};
-module.exports.signupTeam = function(email, display_name, success, error) {
+module.exports.signupTeam = function(email, success, error) {
$.ajax({
url: "/api/v1/teams/signup",
dataType: 'json',
contentType: 'application/json',
type: 'POST',
- data: JSON.stringify({email: email, display_name: display_name}),
+ data: JSON.stringify({email: email}),
success: success,
error: function(xhr, status, err) {
e = handleError("singupTeam", xhr, status, err);
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index fbf1e0d4f..8a4d92b85 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -22,8 +22,6 @@ module.exports.cleanUpUrlable = function(input) {
return cleaned;
};
-
-
module.exports.isTestDomain = function() {
if ((/^localhost/).test(window.location.hostname))
@@ -841,3 +839,12 @@ module.exports.getDisplayName = function(user) {
}
}
};
+
+//IE10 does not set window.location.origin automatically so this must be called instead when using it
+module.exports.getWindowLocationOrigin = function() {
+ var windowLocationOrigin = window.location.origin;
+ if (!windowLocationOrigin) {
+ windowLocationOrigin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
+ }
+ return windowLocationOrigin;
+};
diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss
index 2d78cf242..719934638 100644
--- a/web/sass-files/sass/partials/_responsive.scss
+++ b/web/sass-files/sass/partials/_responsive.scss
@@ -426,13 +426,15 @@
}
body {
&.white {
- .row.content {
+ .inner__wrap {
+ >.row.content {
margin-bottom: -185px;
}
+ }
}
}
.footer, .footer-pane, .footer-push {
- height: auto;
+ height: 187px;
}
.footer-pane {
.footer-link {
diff --git a/web/sass-files/sass/partials/_signup.scss b/web/sass-files/sass/partials/_signup.scss
index 5996306d2..1a0c55f39 100644
--- a/web/sass-files/sass/partials/_signup.scss
+++ b/web/sass-files/sass/partials/_signup.scss
@@ -9,65 +9,108 @@
max-width: 380px;
margin: 0 auto;
position: relative;
+ &.padding--less {
+ padding-top: 50px;
+ }
+
h1, h2, h3, h4, h5, h6, p {
line-height: 1.3;
}
+
+ h1 {
+ font-weight: 600;
+ }
+
h2 {
font-weight: 600;
- margin-bottom: 0.5em;
+ margin-bottom: 0.8em;
letter-spacing: -0.5px;
font-size: em(30px);
}
+
h3 {
font-weight: 600;
margin: 0 0 1.3em 0;
font-size: 1.5em;
- &.extra-margin {
- margin-bottom: 2.5em;
- }
}
+
h4 {
font-size: em(20px);
font-weight: 600;
margin-bottom: 1em;
- &.text--light {
- font-weight: 300;
- color: #999;
- }
}
+
+ h5 {
+ font-size: em(16px);
+ }
+
+ hr {
+ margin: 2em 0;
+ }
+
p {
color: #555;
line-height: 1.5;
margin-bottom: 1em;
- .black, &.black {
- color: #000;
- }
}
+
+ .inner__content {
+ padding: 0 15px;
+ margin: 30px 0 20px;
+ }
+
+ .block--gray {
+ background: #f2f2f2;
+ display: inline-block;
+ padding: 0.85em 1.2em;
+ font-weight: 600;
+ @include border-radius(3px);
+ }
+
form {
margin-bottom: 0.8em;
}
+
.form__hint {
font-size: 0.95em;
color: #999;
margin: 10px 0;
}
- .external-link {
- position: absolute;
- bottom: 0;
- left: 0;
+
+ .signup-team-confirm__container {
+ padding: 100px 0px 100px 0px;
+ }
+
+ .signup-team-logo {
+ display: none;
+ width: 210px;
+ margin: 0 0 2em 0;
+ }
+
+ .signup-team-login {
+ padding-bottom: 10px;
+ font-weight: 700;
}
+
.signup-team__name {
+ margin: 0.5em 0 0;
font-size: 2.2em;
font-weight: 600;
- text-transform: uppercase;
+ padding-left: 1rem;
}
+
.signup-team__subdomain {
+ margin: 0.2em 0 1.2em;
font-size: 1.5em;
- padding-left: 1em;
+ padding-left: 1rem;
+ font-weight: 300;
+ text-transform: uppercase;
}
+
.form-control {
height: em(38px);
}
+
.or__container {
height: 1px;
background: #dddddd;
@@ -84,6 +127,12 @@
display: inline-block;
}
}
+
+ ul {
+ margin-bottom: 0;
+ padding-left: 18px;
+ }
+
.btn {
padding: em(7px) em(15px);
font-weight: 600;
@@ -121,8 +170,8 @@
}
.glyphicon {
&.glyphicon-ok, &.glyphicon-refresh {
- margin-right: 0.3em;
- left: -5px;
+ margin-right: 0.5em;
+ left: -2px;
font-size: 0.9em;
}
&.glyphicon-chevron-right {
@@ -137,6 +186,7 @@
}
}
}
+
.has-error {
.control-label {
background: #f2f2f2;
@@ -148,13 +198,14 @@
color: #999;
width: 100%;
&:before {
- @extend .fa;
- content: "\f071";
- margin-right: 4px;
- color: #aaa;
+ @extend .fa;
+ content: "\f071";
+ margin-right: 4px;
+ color: #aaa;
}
}
}
+
.reset-form {
@include border-radius(3px);
position: relative;
@@ -163,19 +214,49 @@
color: inherit;
}
}
-}
-.signup-team-confirm__container {
- padding: 100px 0px 100px 0px;
-}
+ // Modifier Styles
+ h1, h2, h3, h4, h5, h6 {
+ &.margin--top-none {
+ margin-top: 0;
+ }
+ &.margin--bottom-none {
+ margin-bottom: 0;
+ }
+ &.margin--less {
+ margin-bottom: 0.3em;
+ }
+ &.sub-heading {
+ font-weight: 400;
+ margin-bottom: 0;
+ }
+ &.color--light {
+ font-weight: 300;
+ }
+ }
-.signup-team-logo {
- display: none;
- width: 210px;
- margin: 0 0 2em 0;
-}
+ p {
+ &.margin--extra {
+ margin-bottom: 1.5em;
+ }
+ &.margin--less {
+ margin-bottom: 0.3em;
+ }
+ .black, &.black {
+ color: #000;
+ }
+ }
+
+ .color--light {
+ color: #777;
+ }
+
+ .margin--extra {
+ margin-top: 3em;
+ }
+
+ .margin--extra-2x {
+ margin-top: 6em;
+ }
-.signup-team-login {
- padding-bottom: 10px;
- font-weight: 700;
}
diff --git a/web/templates/signup_team.html b/web/templates/signup_team.html
index b86590589..b84b8e486 100644
--- a/web/templates/signup_team.html
+++ b/web/templates/signup_team.html
@@ -9,8 +9,8 @@
<div class="col-sm-12">
<div class="signup-team__container">
<img class="signup-team-logo" src="/static/images/logo.png" />
- <h2>All team communication in one place, searchable and accessible anywhere</h2>
- <h4 class="text--light">{{ .SiteName }} is free for an unlimited time, for unlimited users </h4 class="text--light">
+ <h1>Mattermost</h1>
+ <h4 class="color--light">All team communication in one place, searchable and accesible anywhere</h4>
<div id="signup-team"></div>
</div>
</div>
diff --git a/web/templates/signup_team_complete.html b/web/templates/signup_team_complete.html
index 674e54ee2..041889435 100644
--- a/web/templates/signup_team_complete.html
+++ b/web/templates/signup_team_complete.html
@@ -19,7 +19,7 @@
</div>
</div>
<script>
-window.setup_signup_team_complete_page('{{.Props.Email}}', '{{.Props.DisplayName}}', '{{.Props.Data}}', '{{.Props.Hash}}');
+window.setup_signup_team_complete_page('{{.Props.Email}}', '{{.Props.Data}}', '{{.Props.Hash}}');
</script>
</body>
</html>
diff --git a/web/templates/signup_user_complete.html b/web/templates/signup_user_complete.html
index 176ca77b1..e9f6bafcf 100644
--- a/web/templates/signup_user_complete.html
+++ b/web/templates/signup_user_complete.html
@@ -7,7 +7,7 @@
<div class="inner__wrap">
<div class="row content">
<div class="col-sm-12">
- <div class="signup-team__container">
+ <div class="signup-team__container padding--less">
<div id="signup-user-complete"></div>
</div>
</div>
diff --git a/web/web.go b/web/web.go
index 1d59ef946..68e2a5226 100644
--- a/web/web.go
+++ b/web/web.go
@@ -219,7 +219,6 @@ func signupTeamComplete(c *api.Context, w http.ResponseWriter, r *http.Request)
page := NewHtmlTemplatePage("signup_team_complete", "Complete Team Sign Up")
page.Props["Email"] = props["email"]
- page.Props["DisplayName"] = props["display_name"]
page.Props["Data"] = data
page.Props["Hash"] = hash
page.Render(c, w)