From f34e83b3255b446dbfcdfca8727e37586274be05 Mon Sep 17 00:00:00 2001 From: rr- Date: Thu, 14 Apr 2016 12:11:31 +0200 Subject: [PATCH] client/users: add filtering --- client/css/forms.styl | 19 ++++++------ client/css/users.styl | 2 +- client/html/manual_pager.hbs | 1 + client/html/user_list_header.hbs | 14 +++++++++ .../{user_list.hbs => user_list_page.hbs} | 0 client/js/controllers/users_controller.js | 11 ++++--- client/js/util/handlebars-helpers.js | 27 +++++++++-------- client/js/views/endless_page_view.js | 3 +- client/js/views/manual_page_view.js | 7 ++++- client/js/views/user_list_header_view.js | 30 +++++++++++++++++++ ...er_list_view.js => user_list_page_view.js} | 7 ++--- 11 files changed, 88 insertions(+), 33 deletions(-) create mode 100644 client/html/user_list_header.hbs rename client/html/{user_list.hbs => user_list_page.hbs} (100%) create mode 100644 client/js/views/user_list_header_view.js rename client/js/views/{user_list_view.js => user_list_page_view.js} (60%) diff --git a/client/css/forms.styl b/client/css/forms.styl index b61aa41..f6c684b 100644 --- a/client/css/forms.styl +++ b/client/css/forms.styl @@ -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 + /* diff --git a/client/css/users.styl b/client/css/users.styl index 735dee2..4d783f5 100644 --- a/client/css/users.styl +++ b/client/css/users.styl @@ -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 diff --git a/client/html/manual_pager.hbs b/client/html/manual_pager.hbs index 4bef243..68aadf3 100644 --- a/client/html/manual_pager.hbs +++ b/client/html/manual_pager.hbs @@ -1,4 +1,5 @@
+
diff --git a/client/html/user_list_header.hbs b/client/html/user_list_header.hbs new file mode 100644 index 0000000..b340f02 --- /dev/null +++ b/client/html/user_list_header.hbs @@ -0,0 +1,14 @@ +
+
+
+
    +
  • + {{textInput id='search-text' name='search-text' value=this.searchQuery.text}} +
  • +
+
+
+ +
+
+
diff --git a/client/html/user_list.hbs b/client/html/user_list_page.hbs similarity index 100% rename from client/html/user_list.hbs rename to client/html/user_list_page.hbs diff --git a/client/js/controllers/users_controller.js b/client/js/controllers/users_controller.js index e9cf54c..68d18f7 100644 --- a/client/js/controllers/users_controller.js +++ b/client/js/controllers/users_controller.js @@ -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, }); } diff --git a/client/js/util/handlebars-helpers.js b/client/js/util/handlebars-helpers.js index 712782f..d08a1d9 100644 --- a/client/js/util/handlebars-helpers.js +++ b/client/js/util/handlebars-helpers.js @@ -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, diff --git a/client/js/views/endless_page_view.js b/client/js/views/endless_page_view.js index 5c813ef..e0248f0 100644 --- a/client/js/views/endless_page_view.js +++ b/client/js/views/endless_page_view.js @@ -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); } diff --git a/client/js/views/manual_page_view.js b/client/js/views/manual_page_view.js index 736999f..3d91600 100644 --- a/client/js/views/manual_page_view.js +++ b/client/js/views/manual_page_view.js @@ -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; diff --git a/client/js/views/user_list_header_view.js b/client/js/views/user_list_header_view.js new file mode 100644 index 0000000..3719ce1 --- /dev/null +++ b/client/js/views/user_list_header_view.js @@ -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; diff --git a/client/js/views/user_list_view.js b/client/js/views/user_list_page_view.js similarity index 60% rename from client/js/views/user_list_view.js rename to client/js/views/user_list_page_view.js index ab36637..ea9b99d 100644 --- a/client/js/views/user_list_view.js +++ b/client/js/views/user_list_page_view.js @@ -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;