client/users: add filtering
This commit is contained in:
parent
90559ffcdb
commit
f34e83b325
11 changed files with 88 additions and 33 deletions
|
@ -8,25 +8,19 @@ form
|
||||||
list-style-type: none
|
list-style-type: none
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
li
|
li
|
||||||
margin-top: 0.5em
|
margin-top: 0.5em
|
||||||
|
|
||||||
label
|
label
|
||||||
display: block
|
display: block
|
||||||
padding: 0.5em 0
|
padding: 0.5em 0
|
||||||
|
|
||||||
.input
|
.input
|
||||||
margin-bottom: 1em
|
margin-bottom: 1em
|
||||||
|
|
||||||
.buttons
|
.buttons
|
||||||
margin-top: 1em
|
margin-top: 1em
|
||||||
|
|
||||||
.input li:first-child label:not(.radio):not(.checkbox):not(.file-dropper),
|
.input li:first-child label:not(.radio):not(.checkbox):not(.file-dropper),
|
||||||
.input li:first-child
|
.input li:first-child
|
||||||
padding-top: 0
|
padding-top: 0
|
||||||
margin-top: 0
|
margin-top: 0
|
||||||
|
|
||||||
.hint
|
.hint
|
||||||
margin-top: 0.5em
|
margin-top: 0.5em
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
|
@ -38,17 +32,24 @@ form.tabular
|
||||||
ul
|
ul
|
||||||
display: table
|
display: table
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
li
|
li
|
||||||
display: table-row
|
display: table-row
|
||||||
|
|
||||||
label:not(.radio):not(.checkbox):not(.file-dropper)
|
label:not(.radio):not(.checkbox):not(.file-dropper)
|
||||||
display: table-cell
|
display: table-cell
|
||||||
width: 33%
|
width: 33%
|
||||||
|
|
||||||
.messages, .buttons
|
.messages, .buttons
|
||||||
margin-left: 33%
|
margin-left: 33%
|
||||||
|
|
||||||
|
form.horizontal
|
||||||
|
display: inline-block
|
||||||
|
margin-bottom: 1em
|
||||||
|
.input, .buttons, ul
|
||||||
|
display: inline-block
|
||||||
|
margin: 0
|
||||||
|
padding: 0
|
||||||
|
.buttons
|
||||||
|
margin-right: 0.5em
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -76,11 +76,11 @@
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
display: flex
|
display: flex
|
||||||
justify-content: center
|
|
||||||
align-content: flex-end
|
align-content: flex-end
|
||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
margin: 0 -0.5em 0 -0.5em
|
margin: 0 -0.5em 0 -0.5em
|
||||||
li
|
li
|
||||||
|
flex-grow: 1
|
||||||
width: 20em
|
width: 20em
|
||||||
margin: 0 0.5em 1em 0.5em
|
margin: 0 0.5em 1em 0.5em
|
||||||
padding: 0.75em
|
padding: 0.75em
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<div class='pager'>
|
<div class='pager'>
|
||||||
|
<div class='page-header-holder'></div>
|
||||||
<div class='messages'></div>
|
<div class='messages'></div>
|
||||||
<div class='page-content-holder'></div>
|
<div class='page-content-holder'></div>
|
||||||
<div class='page-nav'></div>
|
<div class='page-nav'></div>
|
||||||
|
|
14
client/html/user_list_header.hbs
Normal file
14
client/html/user_list_header.hbs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<div class='user-list-header'>
|
||||||
|
<form class='horizontal'>
|
||||||
|
<div class='input'>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
{{textInput id='search-text' name='search-text' value=this.searchQuery.text}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class='buttons'>
|
||||||
|
<input type='submit' value='Search'/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -10,14 +10,16 @@ const topNavController = require('../controllers/top_nav_controller.js');
|
||||||
const pageController = require('../controllers/page_controller.js');
|
const pageController = require('../controllers/page_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');
|
||||||
const UserListView = require('../views/user_list_view.js');
|
const UserListHeaderView = require('../views/user_list_header_view.js');
|
||||||
|
const UserListPageView = require('../views/user_list_page_view.js');
|
||||||
const EmptyView = require('../views/empty_view.js');
|
const EmptyView = require('../views/empty_view.js');
|
||||||
|
|
||||||
class UsersController {
|
class UsersController {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.registrationView = new RegistrationView();
|
this.registrationView = new RegistrationView();
|
||||||
this.userView = new UserView();
|
this.userView = new UserView();
|
||||||
this.userListView = new UserListView();
|
this.userListHeaderView = new UserListHeaderView();
|
||||||
|
this.userListPageView = new UserListPageView();
|
||||||
this.emptyView = new EmptyView();
|
this.emptyView = new EmptyView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +64,9 @@ class UsersController {
|
||||||
},
|
},
|
||||||
clientUrl: '/users/' + misc.formatSearchQuery({
|
clientUrl: '/users/' + misc.formatSearchQuery({
|
||||||
text: ctx.searchQuery.text, page: '{page}'}),
|
text: ctx.searchQuery.text, page: '{page}'}),
|
||||||
initialPage: ctx.searchQuery.page,
|
searchQuery: ctx.searchQuery,
|
||||||
pageRenderer: this.userListView,
|
headerRenderer: this.userListHeaderView,
|
||||||
|
pageRenderer: this.userListPageView,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,17 @@ const views = require('../util/views.js');
|
||||||
const handlebars = require('handlebars');
|
const handlebars = require('handlebars');
|
||||||
const misc = require('./misc.js');
|
const misc = require('./misc.js');
|
||||||
|
|
||||||
|
function makeLabel(options, attrs) {
|
||||||
|
if (!options.hash.text) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (!attrs) {
|
||||||
|
attrs = {};
|
||||||
|
}
|
||||||
|
attrs.for = options.hash.id;
|
||||||
|
return views.makeNonVoidElement('label', attrs, options.hash.text);
|
||||||
|
}
|
||||||
|
|
||||||
handlebars.registerHelper('reltime', function(time) {
|
handlebars.registerHelper('reltime', function(time) {
|
||||||
return new handlebars.SafeString(
|
return new handlebars.SafeString(
|
||||||
views.makeNonVoidElement(
|
views.makeNonVoidElement(
|
||||||
|
@ -34,10 +45,7 @@ handlebars.registerHelper('radio', function(options) {
|
||||||
checked: options.hash.selectedValue === options.hash.value,
|
checked: options.hash.selectedValue === options.hash.value,
|
||||||
required: options.hash.required,
|
required: options.hash.required,
|
||||||
}),
|
}),
|
||||||
views.makeNonVoidElement('label', {
|
makeLabel(options, {class: 'radio'})));
|
||||||
for: options.hash.id,
|
|
||||||
class: 'radio',
|
|
||||||
}, options.hash.text)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handlebars.registerHelper('checkbox', function(options) {
|
handlebars.registerHelper('checkbox', function(options) {
|
||||||
|
@ -51,16 +59,12 @@ handlebars.registerHelper('checkbox', function(options) {
|
||||||
options.hash.checked : false,
|
options.hash.checked : false,
|
||||||
required: options.hash.required,
|
required: options.hash.required,
|
||||||
}),
|
}),
|
||||||
views.makeNonVoidElement('label', {
|
makeLabel(options, {class: 'checkbox'})));
|
||||||
for: options.hash.id,
|
|
||||||
class: 'checkbox',
|
|
||||||
}, options.hash.text)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handlebars.registerHelper('select', function(options) {
|
handlebars.registerHelper('select', function(options) {
|
||||||
return new handlebars.SafeString('{0}{1}'.format(
|
return new handlebars.SafeString('{0}{1}'.format(
|
||||||
views.makeNonVoidElement(
|
makeLabel(options),
|
||||||
'label', {for: options.hash.id}, options.hash.text),
|
|
||||||
views.makeNonVoidElement(
|
views.makeNonVoidElement(
|
||||||
'select',
|
'select',
|
||||||
{id: options.hash.id, name: options.hash.name},
|
{id: options.hash.id, name: options.hash.name},
|
||||||
|
@ -74,8 +78,7 @@ handlebars.registerHelper('select', function(options) {
|
||||||
|
|
||||||
handlebars.registerHelper('input', function(options) {
|
handlebars.registerHelper('input', function(options) {
|
||||||
return new handlebars.SafeString('{0}{1}'.format(
|
return new handlebars.SafeString('{0}{1}'.format(
|
||||||
views.makeNonVoidElement(
|
makeLabel(options),
|
||||||
'label', {for: options.hash.id}, options.hash.text),
|
|
||||||
views.makeVoidElement(
|
views.makeVoidElement(
|
||||||
'input', {
|
'input', {
|
||||||
type: options.hash.inputType,
|
type: options.hash.inputType,
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
const page = require('page');
|
const page = require('page');
|
||||||
const events = require('../events.js');
|
const events = require('../events.js');
|
||||||
const misc = require('../util/misc.js');
|
|
||||||
const views = require('../util/views.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class EndlessPageView {
|
class EndlessPageView {
|
||||||
|
@ -85,7 +84,7 @@ class EndlessPageView {
|
||||||
pagesHolder.innerHTML = ctx.state.html;
|
pagesHolder.innerHTML = ctx.state.html;
|
||||||
window.scroll(ctx.state.scrollX, ctx.state.scrollY);
|
window.scroll(ctx.state.scrollX, ctx.state.scrollY);
|
||||||
} else {
|
} else {
|
||||||
this.loadPage(pagesHolder, ctx, ctx.initialPage, true);
|
this.loadPage(pagesHolder, ctx, ctx.searchQuery.page, true);
|
||||||
}
|
}
|
||||||
window.addEventListener('scroll', this.updater, true);
|
window.addEventListener('scroll', this.updater, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,13 @@ class ManualPageView {
|
||||||
const target = document.getElementById('content-holder');
|
const target = document.getElementById('content-holder');
|
||||||
const source = this.holderTemplate();
|
const source = this.holderTemplate();
|
||||||
const pageContentHolder = source.querySelector('.page-content-holder');
|
const pageContentHolder = source.querySelector('.page-content-holder');
|
||||||
|
const pageHeaderHolder = source.querySelector('.page-header-holder');
|
||||||
const pageNav = source.querySelector('.page-nav');
|
const pageNav = source.querySelector('.page-nav');
|
||||||
const currentPage = ctx.initialPage;
|
const currentPage = ctx.searchQuery.page;
|
||||||
|
|
||||||
|
let headerRendererCtx = ctx;
|
||||||
|
headerRendererCtx.target = pageHeaderHolder;
|
||||||
|
ctx.headerRenderer.render(headerRendererCtx);
|
||||||
|
|
||||||
ctx.requestPage(currentPage).then(response => {
|
ctx.requestPage(currentPage).then(response => {
|
||||||
let pageRendererCtx = response;
|
let pageRendererCtx = response;
|
||||||
|
|
30
client/js/views/user_list_header_view.js
Normal file
30
client/js/views/user_list_header_view.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const page = require('page');
|
||||||
|
const misc = require('../util/misc.js');
|
||||||
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
|
class UserListHeaderView {
|
||||||
|
constructor() {
|
||||||
|
this.template = views.getTemplate('user-list-header');
|
||||||
|
}
|
||||||
|
|
||||||
|
render(ctx) {
|
||||||
|
const target = ctx.target;
|
||||||
|
const source = this.template(ctx);
|
||||||
|
|
||||||
|
const form = source.querySelector('form');
|
||||||
|
|
||||||
|
form.addEventListener('submit', e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const searchTextInput = form.querySelector('[name=search-text]');
|
||||||
|
const text = searchTextInput.value;
|
||||||
|
searchTextInput.blur();
|
||||||
|
page('/users/' + misc.formatSearchQuery({text: text}));
|
||||||
|
});
|
||||||
|
|
||||||
|
views.showView(target, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserListHeaderView;
|
|
@ -2,17 +2,16 @@
|
||||||
|
|
||||||
const views = require('../util/views.js');
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
class UserListView {
|
class UserListPageView {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.template = views.getTemplate('user-list');
|
this.template = views.getTemplate('user-list-page');
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
const target = ctx.target;
|
const target = ctx.target;
|
||||||
const source = this.template(ctx);
|
const source = this.template(ctx);
|
||||||
views.listenToMessages(target);
|
|
||||||
views.showView(target, source);
|
views.showView(target, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = UserListView;
|
module.exports = UserListPageView;
|
Loading…
Reference in a new issue