diff --git a/ide/static/css/signup_style.css b/ide/static/css/signup_style.css new file mode 100644 index 000000000..1a88371fc --- /dev/null +++ b/ide/static/css/signup_style.css @@ -0,0 +1,126 @@ +.signup-container { + background-size: cover; + background: #f4f6ff; + height: 100%; + width: 100%; + position: fixed; + top: 0; + left: 0; +} + +.card { + background: #fff; + width: 40em; + height: 44em; + border-radius: 5px; + margin-top: 5em; + box-shadow: 1px 1px 132px -20px rgba(205, 207, 210, 0.8); +} + +.card-top { + width: 100%; + height: 11em; + border-bottom: 1px solid #eee; +} + +.card-top-left { + float: left; + border-right: 1px solid #eee; + width: 50%; +} + +.card-top-left img { + width: 50%; + margin: 2.95em 0 2.95em 0; +} + +.card-top-right h1{ + color: #455062; + font-size: 1.4em; + margin-top: 0.8em; +} + +.card-top-right img { + width: 15%; + margin-top: 1.4em; +} + +.form { + margin-top: 3em; +} + +.input { + border: 2px solid #eee; + border-radius: 10px; + width: 300px; + margin: 1em; + transition: all .3s ease; +} + +.input img{ + width: 15%; + margin-left: -0.4em; + transition: all .3s ease; +} + +.field { + margin: 0; + border: 0; + outline: 0; + width: 245px; + position: relative; + top: 0.1em; + padding: 0.5em 0 0.5em 0; + color: #455060; + font-size: 1.1em; +} + +.field::placeholder { + color: #455060; +} + +.active-input { + border-color: #455060; + transition: all .3s ease; +} + +.wrong-input { + border-color: #eb4d4b; + transition: all .3s ease; +} + +.error-message { + color: #eb4d4b; + margin: 1.1em 0 0.2em 0; + opacity: 0; + transition: all .3s ease; +} + +.show { + opacity: 1 !important; + transition: all .3s ease; +} + +input[type=submit] { + background: #455062; + border: 0; + outline: 0; + box-shadow: none; + color: #fff; + margin: 0.4em; + text-transform: uppercase; + font-weight: bold; + padding: 1.2em 0 1.2em 0; + width: 300px; + border-radius: 10px; +} + +.login-link { + margin: 2em; + color: #455062; + display: inline-block; +} + +.login-link:hover { + color: #2c323d; +} diff --git a/ide/static/img/account.png b/ide/static/img/account.png new file mode 100644 index 000000000..b0c5d31cd Binary files /dev/null and b/ide/static/img/account.png differ diff --git a/ide/static/img/email_icon.png b/ide/static/img/email_icon.png new file mode 100644 index 000000000..6b0f97a68 Binary files /dev/null and b/ide/static/img/email_icon.png differ diff --git a/ide/static/img/email_icon_active.png b/ide/static/img/email_icon_active.png new file mode 100644 index 000000000..2557accaf Binary files /dev/null and b/ide/static/img/email_icon_active.png differ diff --git a/ide/static/img/email_icon_wrong.png b/ide/static/img/email_icon_wrong.png new file mode 100644 index 000000000..741887386 Binary files /dev/null and b/ide/static/img/email_icon_wrong.png differ diff --git a/ide/static/img/logo_without_bg.png b/ide/static/img/logo_without_bg.png new file mode 100644 index 000000000..fba352238 Binary files /dev/null and b/ide/static/img/logo_without_bg.png differ diff --git a/ide/static/img/password_icon.png b/ide/static/img/password_icon.png new file mode 100644 index 000000000..3e3eab72e Binary files /dev/null and b/ide/static/img/password_icon.png differ diff --git a/ide/static/img/password_icon_active.png b/ide/static/img/password_icon_active.png new file mode 100644 index 000000000..d1f8cc3ef Binary files /dev/null and b/ide/static/img/password_icon_active.png differ diff --git a/ide/static/img/password_icon_wrong.png b/ide/static/img/password_icon_wrong.png new file mode 100644 index 000000000..eeaf24585 Binary files /dev/null and b/ide/static/img/password_icon_wrong.png differ diff --git a/ide/static/img/username_icon.png b/ide/static/img/username_icon.png new file mode 100644 index 000000000..4e3531c42 Binary files /dev/null and b/ide/static/img/username_icon.png differ diff --git a/ide/static/img/username_icon_active.png b/ide/static/img/username_icon_active.png new file mode 100644 index 000000000..350080f4d Binary files /dev/null and b/ide/static/img/username_icon_active.png differ diff --git a/ide/static/img/username_icon_wrong.png b/ide/static/img/username_icon_wrong.png new file mode 100644 index 000000000..e97e5e059 Binary files /dev/null and b/ide/static/img/username_icon_wrong.png differ diff --git a/ide/static/js/index.js b/ide/static/js/index.js index d387a3637..da50782c8 100644 --- a/ide/static/js/index.js +++ b/ide/static/js/index.js @@ -3,10 +3,12 @@ import React from 'react'; import { render } from 'react-dom'; import { Router, Route, hashHistory } from 'react-router'; import App from './app.js'; +import Signup from './signup.js'; import '../css/style.css'; render( + , document.getElementById('app') ); diff --git a/ide/static/js/login.js b/ide/static/js/login.js index a31214afa..e0af648c4 100644 --- a/ide/static/js/login.js +++ b/ide/static/js/login.js @@ -26,6 +26,11 @@ class Login extends React.Component { this.setState({ loginState: false }); this.props.setUserId(null); this.props.setUserName(null); + localStorage.removeItem('userID'); + localStorage.removeItem('username'); + if (localStorage.hasOwnProperty('email')) { + localStorage.removeItem('email'); + } } }.bind(this), error: function () { @@ -68,6 +73,8 @@ class Login extends React.Component { this.setState({ loginState: response.result }); this.props.setUserId(response.user_id); this.props.setUserName(response.username); + localStorage.setItem("userID",response.user_id); + localStorage.setItem("username",response.username); if (showNotification) { $('#successful-login-notification')[0].style.display = 'block'; diff --git a/ide/static/js/signup.js b/ide/static/js/signup.js new file mode 100644 index 000000000..ca171edcd --- /dev/null +++ b/ide/static/js/signup.js @@ -0,0 +1,295 @@ +import React from "react"; +import DjangoCSRFToken from "django-react-csrftoken"; +import $ from "jquery"; + +class Signup extends React.Component { + constructor(props) { + super(props); + this.state = { + error_username: 0, + error_email: 0, + error_password: 0, + error_confirm_password: 0 + }; + this.submitForm = this.submitForm.bind(this); + this.validateUsernameMaxLen = this.validateUsernameMaxLen.bind(this); + this.onClickUsernameInput = this.onClickUsernameInput.bind(this); + this.validateEmailFormat = this.validateEmailFormat.bind(this); + this.onClickEmailInput = this.onClickEmailInput.bind(this); + this.validatePasswordFormat = this.validatePasswordFormat.bind(this); + this.onClickPasswordInput = this.onClickPasswordInput.bind(this); + this.validateSamePassword = this.validateSamePassword.bind(this); + this.onClickConfirmPasswordInput = this.onClickConfirmPasswordInput.bind(this); + } + + onClickUsernameInput() { + document.getElementById("username-input").className = "input active-input"; + document.getElementById("username-icon").src = "static/img/username_icon_active.png"; + } + + validateUsernameMaxLen() { + let username = document.getElementById("username-value").value; + let username_input = document.getElementById("username-input"); + let username_icon = document.getElementById("username-icon"); + let error_message = document.getElementById("error-message"); + username_input.className = "input"; + if (username.length == "") { + username_input.className = "input wrong-input"; + error_message.innerHTML = "The username can't be empty."; + error_message.className = "error-message show"; + username_icon.src = "static/img/username_icon_wrong.png"; + this.setState({ error_username: 1 }); + } else if (username.length > 150) { + username_input.className = "input wrong-input"; + error_message.innerHTML = "The username can't be more than 150 characters."; + error_message.className = "error-message show"; + username_icon.src = "static/img/username_icon_wrong.png"; + this.setState({ error_username: 1 }); + } else { + username_input.className = "input"; + error_message.innerHTML = ""; + error_message.className = "error-message"; + this.setState({ error_username: 0 }); + } + } + + onClickEmailInput() { + document.getElementById("email-input").className = "input active-input"; + document.getElementById("email-icon").src = + "static/img/email_icon_active.png"; + } + + validateEmailFormat() { + let email = document.getElementById("email-value").value; + let email_input = document.getElementById("email-input"); + let email_icon = document.getElementById("email-icon"); + let error_message = document.getElementById("error-message"); + let symbol = email.indexOf("@"); + let next = email.charAt(symbol + 1); + email_input.className = "input"; + if (email.length == "") { + email_input.className = "input wrong-input"; + error_message.innerHTML = "The email can't be empty."; + error_message.className = "error-message show"; + email_icon.src = "static/img/email_icon_wrong.png"; + this.setState({ error_email: 1 }); + } else if (!email.includes("@")) { + email_input.className = "input wrong-input"; + error_message.innerHTML = "The email should contain @ symbol."; + error_message.className = "error-message show"; + email_icon.src = "static/img/email_icon_wrong.png"; + this.setState({ error_email: 1 }); + } else if (next == "") { + email_input.className = "input wrong-input"; + error_message.innerHTML = "The email should contain the domain."; + error_message.className = "error-message show"; + email_icon.src = "static/img/email_icon_wrong.png"; + this.setState({ error_email: 1 }); + } else { + email_input.className = "input"; + error_message.innerHTML = ""; + error_message.className = "error-message"; + this.setState({ error_email: 0 }); + } + } + + onClickPasswordInput() { + document.getElementById("password-input").className = "input active-input"; + document.getElementById("password-icon").src = + "static/img/password_icon_active.png"; + } + + validatePasswordFormat() { + let password = document.getElementById("password-value").value; + let password_input = document.getElementById("password-input"); + let password_icon = document.getElementById("password-icon"); + let error_message = document.getElementById("error-message"); + password_input.className = "input"; + if (password.length == "") { + password_input.className = "input wrong-input"; + error_message.innerHTML = "The password can't be empty."; + error_message.className = "error-message show"; + password_icon.src = "static/img/password_icon_wrong.png"; + this.setState({ error_password: 1 }); + } else if (password.length < 6) { + password_input.className = "input wrong-input"; + error_message.innerHTML = "The password should be atleast 6 characters long."; + error_message.className = "error-message show"; + password_icon.src = "static/img/password_icon_wrong.png"; + this.setState({ error_password: 1 }); + } else { + password_input.className = "input"; + error_message.innerHTML = ""; + error_message.className = "error-message"; + this.setState({ error_password: 0 }); + } + } + + onClickConfirmPasswordInput() { + document.getElementById("confirm-password-input").className = "input active-input"; + document.getElementById("confirm-password-icon").src = "static/img/password_icon_active.png"; + } + + validateSamePassword() { + let confirm_password = document.getElementById("confirm-password-value").value; + let password = document.getElementById("password-value").value; + let confirm_password_input = document.getElementById("confirm-password-input"); + let confirm_password_icon = document.getElementById("confirm-password-icon"); + let error_message = document.getElementById("error-message"); + confirm_password_input.className = "input"; + if (confirm_password != password) { + confirm_password_input.className = "input wrong-input"; + error_message.innerHTML = "The passwords do not match."; + error_message.className = "error-message show"; + confirm_password_icon.src = "static/img/password_icon_wrong.png"; + this.setState({ error_confirm_password: 1 }); + } else { + confirm_password_input.className = "input"; + error_message.innerHTML = ""; + error_message.className = "error-message"; + this.setState({ error_confirm_password: 0 }); + } + } + + submitForm(e) { + e.preventDefault(); + let username = document.getElementById("username-value").value; + let email = document.getElementById("email-value").value; + let password = document.getElementById("password-value").value; + password.replace(/[|&;$%@"<>()+,]/g, ""); + let confirm_password = document.getElementById("confirm-password-value").value; + confirm_password.replace(/[|&;$%@"<>()+,]/g, ""); + let cleaned_password = password.trim(); + let cleaned_confirm_password = confirm_password.trim(); + let csrfmiddlewaretoken = document.getElementsByName("csrfmiddlewaretoken")[0].value; + if ( + this.state.error_username == 0 && + this.state.error_email == 0 && + this.state.error_password == 0 && + this.state.error_confirm_password == 0 + ) { + $.ajax({ + method: "POST", + url: "/accounts/signup/", + data: { + csrfmiddlewaretoken: csrfmiddlewaretoken, + username: username, + email: email, + password1: cleaned_password, + password2: cleaned_confirm_password + }, + success: function(result) { + if (result.location == "/") { + localStorage.setItem('email', email); + window.location = "/"; + } else { + let error_message = document.getElementById("error-message"); + error_message.innerHTML = "Network error"; + error_message.className = "error-message show"; + } + }, + complete: function(xhr) { + if (xhr.status == 400) { + let error_message = document.getElementById("error-message"); + error_message.innerHTML = + "An account with those details already exists."; + error_message.className = "error-message show"; + } + } + }); + } else { + let error_message = document.getElementById("error-message"); + error_message.innerHTML = "Error"; + error_message.className = "error-message show"; + } + } + render() { + return ( +
+
+
+
+
+ +
+
+ +

Create your account

+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +

+ +

+
+ + Already have an account? + +
+
+
+ ); + } +} + +export default Signup; diff --git a/ide/templates/index.html b/ide/templates/index.html index 80ea64972..63bc0b032 100644 --- a/ide/templates/index.html +++ b/ide/templates/index.html @@ -13,6 +13,7 @@ rel="stylesheet"> + diff --git a/package.json b/package.json index 16e0bf723..c1b62e305 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "babel-polyfill": "^6.9.1", "bootstrap": "^3.3.6", + "django-react-csrftoken": "^1.0.4", "jquery": "^3.0.0", "react": "^15.1.0", "react-dom": "^15.1.0",