client/views: replace inheritance with composition
This commit is contained in:
parent
4821f2ac6c
commit
2e1823b708
15 changed files with 214 additions and 198 deletions
|
@ -69,3 +69,6 @@
|
||||||
#user-delete form {
|
#user-delete form {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
#user-delete form label {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ const api = require('../api.js');
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
const events = require('../events.js');
|
const events = require('../events.js');
|
||||||
const misc = require('../util/misc.js');
|
const misc = require('../util/misc.js');
|
||||||
|
const views = require('../util/views.js');
|
||||||
const topNavController = require('../controllers/top_nav_controller.js');
|
const topNavController = require('../controllers/top_nav_controller.js');
|
||||||
const RegistrationView = require('../views/registration_view.js');
|
const RegistrationView = require('../views/registration_view.js');
|
||||||
const UserView = require('../views/user_view.js');
|
const UserView = require('../views/user_view.js');
|
||||||
|
@ -58,7 +59,7 @@ class UsersController {
|
||||||
this.user = response.user;
|
this.user = response.user;
|
||||||
next();
|
next();
|
||||||
}).catch(response => {
|
}).catch(response => {
|
||||||
this.userView.emptyView(this.userView.contentHolder);
|
views.emptyView(document.getElementById('content-holder'));
|
||||||
events.notify(events.Error, response.description);
|
events.notify(events.Error, response.description);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
let listeners = [];
|
let listeners = [];
|
||||||
|
|
||||||
|
function unlisten(messageClass) {
|
||||||
|
listeners[messageClass] = [];
|
||||||
|
}
|
||||||
|
|
||||||
function listen(messageClass, handler) {
|
function listen(messageClass, handler) {
|
||||||
if (!(messageClass in listeners)) {
|
if (!(messageClass in listeners)) {
|
||||||
listeners[messageClass] = [];
|
listeners[messageClass] = [];
|
||||||
|
@ -25,4 +29,5 @@ module.exports = {
|
||||||
|
|
||||||
notify: notify,
|
notify: notify,
|
||||||
listen: listen,
|
listen: listen,
|
||||||
|
unlisten: unlisten,
|
||||||
};
|
};
|
||||||
|
|
125
client/js/util/views.js
Normal file
125
client/js/util/views.js
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('../util/polyfill.js');
|
||||||
|
const handlebars = require('handlebars');
|
||||||
|
const events = require('../events.js');
|
||||||
|
const domParser = new DOMParser();
|
||||||
|
|
||||||
|
function _messageHandler(target, message, className) {
|
||||||
|
if (!message) {
|
||||||
|
message = 'Unknown message';
|
||||||
|
}
|
||||||
|
const messagesHolder = target.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function listenToMessages(target) {
|
||||||
|
events.unlisten(events.Success);
|
||||||
|
events.unlisten(events.Error);
|
||||||
|
events.listen(
|
||||||
|
events.Success, msg => { _messageHandler(target, msg, 'success'); });
|
||||||
|
events.listen(
|
||||||
|
events.Error, msg => { _messageHandler(target, msg, 'error'); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearMessages(target) {
|
||||||
|
const messagesHolder = target.querySelector('.messages');
|
||||||
|
/* TODO: animate that */
|
||||||
|
while (messagesHolder.lastChild) {
|
||||||
|
messagesHolder.removeChild(messagesHolder.lastChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function htmlToDom(html) {
|
||||||
|
const parsed = domParser.parseFromString(html, 'text/html').body;
|
||||||
|
return parsed.childNodes.length > 1 ?
|
||||||
|
parsed.childNodes :
|
||||||
|
parsed.firstChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTemplate(templatePath) {
|
||||||
|
const templateElement = document.getElementById(templatePath + '-template');
|
||||||
|
if (!templateElement) {
|
||||||
|
console.error('Missing template: ' + templatePath);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const templateText = templateElement.innerHTML.trim();
|
||||||
|
const templateFactory = handlebars.compile(templateText);
|
||||||
|
return (...args) => {
|
||||||
|
return htmlToDom(templateFactory(...args));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function decorateValidator(form) {
|
||||||
|
// postpone showing form fields validity until user actually tries
|
||||||
|
// to submit it (seeing red/green form w/o doing anything breaks POLA)
|
||||||
|
const submitButton = form.querySelector('.buttons input');
|
||||||
|
submitButton.addEventListener('click', e => {
|
||||||
|
form.classList.add('show-validation');
|
||||||
|
});
|
||||||
|
form.addEventListener('submit', e => {
|
||||||
|
form.classList.remove('show-validation');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableForm(form) {
|
||||||
|
for (let input of form.querySelectorAll('input')) {
|
||||||
|
input.disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableForm(form) {
|
||||||
|
for (let input of form.querySelectorAll('input')) {
|
||||||
|
input.disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function emptyView(target) {
|
||||||
|
const ret = showView(target, htmlToDom('<div class="messages"></div>'));
|
||||||
|
listenToMessages(target);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showView(target, source) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let observer = new MutationObserver(mutations => {
|
||||||
|
resolve();
|
||||||
|
observer.disconnect();
|
||||||
|
});
|
||||||
|
observer.observe(target, {childList: true});
|
||||||
|
while (target.lastChild) {
|
||||||
|
target.removeChild(target.lastChild);
|
||||||
|
}
|
||||||
|
if (source instanceof NodeList) {
|
||||||
|
for (let child of source) {
|
||||||
|
target.appendChild(child);
|
||||||
|
}
|
||||||
|
} else if (source instanceof Node) {
|
||||||
|
target.appendChild(source);
|
||||||
|
} else {
|
||||||
|
console.error('Invalid view source', source);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
htmlToDom: htmlToDom,
|
||||||
|
getTemplate: getTemplate,
|
||||||
|
showView: showView,
|
||||||
|
emptyView: emptyView,
|
||||||
|
enableForm: enableForm,
|
||||||
|
disableForm: disableForm,
|
||||||
|
listenToMessages: listenToMessages,
|
||||||
|
clearMessages: clearMessages,
|
||||||
|
decorateValidator: decorateValidator,
|
||||||
|
};
|
|
@ -1,115 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const handlebars = require('handlebars');
|
|
||||||
const events = require('../events.js');
|
|
||||||
const contentHolder = document.getElementById('content-holder');
|
|
||||||
require('../util/polyfill.js');
|
|
||||||
|
|
||||||
function messageHandler(message, className) {
|
|
||||||
if (!message) {
|
|
||||||
message = 'Unknown message';
|
|
||||||
}
|
|
||||||
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'); });
|
|
||||||
|
|
||||||
class BaseView {
|
|
||||||
constructor() {
|
|
||||||
this.contentHolder = contentHolder;
|
|
||||||
this.domParser = new DOMParser();
|
|
||||||
}
|
|
||||||
|
|
||||||
htmlToDom(html) {
|
|
||||||
const parsed = this.domParser.parseFromString(html, 'text/html').body;
|
|
||||||
return parsed.childNodes.length > 1 ?
|
|
||||||
parsed.childNodes :
|
|
||||||
parsed.firstChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTemplate(templatePath) {
|
|
||||||
const templateElement = document.getElementById(templatePath);
|
|
||||||
if (!templateElement) {
|
|
||||||
console.error('Missing template: ' + templatePath);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const templateText = templateElement.innerHTML.trim();
|
|
||||||
const templateFactory = handlebars.compile(templateText);
|
|
||||||
return (...args) => {
|
|
||||||
return this.htmlToDom(templateFactory(...args));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clearMessages() {
|
|
||||||
const messagesHolder = this.contentHolder.querySelector('.messages');
|
|
||||||
/* TODO: animate that */
|
|
||||||
while (messagesHolder.lastChild) {
|
|
||||||
messagesHolder.removeChild(messagesHolder.lastChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decorateValidator(form) {
|
|
||||||
// postpone showing form fields validity until user actually tries
|
|
||||||
// to submit it (seeing red/green form w/o doing anything breaks POLA)
|
|
||||||
const submitButton = form.querySelector('.buttons input');
|
|
||||||
submitButton.addEventListener('click', e => {
|
|
||||||
form.classList.add('show-validation');
|
|
||||||
});
|
|
||||||
form.addEventListener('submit', e => {
|
|
||||||
form.classList.remove('show-validation');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
disableForm(form) {
|
|
||||||
for (let input of form.querySelectorAll('input')) {
|
|
||||||
input.disabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enableForm(form) {
|
|
||||||
for (let input of form.querySelectorAll('input')) {
|
|
||||||
input.disabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyView(target) {
|
|
||||||
return this.showView(
|
|
||||||
target,
|
|
||||||
this.htmlToDom('<div class="messages"></div>'));
|
|
||||||
}
|
|
||||||
|
|
||||||
showView(target, source) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let observer = new MutationObserver(mutations => {
|
|
||||||
resolve();
|
|
||||||
observer.disconnect();
|
|
||||||
});
|
|
||||||
observer.observe(target, {childList: true});
|
|
||||||
while (target.lastChild) {
|
|
||||||
target.removeChild(target.lastChild);
|
|
||||||
}
|
|
||||||
if (source instanceof NodeList) {
|
|
||||||
for (let child of source) {
|
|
||||||
target.appendChild(child);
|
|
||||||
}
|
|
||||||
} else if (source instanceof Node) {
|
|
||||||
target.appendChild(source);
|
|
||||||
} else {
|
|
||||||
console.error('Invalid view source', source);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = BaseView;
|
|
|
@ -1,31 +1,30 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
const BaseView = require('./base_view.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class HelpView extends BaseView {
|
class HelpView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('help');
|
||||||
this.template = this.getTemplate('help-template');
|
|
||||||
this.sectionTemplates = {};
|
this.sectionTemplates = {};
|
||||||
const sectionKeys = ['about', 'keyboard', 'search', 'comments', 'tos'];
|
const sectionKeys = ['about', 'keyboard', 'search', 'comments', 'tos'];
|
||||||
for (let section of sectionKeys) {
|
for (let section of sectionKeys) {
|
||||||
const templateName = 'help-' + section + '-template';
|
const templateName = 'help-' + section;
|
||||||
this.sectionTemplates[section] = this.getTemplate(templateName);
|
this.sectionTemplates[section] = views.getTemplate(templateName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = this.contentHolder;
|
const target = document.getElementById('content-holder');
|
||||||
const source = this.template();
|
const source = this.template();
|
||||||
|
|
||||||
ctx.section = ctx.section || 'about';
|
ctx.section = ctx.section || 'about';
|
||||||
if (!(ctx.section in this.sectionTemplates)) {
|
if (!(ctx.section in this.sectionTemplates)) {
|
||||||
this.emptyView(this.contentHolder);
|
views.emptyView(target);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showView(
|
views.showView(
|
||||||
source.querySelector('.content'),
|
source.querySelector('.content'),
|
||||||
this.sectionTemplates[ctx.section]({
|
this.sectionTemplates[ctx.section]({
|
||||||
name: config.name,
|
name: config.name,
|
||||||
|
@ -40,7 +39,8 @@ class HelpView extends BaseView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
const BaseView = require('./base_view.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class HomeView extends BaseView {
|
class HomeView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('home');
|
||||||
this.template = this.getTemplate('home-template');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = this.contentHolder;
|
const target = document.getElementById('content-holder');
|
||||||
const source = this.template({
|
const source = this.template({
|
||||||
name: config.name,
|
name: config.name,
|
||||||
version: config.meta.version,
|
version: config.meta.version,
|
||||||
buildDate: config.meta.buildDate,
|
buildDate: config.meta.buildDate,
|
||||||
});
|
});
|
||||||
this.showView(target, source);
|
|
||||||
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
const events = require('../events.js');
|
const views = require('../util/views.js');
|
||||||
const BaseView = require('./base_view.js');
|
|
||||||
|
|
||||||
class LoginView extends BaseView {
|
class LoginView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('login');
|
||||||
this.template = this.getTemplate('login-template');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = this.contentHolder;
|
const target = document.getElementById('content-holder');
|
||||||
const source = this.template({canSendMails: config.canSendMails});
|
const source = this.template({canSendMails: config.canSendMails});
|
||||||
|
|
||||||
const form = source.querySelector('form');
|
const form = source.querySelector('form');
|
||||||
|
@ -19,22 +17,23 @@ class LoginView extends BaseView {
|
||||||
const passwordField = source.querySelector('#user-password');
|
const passwordField = source.querySelector('#user-password');
|
||||||
const rememberUserField = source.querySelector('#remember-user');
|
const rememberUserField = source.querySelector('#remember-user');
|
||||||
|
|
||||||
this.decorateValidator(form);
|
views.decorateValidator(form);
|
||||||
userNameField.setAttribute('pattern', config.userNameRegex);
|
userNameField.setAttribute('pattern', config.userNameRegex);
|
||||||
passwordField.setAttribute('pattern', config.passwordRegex);
|
passwordField.setAttribute('pattern', config.passwordRegex);
|
||||||
|
|
||||||
form.addEventListener('submit', e => {
|
form.addEventListener('submit', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.clearMessages();
|
views.clearMessages(target);
|
||||||
this.disableForm(form);
|
views.disableForm(form);
|
||||||
ctx.login(
|
ctx.login(
|
||||||
userNameField.value,
|
userNameField.value,
|
||||||
passwordField.value,
|
passwordField.value,
|
||||||
rememberUserField.checked)
|
rememberUserField.checked)
|
||||||
.always(() => { this.enableForm(form); });
|
.always(() => { views.enableForm(form); });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,31 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const events = require('../events.js');
|
const views = require('../util/views.js');
|
||||||
const BaseView = require('./base_view.js');
|
|
||||||
|
|
||||||
class PasswordResetView extends BaseView {
|
class PasswordResetView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('password-reset');
|
||||||
this.template = this.getTemplate('password-reset-template');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = this.contentHolder;
|
const target = document.getElementById('content-holder');
|
||||||
const source = this.template();
|
const source = this.template();
|
||||||
|
|
||||||
const form = source.querySelector('form');
|
const form = source.querySelector('form');
|
||||||
const userNameOrEmailField = source.querySelector('#user-name');
|
const userNameOrEmailField = source.querySelector('#user-name');
|
||||||
|
|
||||||
this.decorateValidator(form);
|
views.decorateValidator(form);
|
||||||
|
|
||||||
form.addEventListener('submit', e => {
|
form.addEventListener('submit', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.clearMessages();
|
views.clearMessages(target);
|
||||||
this.disableForm(form);
|
views.disableForm(form);
|
||||||
ctx.proceed(userNameOrEmailField.value)
|
ctx.proceed(userNameOrEmailField.value)
|
||||||
.catch(() => { this.enableForm(form); });
|
.catch(() => { views.enableForm(form); });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
const events = require('../events.js');
|
const views = require('../util/views.js');
|
||||||
const BaseView = require('./base_view.js');
|
|
||||||
|
|
||||||
class RegistrationView extends BaseView {
|
class RegistrationView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('user-registration');
|
||||||
this.template = this.getTemplate('user-registration-template');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = this.contentHolder;
|
const target = document.getElementById('content-holder');
|
||||||
const source = this.template();
|
const source = this.template();
|
||||||
|
|
||||||
const form = source.querySelector('form');
|
const form = source.querySelector('form');
|
||||||
|
@ -19,22 +17,23 @@ class RegistrationView extends BaseView {
|
||||||
const passwordField = source.querySelector('#user-password');
|
const passwordField = source.querySelector('#user-password');
|
||||||
const emailField = source.querySelector('#user-email');
|
const emailField = source.querySelector('#user-email');
|
||||||
|
|
||||||
this.decorateValidator(form);
|
views.decorateValidator(form);
|
||||||
userNameField.setAttribute('pattern', config.userNameRegex);
|
userNameField.setAttribute('pattern', config.userNameRegex);
|
||||||
passwordField.setAttribute('pattern', config.passwordRegex);
|
passwordField.setAttribute('pattern', config.passwordRegex);
|
||||||
|
|
||||||
form.addEventListener('submit', e => {
|
form.addEventListener('submit', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.clearMessages();
|
views.clearMessages(target);
|
||||||
this.disableForm(form);
|
views.disableForm(form);
|
||||||
ctx.register(
|
ctx.register(
|
||||||
userNameField.value,
|
userNameField.value,
|
||||||
passwordField.value,
|
passwordField.value,
|
||||||
emailField.value)
|
emailField.value)
|
||||||
.always(() => { this.enableForm(form); });
|
.always(() => { views.enableForm(form); });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const BaseView = require('./base_view.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class TopNavView extends BaseView {
|
class TopNavView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('top-nav');
|
||||||
this.template = this.getTemplate('top-nav-template');
|
|
||||||
this.navHolder = document.getElementById('top-nav-holder');
|
this.navHolder = document.getElementById('top-nav-holder');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +20,7 @@ class TopNavView extends BaseView {
|
||||||
'<span class="access-key" data-accesskey="$1">$1</span>');
|
'<span class="access-key" data-accesskey="$1">$1</span>');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showView(this.navHolder, source);
|
views.showView(this.navHolder, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
activate(itemName) {
|
activate(itemName) {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const BaseView = require('./base_view.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class UserDeletionView extends BaseView {
|
class UserDeletionView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('user-deletion');
|
||||||
this.template = this.getTemplate('user-deletion-template');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
|
@ -14,16 +13,17 @@ class UserDeletionView extends BaseView {
|
||||||
|
|
||||||
const form = source.querySelector('form');
|
const form = source.querySelector('form');
|
||||||
|
|
||||||
this.decorateValidator(form);
|
views.decorateValidator(form);
|
||||||
|
|
||||||
form.addEventListener('submit', e => {
|
form.addEventListener('submit', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.clearMessages();
|
views.clearMessages(target);
|
||||||
this.disableForm(form);
|
views.disableForm(form);
|
||||||
ctx.delete();
|
ctx.delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
const BaseView = require('./base_view.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class UserEditView extends BaseView {
|
class UserEditView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('user-edit');
|
||||||
this.template = this.getTemplate('user-edit-template');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
|
@ -19,7 +18,7 @@ class UserEditView extends BaseView {
|
||||||
const userNameField = source.querySelector('#user-name');
|
const userNameField = source.querySelector('#user-name');
|
||||||
const passwordField = source.querySelector('#user-password');
|
const passwordField = source.querySelector('#user-password');
|
||||||
|
|
||||||
this.decorateValidator(form);
|
views.decorateValidator(form);
|
||||||
|
|
||||||
if (userNameField) {
|
if (userNameField) {
|
||||||
userNameField.setAttribute(
|
userNameField.setAttribute(
|
||||||
|
@ -41,17 +40,18 @@ class UserEditView extends BaseView {
|
||||||
|
|
||||||
form.addEventListener('submit', e => {
|
form.addEventListener('submit', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.clearMessages();
|
views.clearMessages(target);
|
||||||
this.disableForm(form);
|
views.disableForm(form);
|
||||||
ctx.edit(
|
ctx.edit(
|
||||||
userNameField.value,
|
userNameField.value,
|
||||||
passwordField.value,
|
passwordField.value,
|
||||||
emailField.value,
|
emailField.value,
|
||||||
rankField.value)
|
rankField.value)
|
||||||
.always(() => { this.enableForm(form); });
|
.always(() => { views.enableForm(form); });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const BaseView = require('./base_view.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class UserSummaryView extends BaseView {
|
class UserSummaryView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('user-summary');
|
||||||
this.template = this.getTemplate('user-summary-template');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = ctx.target;
|
const target = ctx.target;
|
||||||
const source = this.template(ctx);
|
const source = this.template(ctx);
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const BaseView = require('./base_view.js');
|
const views = require('../util/views.js');
|
||||||
const UserDeletionView = require('./user_deletion_view.js');
|
const UserDeletionView = require('./user_deletion_view.js');
|
||||||
const UserSummaryView = require('./user_summary_view.js');
|
const UserSummaryView = require('./user_summary_view.js');
|
||||||
const UserEditView = require('./user_edit_view.js');
|
const UserEditView = require('./user_edit_view.js');
|
||||||
|
|
||||||
class UserView extends BaseView {
|
class UserView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.template = views.getTemplate('user');
|
||||||
this.template = this.getTemplate('user-template');
|
|
||||||
this.deletionView = new UserDeletionView();
|
this.deletionView = new UserDeletionView();
|
||||||
this.summaryView = new UserSummaryView();
|
this.summaryView = new UserSummaryView();
|
||||||
this.editView = new UserEditView();
|
this.editView = new UserEditView();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = this.contentHolder;
|
const target = document.getElementById('content-holder');
|
||||||
const source = this.template(ctx);
|
const source = this.template(ctx);
|
||||||
|
|
||||||
ctx.section = ctx.section || 'summary';
|
ctx.section = ctx.section || 'summary';
|
||||||
|
@ -39,7 +38,8 @@ class UserView extends BaseView {
|
||||||
ctx.target = source.querySelector('#user-content-holder');
|
ctx.target = source.querySelector('#user-content-holder');
|
||||||
view.render(ctx);
|
view.render(ctx);
|
||||||
|
|
||||||
this.showView(target, source);
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue