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
|
||||
margin: 0
|
||||
padding: 0
|
||||
|
||||
li
|
||||
margin-top: 0.5em
|
||||
|
||||
label
|
||||
display: block
|
||||
padding: 0.5em 0
|
||||
|
||||
.input
|
||||
margin-bottom: 1em
|
||||
|
||||
.buttons
|
||||
margin-top: 1em
|
||||
|
||||
.input li:first-child label:not(.radio):not(.checkbox):not(.file-dropper),
|
||||
.input li:first-child
|
||||
padding-top: 0
|
||||
margin-top: 0
|
||||
|
||||
.hint
|
||||
margin-top: 0.5em
|
||||
margin-bottom: 0
|
||||
|
@ -38,17 +32,24 @@ form.tabular
|
|||
ul
|
||||
display: table
|
||||
width: 100%
|
||||
|
||||
li
|
||||
display: table-row
|
||||
|
||||
label:not(.radio):not(.checkbox):not(.file-dropper)
|
||||
display: table-cell
|
||||
width: 33%
|
||||
|
||||
.messages, .buttons
|
||||
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
|
||||
padding: 0
|
||||
display: flex
|
||||
justify-content: center
|
||||
align-content: flex-end
|
||||
flex-wrap: wrap
|
||||
margin: 0 -0.5em 0 -0.5em
|
||||
li
|
||||
flex-grow: 1
|
||||
width: 20em
|
||||
margin: 0 0.5em 1em 0.5em
|
||||
padding: 0.75em
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<div class='pager'>
|
||||
<div class='page-header-holder'></div>
|
||||
<div class='messages'></div>
|
||||
<div class='page-content-holder'></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 RegistrationView = require('../views/registration_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');
|
||||
|
||||
class UsersController {
|
||||
constructor() {
|
||||
this.registrationView = new RegistrationView();
|
||||
this.userView = new UserView();
|
||||
this.userListView = new UserListView();
|
||||
this.userListHeaderView = new UserListHeaderView();
|
||||
this.userListPageView = new UserListPageView();
|
||||
this.emptyView = new EmptyView();
|
||||
}
|
||||
|
||||
|
@ -62,8 +64,9 @@ class UsersController {
|
|||
},
|
||||
clientUrl: '/users/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
initialPage: ctx.searchQuery.page,
|
||||
pageRenderer: this.userListView,
|
||||
searchQuery: ctx.searchQuery,
|
||||
headerRenderer: this.userListHeaderView,
|
||||
pageRenderer: this.userListPageView,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,17 @@ const views = require('../util/views.js');
|
|||
const handlebars = require('handlebars');
|
||||
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) {
|
||||
return new handlebars.SafeString(
|
||||
views.makeNonVoidElement(
|
||||
|
@ -34,10 +45,7 @@ handlebars.registerHelper('radio', function(options) {
|
|||
checked: options.hash.selectedValue === options.hash.value,
|
||||
required: options.hash.required,
|
||||
}),
|
||||
views.makeNonVoidElement('label', {
|
||||
for: options.hash.id,
|
||||
class: 'radio',
|
||||
}, options.hash.text)));
|
||||
makeLabel(options, {class: 'radio'})));
|
||||
});
|
||||
|
||||
handlebars.registerHelper('checkbox', function(options) {
|
||||
|
@ -51,16 +59,12 @@ handlebars.registerHelper('checkbox', function(options) {
|
|||
options.hash.checked : false,
|
||||
required: options.hash.required,
|
||||
}),
|
||||
views.makeNonVoidElement('label', {
|
||||
for: options.hash.id,
|
||||
class: 'checkbox',
|
||||
}, options.hash.text)));
|
||||
makeLabel(options, {class: 'checkbox'})));
|
||||
});
|
||||
|
||||
handlebars.registerHelper('select', function(options) {
|
||||
return new handlebars.SafeString('{0}{1}'.format(
|
||||
views.makeNonVoidElement(
|
||||
'label', {for: options.hash.id}, options.hash.text),
|
||||
makeLabel(options),
|
||||
views.makeNonVoidElement(
|
||||
'select',
|
||||
{id: options.hash.id, name: options.hash.name},
|
||||
|
@ -74,8 +78,7 @@ handlebars.registerHelper('select', function(options) {
|
|||
|
||||
handlebars.registerHelper('input', function(options) {
|
||||
return new handlebars.SafeString('{0}{1}'.format(
|
||||
views.makeNonVoidElement(
|
||||
'label', {for: options.hash.id}, options.hash.text),
|
||||
makeLabel(options),
|
||||
views.makeVoidElement(
|
||||
'input', {
|
||||
type: options.hash.inputType,
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
const page = require('page');
|
||||
const events = require('../events.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
|
||||
class EndlessPageView {
|
||||
|
@ -85,7 +84,7 @@ class EndlessPageView {
|
|||
pagesHolder.innerHTML = ctx.state.html;
|
||||
window.scroll(ctx.state.scrollX, ctx.state.scrollY);
|
||||
} else {
|
||||
this.loadPage(pagesHolder, ctx, ctx.initialPage, true);
|
||||
this.loadPage(pagesHolder, ctx, ctx.searchQuery.page, true);
|
||||
}
|
||||
window.addEventListener('scroll', this.updater, true);
|
||||
}
|
||||
|
|
|
@ -20,8 +20,13 @@ class ManualPageView {
|
|||
const target = document.getElementById('content-holder');
|
||||
const source = this.holderTemplate();
|
||||
const pageContentHolder = source.querySelector('.page-content-holder');
|
||||
const pageHeaderHolder = source.querySelector('.page-header-holder');
|
||||
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 => {
|
||||
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');
|
||||
|
||||
class UserListView {
|
||||
class UserListPageView {
|
||||
constructor() {
|
||||
this.template = views.getTemplate('user-list');
|
||||
this.template = views.getTemplate('user-list-page');
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
const target = ctx.target;
|
||||
const source = this.template(ctx);
|
||||
views.listenToMessages(target);
|
||||
views.showView(target, source);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserListView;
|
||||
module.exports = UserListPageView;
|
Loading…
Reference in a new issue