client/api: convert messages to events
This commit is contained in:
parent
c1816a292f
commit
8a1140eff6
|
@ -2,14 +2,13 @@
|
|||
|
||||
const request = require('superagent');
|
||||
const config = require('./config.js');
|
||||
const EventListener = require('./event_listener.js');
|
||||
const events = require('./events.js');
|
||||
|
||||
class Api {
|
||||
constructor() {
|
||||
this.user = null;
|
||||
this.userName = null;
|
||||
this.userPassword = null;
|
||||
this.authenticated = new EventListener();
|
||||
}
|
||||
|
||||
get(url) {
|
||||
|
@ -70,11 +69,11 @@ class Api {
|
|||
.then(response => {
|
||||
this.user = response.user;
|
||||
resolve();
|
||||
this.authenticated.fire();
|
||||
events.notify(events.Authentication);
|
||||
}).catch(response => {
|
||||
reject(response.description);
|
||||
this.logout();
|
||||
this.authenticated.fire();
|
||||
events.notify(events.Authentication);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -83,7 +82,7 @@ class Api {
|
|||
this.user = null;
|
||||
this.userName = null;
|
||||
this.userPassword = null;
|
||||
this.authenticated.fire();
|
||||
events.notify(events.Authentication);
|
||||
}
|
||||
|
||||
isLoggedIn() {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const cookies = require('js-cookie');
|
||||
const page = require('page');
|
||||
const api = require('../api.js');
|
||||
const events = require('../events.js');
|
||||
const topNavController = require('../controllers/top_nav_controller.js');
|
||||
const LoginView = require('../views/login_view.js');
|
||||
const PasswordResetView = require('../views/password_reset_view.js');
|
||||
|
@ -11,16 +12,21 @@ class AuthController {
|
|||
constructor() {
|
||||
this.loginView = new LoginView();
|
||||
this.passwordResetView = new PasswordResetView();
|
||||
}
|
||||
|
||||
const auth = cookies.getJSON('auth');
|
||||
if (auth && auth.user && auth.password) {
|
||||
api.login(auth.user, auth.password).catch(errorMessage => {
|
||||
page('/');
|
||||
this.loginView.notifyError(
|
||||
'An error happened while trying to log you in: ' +
|
||||
errorMessage);
|
||||
});
|
||||
}
|
||||
login() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const auth = cookies.getJSON('auth');
|
||||
if (auth && auth.user && auth.password) {
|
||||
api.login(auth.user, auth.password)
|
||||
.then(resolve)
|
||||
.catch(errorMessage => {
|
||||
reject(errorMessage);
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
registerRoutes() {
|
||||
|
@ -51,7 +57,7 @@ class AuthController {
|
|||
options);
|
||||
resolve();
|
||||
page('/');
|
||||
this.loginView.notifySuccess('Logged in');
|
||||
events.notify(events.Success, 'Logged in');
|
||||
}).catch(errorMessage => { reject(errorMessage); });
|
||||
});
|
||||
}});
|
||||
|
@ -61,7 +67,7 @@ class AuthController {
|
|||
api.logout();
|
||||
cookies.remove('auth');
|
||||
page('/');
|
||||
this.loginView.notifySuccess('Logged out');
|
||||
events.notify(events.Success, 'Logged out');
|
||||
}
|
||||
|
||||
passwordResetRoute() {
|
||||
|
@ -89,15 +95,15 @@ class AuthController {
|
|||
cookies.set(
|
||||
'auth', {'user': name, 'password': password}, {});
|
||||
page('/');
|
||||
this.passwordResetView.notifySuccess(
|
||||
events.notify(events.Success,
|
||||
'New password: ' + password);
|
||||
}).catch(errorMessage => {
|
||||
page('/');
|
||||
this.passwordResetView.notifyError(errorMessage);
|
||||
events.notify(events.Error, errorMessage);
|
||||
});
|
||||
}).catch(response => {
|
||||
page('/');
|
||||
this.passwordResetView.notifyError(response.description);
|
||||
events.notify(events.Error, response.description);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const events = require('../events.js');
|
||||
const TopNavView = require('../views/top_nav_view.js');
|
||||
|
||||
class NavigationItem {
|
||||
|
@ -31,11 +32,13 @@ class TopNavController {
|
|||
'help': new NavigationItem('E', 'Help', '/help'),
|
||||
};
|
||||
|
||||
api.authenticated.listen(() => {
|
||||
this.updateVisibility();
|
||||
this.topNavView.render(this.items, this.activeItem);
|
||||
this.topNavView.activate(this.activeItem);
|
||||
});
|
||||
events.listen(
|
||||
events.Authentication,
|
||||
() => {
|
||||
this.updateVisibility();
|
||||
this.topNavView.render(this.items, this.activeItem);
|
||||
this.topNavView.activate(this.activeItem);
|
||||
});
|
||||
|
||||
this.updateVisibility();
|
||||
this.topNavView.render(this.items, this.activeItem);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const cookies = require('js-cookie');
|
||||
const page = require('page');
|
||||
const api = require('../api.js');
|
||||
const events = require('../events.js');
|
||||
const topNavController = require('../controllers/top_nav_controller.js');
|
||||
const RegistrationView = require('../views/registration_view.js');
|
||||
const UserView = require('../views/user_view.js');
|
||||
|
@ -50,7 +51,7 @@ class UsersController {
|
|||
cookies.set('auth', {'user': name, 'password': password});
|
||||
resolve();
|
||||
page('/');
|
||||
this.registrationView.notifySuccess('Welcome aboard!');
|
||||
events.notify(events.Success, 'Welcome aboard!');
|
||||
}).catch(response => {
|
||||
reject(response.description);
|
||||
});
|
||||
|
@ -74,7 +75,7 @@ class UsersController {
|
|||
next();
|
||||
}).catch(response => {
|
||||
this.userView.empty();
|
||||
this.userView.notifyError(response.description);
|
||||
events.notify(events.Error, response.description);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
class EventListener {
|
||||
constructor() {
|
||||
this.listeners = [];
|
||||
}
|
||||
|
||||
listen(callback) {
|
||||
this.listeners.push(callback);
|
||||
}
|
||||
|
||||
unlisten(callback) {
|
||||
const index = this.listeners.indexOf(callback);
|
||||
if (index !== -1) {
|
||||
this.listeners.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
fire(data) {
|
||||
for (let listener of this.listeners) {
|
||||
listener(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EventListener;
|
|
@ -0,0 +1,28 @@
|
|||
'use strict';
|
||||
|
||||
let listeners = [];
|
||||
|
||||
function listen(messageClass, handler) {
|
||||
if (!(messageClass in listeners)) {
|
||||
listeners[messageClass] = [];
|
||||
}
|
||||
listeners[messageClass].push(handler);
|
||||
}
|
||||
|
||||
function notify(messageClass, message) {
|
||||
if (!(messageClass in listeners)) {
|
||||
return;
|
||||
}
|
||||
for (let handler of listeners[messageClass]) {
|
||||
handler(message);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Success: 1,
|
||||
Error: 2,
|
||||
Authentication: 3,
|
||||
|
||||
notify: notify,
|
||||
listen: listen,
|
||||
};
|
|
@ -3,18 +3,29 @@
|
|||
require('./util/handlebars-helpers.js');
|
||||
|
||||
let controllers = [];
|
||||
const authController = require('./controllers/auth_controller.js');
|
||||
controllers.push(authController);
|
||||
controllers.push(require('./controllers/posts_controller.js'));
|
||||
controllers.push(require('./controllers/users_controller.js'));
|
||||
controllers.push(require('./controllers/help_controller.js'));
|
||||
controllers.push(require('./controllers/auth_controller.js'));
|
||||
controllers.push(require('./controllers/comments_controller.js'));
|
||||
controllers.push(require('./controllers/history_controller.js'));
|
||||
controllers.push(require('./controllers/tags_controller.js'));
|
||||
|
||||
controllers.push(require('./controllers/home_controller.js'));
|
||||
|
||||
const events = require('./events.js');
|
||||
const page = require('page');
|
||||
for (let controller of controllers) {
|
||||
controller.registerRoutes();
|
||||
}
|
||||
page();
|
||||
|
||||
authController.login().then(() => {
|
||||
page();
|
||||
}).catch(errorMessage => {
|
||||
page();
|
||||
page('/');
|
||||
events.notify(
|
||||
events.Error,
|
||||
'An error happened while trying to log you in: ' + errorMessage);
|
||||
});
|
||||
|
|
|
@ -1,13 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
const handlebars = require('handlebars');
|
||||
const events = require('../events.js');
|
||||
const contentHolder = document.getElementById('content-holder');
|
||||
|
||||
function messageHandler(message, className) {
|
||||
const messagesHolder = contentHolder.querySelector('.messages');
|
||||
if (!messagesHolder) {
|
||||
alert(message);
|
||||
return;
|
||||
}
|
||||
/* TODO: animate this */
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = message.replace(/\n/g, '<br/>');
|
||||
node.classList.add('message');
|
||||
node.classList.add(className);
|
||||
messagesHolder.appendChild(node);
|
||||
}
|
||||
|
||||
events.listen(events.Success, msg => { messageHandler(msg, 'success'); });
|
||||
events.listen(events.Error, msg => { messageHandler(msg, 'error'); });
|
||||
|
||||
// fix iterating over NodeList in Chrome and Opera
|
||||
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
|
||||
|
||||
class BaseView {
|
||||
constructor() {
|
||||
this.contentHolder = document.getElementById('content-holder');
|
||||
this.contentHolder = contentHolder;
|
||||
}
|
||||
|
||||
getTemplate(templatePath) {
|
||||
|
@ -20,24 +39,6 @@ class BaseView {
|
|||
return handlebars.compile(templateText);
|
||||
}
|
||||
|
||||
notifyError(message) {
|
||||
this.notify(message, 'error');
|
||||
}
|
||||
|
||||
notifySuccess(message) {
|
||||
this.notify(message, 'success');
|
||||
}
|
||||
|
||||
notify(message, className) {
|
||||
const messagesHolder = this.contentHolder.querySelector('.messages');
|
||||
/* TODO: animate this */
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = message.replace(/\n/g, '<br/>');
|
||||
node.classList.add('message');
|
||||
node.classList.add(className);
|
||||
messagesHolder.appendChild(node);
|
||||
}
|
||||
|
||||
clearMessages() {
|
||||
const messagesHolder = this.contentHolder.querySelector('.messages');
|
||||
/* TODO: animate that */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const config = require('../config.js');
|
||||
const events = require('../events.js');
|
||||
const BaseView = require('./base_view.js');
|
||||
|
||||
class LoginView extends BaseView {
|
||||
|
@ -34,7 +35,7 @@ class LoginView extends BaseView {
|
|||
})
|
||||
.catch(errorMessage => {
|
||||
this.enableForm(form);
|
||||
this.notifyError(errorMessage);
|
||||
events.notify(events.Error, errorMessage);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const events = require('../events.js');
|
||||
const BaseView = require('./base_view.js');
|
||||
|
||||
class PasswordResetView extends BaseView {
|
||||
|
@ -22,13 +23,14 @@ class PasswordResetView extends BaseView {
|
|||
options
|
||||
.proceed(userNameOrEmailField.value)
|
||||
.then(() => {
|
||||
this.notifySuccess(
|
||||
events.notify(
|
||||
events.Success,
|
||||
'E-mail has been sent. To finish the procedure, ' +
|
||||
'please click the link it contains.');
|
||||
})
|
||||
.catch(errorMessage => {
|
||||
this.enableForm(form);
|
||||
this.notifyError(errorMessage);
|
||||
events.notify(events.Error, errorMessage);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const config = require('../config.js');
|
||||
const events = require('../events.js');
|
||||
const BaseView = require('./base_view.js');
|
||||
|
||||
class RegistrationView extends BaseView {
|
||||
|
@ -11,12 +12,13 @@ class RegistrationView extends BaseView {
|
|||
|
||||
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');
|
||||
const emailField = document.getElementById('user-email');
|
||||
const form = this.contentHolder.querySelector('form');
|
||||
const userNameField = this.contentHolder.querySelector('#user-name');
|
||||
const passwordField = this.contentHolder.querySelector('#user-password');
|
||||
const emailField = this.contentHolder.querySelector('#user-email');
|
||||
|
||||
this.decorateValidator(form);
|
||||
userNameField.setAttribute('pattern', config.userNameRegex);
|
||||
passwordField.setAttribute('pattern', config.passwordRegex);
|
||||
|
||||
|
@ -34,7 +36,7 @@ class RegistrationView extends BaseView {
|
|||
})
|
||||
.catch(errorMessage => {
|
||||
this.enableForm(form);
|
||||
this.notifyError(errorMessage);
|
||||
events.notify(events.Error, errorMessage);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue