front/login: add view
This commit is contained in:
parent
06ede91d31
commit
8b5ebebd01
11 changed files with 166 additions and 20 deletions
|
@ -1,21 +1,34 @@
|
||||||
|
form {
|
||||||
|
display: block;
|
||||||
|
width: 20em;
|
||||||
|
}
|
||||||
form fieldset {
|
form fieldset {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset legend {
|
form fieldset legend {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 17pt;
|
font-size: 17pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
form ul {
|
form ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
form ul li {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
form .buttons {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
form .input li:first-child label,
|
||||||
|
form .input li:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
form.tabular ul {
|
form.tabular ul {
|
||||||
display: table;
|
display: table;
|
||||||
|
@ -37,13 +50,81 @@ form.tabular .buttons {
|
||||||
|
|
||||||
form:not(.tabular) ul li label {
|
form:not(.tabular) ul li label {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 1em 0 0.5em 0;
|
padding: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=radio], input[type=checkbox] {
|
||||||
|
float: left;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio, .checkbox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: calc(20px + 0.5em) !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.radio:hover:before, .checkbox:hover:before {
|
||||||
|
border-color: var(--main-color);
|
||||||
|
}
|
||||||
|
.radio:before, .checkbox:before {
|
||||||
|
transition: border-color 0.1s linear;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
display: block;
|
||||||
|
margin-top: -10px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border: 2px solid var(--input-background-color);
|
||||||
|
background: var(--input-border-color);
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
input[type=radio]:checked + .radio:before,
|
||||||
|
input[type=checkbox]:checked + .checkbox:before {
|
||||||
|
border-color: var(--main-color);
|
||||||
|
}
|
||||||
|
input[type=radio]:checked + .radio:after,
|
||||||
|
input[type=checkbox]:checked + .checkbox:after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio:after {
|
||||||
|
transition: opacity 0.1s linear;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 5px;
|
||||||
|
display: block;
|
||||||
|
margin-top: -5px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
content: '';
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.checkbox:after {
|
||||||
|
transition: opacity 0.1s linear;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 6px;
|
||||||
|
display: block;
|
||||||
|
margin-top: -7px;
|
||||||
|
width: 5px;
|
||||||
|
height: 9px;
|
||||||
|
border-right: 3px solid var(--main-color);
|
||||||
|
border-bottom: 3px solid var(--main-color);
|
||||||
|
content: '';
|
||||||
|
opacity: 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea,
|
textarea,
|
||||||
input[type=text],
|
input[type=text],
|
||||||
input[type=email],
|
input[type=email],
|
||||||
input[type=password] {
|
input[type=password] {
|
||||||
|
transition: border-color 0.1s linear, background-color 0.1s linear;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
font-family: 'Inconsolata', monospace;
|
font-family: 'Inconsolata', monospace;
|
||||||
padding: 0.3em;
|
padding: 0.3em;
|
||||||
|
@ -55,6 +136,13 @@ input[type=password] {
|
||||||
box-shadow: none; /* :-moz-submit-invalid on FF */
|
box-shadow: none; /* :-moz-submit-invalid on FF */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea:focus,
|
||||||
|
input[type=text]:focus,
|
||||||
|
input[type=email]:focus,
|
||||||
|
input[type=password]:focus {
|
||||||
|
border-color: var(--main-color);
|
||||||
|
}
|
||||||
|
|
||||||
form.show-validation fieldset.input input:invalid {
|
form.show-validation fieldset.input input:invalid {
|
||||||
outline: none;
|
outline: none;
|
||||||
border: 2px solid var(--input-bad-border-color);
|
border: 2px solid var(--input-bad-border-color);
|
||||||
|
|
|
@ -17,6 +17,7 @@ body {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-family: 'Droid Sans' !important;
|
font-family: 'Droid Sans' !important;
|
||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
|
line-height: 20pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
#user-registration form {
|
#user-registration form {
|
||||||
display: block;
|
|
||||||
width: 20em;
|
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
#user-registration .info {
|
#user-registration .info {
|
||||||
line-height: 1.8em;
|
|
||||||
float: left;
|
float: left;
|
||||||
margin-left: 3em;
|
margin-left: 3em;
|
||||||
border-radius: 0.2em;
|
border-radius: 0.2em;
|
||||||
width: 20em;
|
width: 20em;
|
||||||
}
|
}
|
||||||
#user-registration .info ul {
|
#user-registration .info ul {
|
||||||
|
line-height: 1.8em;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -28,15 +26,13 @@
|
||||||
#user-registration .info p:first-child {
|
#user-registration .info p:first-child {
|
||||||
margin: 0 0 0.5em 0;
|
margin: 0 0 0.5em 0;
|
||||||
}
|
}
|
||||||
#user-registration .input li:first-child label {
|
|
||||||
padding-top: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
#user-registration .buttons {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
#user-registration p.hint {
|
#user-registration p.hint {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
color: var(--inactive-link-color);
|
color: var(--inactive-link-color);
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
|
line-height: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login .buttons a {
|
||||||
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
25
static/html/login.tpl
Normal file
25
static/html/login.tpl
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<div class='center' id='login'>
|
||||||
|
<h1>Log in</h1>
|
||||||
|
<form>
|
||||||
|
<fieldset class='input'>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<label for='user-name'>User name</label>
|
||||||
|
<input id='user-name' name='user-name' type='text' required/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for='user-password'>Password</label>
|
||||||
|
<input id='user-password' name='user-password' type='password' required/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input id='remember-user' name='remember-user' type='checkbox'/>
|
||||||
|
<label for='remember-user' class='checkbox'>Remember me</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class='buttons'>
|
||||||
|
<input type='submit' value='Log in'/>
|
||||||
|
<a>Forgot the password?</a>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -1,6 +1,5 @@
|
||||||
<div class='center' id='user-registration'>
|
<div class='center' id='user-registration'>
|
||||||
<h1>Registration</h1>
|
<h1>Registration</h1>
|
||||||
<br/>
|
|
||||||
<form autocomplete='off'>
|
<form autocomplete='off'>
|
||||||
<fieldset class='input'>
|
<fieldset class='input'>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
class AuthController {
|
class AuthController {
|
||||||
constructor(topNavigationController) {
|
constructor(topNavigationController, loginView) {
|
||||||
this.topNavigationController = topNavigationController;
|
this.topNavigationController = topNavigationController;
|
||||||
|
this.loginView = loginView;
|
||||||
this.currentUser = null;
|
this.currentUser = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +25,11 @@ class AuthController {
|
||||||
|
|
||||||
loginRoute() {
|
loginRoute() {
|
||||||
this.topNavigationController.activate('login');
|
this.topNavigationController.activate('login');
|
||||||
|
this.loginView.render({
|
||||||
|
login: (user, password) => {
|
||||||
|
alert(user, password);
|
||||||
|
//self.authController.login(user);
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
logoutRoute() {
|
logoutRoute() {
|
||||||
|
|
|
@ -22,7 +22,7 @@ class TopNavigationController {
|
||||||
'users': new NavigationItem('Users', '/users'),
|
'users': new NavigationItem('Users', '/users'),
|
||||||
'account': new NavigationItem('Account', '/user/{me}'),
|
'account': new NavigationItem('Account', '/user/{me}'),
|
||||||
'register': new NavigationItem('Register', '/register'),
|
'register': new NavigationItem('Register', '/register'),
|
||||||
'login': new NavigationItem('Login', '/login'),
|
'login': new NavigationItem('Log in', '/login'),
|
||||||
'logout': new NavigationItem('Logout', '/logout'),
|
'logout': new NavigationItem('Logout', '/logout'),
|
||||||
'help': new NavigationItem('Help', '/help'),
|
'help': new NavigationItem('Help', '/help'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@ class UsersController {
|
||||||
const self = this;
|
const self = this;
|
||||||
this.topNavigationController.activate('register');
|
this.topNavigationController.activate('register');
|
||||||
this.registrationView.render({
|
this.registrationView.render({
|
||||||
onRegistered: (user) => {
|
register: (user) => {
|
||||||
alert(user);
|
alert(user);
|
||||||
self.authController.login(user);
|
self.authController.login(user);
|
||||||
}});
|
}});
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
const page = require('page');
|
const page = require('page');
|
||||||
const handlebars = require('handlebars');
|
const handlebars = require('handlebars');
|
||||||
|
|
||||||
|
const LoginView = require('./views/login_view.js');
|
||||||
const RegistrationView = require('./views/registration_view.js');
|
const RegistrationView = require('./views/registration_view.js');
|
||||||
const TopNavigationView = require('./views/top_navigation_view.js');
|
const TopNavigationView = require('./views/top_navigation_view.js');
|
||||||
const TopNavigationController
|
const TopNavigationController
|
||||||
|
@ -24,9 +25,10 @@ const TagsController = require('./controllers/tags_controller.js');
|
||||||
// - resolve objects -
|
// - resolve objects -
|
||||||
// -------------------
|
// -------------------
|
||||||
const topNavigationView = new TopNavigationView(handlebars);
|
const topNavigationView = new TopNavigationView(handlebars);
|
||||||
|
const loginView = new LoginView(handlebars);
|
||||||
const registrationView = new RegistrationView(handlebars);
|
const registrationView = new RegistrationView(handlebars);
|
||||||
|
|
||||||
const authController = new AuthController(null);
|
const authController = new AuthController(null, loginView);
|
||||||
const topNavigationController
|
const topNavigationController
|
||||||
= new TopNavigationController(topNavigationView, authController);
|
= new TopNavigationController(topNavigationView, authController);
|
||||||
// break cyclic dependency topNavigationView<->authController
|
// break cyclic dependency topNavigationView<->authController
|
||||||
|
|
29
static/js/views/login_view.js
Normal file
29
static/js/views/login_view.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const config = require('../config.js');
|
||||||
|
const BaseView = require('./base_view.js');
|
||||||
|
|
||||||
|
class LoginView extends BaseView {
|
||||||
|
constructor(handlebars) {
|
||||||
|
super(handlebars);
|
||||||
|
this.template = this.getTemplate('login-template');
|
||||||
|
}
|
||||||
|
|
||||||
|
render(options) {
|
||||||
|
this.showView(this.template());
|
||||||
|
const form = document.querySelector('#content-holder form');
|
||||||
|
this.decorateValidator(form);
|
||||||
|
|
||||||
|
const userNameField = document.getElementById('user-name');
|
||||||
|
const passwordField = document.getElementById('user-password');
|
||||||
|
userNameField.setAttribute('pattern', config.service.userNameRegex);
|
||||||
|
passwordField.setAttribute('pattern', config.service.passwordRegex);
|
||||||
|
|
||||||
|
form.addEventListener('submit', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
options.login(userNameField.value, passwordField.value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = LoginView;
|
|
@ -9,7 +9,7 @@ class RegistrationView extends BaseView {
|
||||||
this.template = this.getTemplate('user-registration-template');
|
this.template = this.getTemplate('user-registration-template');
|
||||||
}
|
}
|
||||||
|
|
||||||
render(settings) {
|
render(options) {
|
||||||
this.showView(this.template());
|
this.showView(this.template());
|
||||||
const form = document.querySelector('#content-holder form');
|
const form = document.querySelector('#content-holder form');
|
||||||
this.decorateValidator(form);
|
this.decorateValidator(form);
|
||||||
|
@ -27,7 +27,7 @@ class RegistrationView extends BaseView {
|
||||||
password: passwordField.value,
|
password: passwordField.value,
|
||||||
email: emailField.value,
|
email: emailField.value,
|
||||||
};
|
};
|
||||||
settings.onRegistered(user);
|
options.register(user);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue