client/tags: add tag listing
This commit is contained in:
parent
c55fb2ef41
commit
266f5c027f
|
@ -0,0 +1,27 @@
|
|||
@import colors
|
||||
|
||||
.tag-list
|
||||
table
|
||||
width: 100%
|
||||
text-align: left
|
||||
.usages
|
||||
text-align: center
|
||||
ul
|
||||
list-style-type: none
|
||||
margin: 0
|
||||
padding: 0
|
||||
display: inline
|
||||
li
|
||||
padding: 0
|
||||
display: inline
|
||||
&:not(:last-child):after
|
||||
content: ', '
|
||||
.tag-list-header
|
||||
text-align: left
|
||||
form
|
||||
width: auto
|
||||
input[name=search-text]
|
||||
max-width: 15em
|
||||
.append
|
||||
font-size: 0.95em
|
||||
color: $inactive-link-color
|
|
@ -0,0 +1,15 @@
|
|||
<div class='tag-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'/>
|
||||
<a class='append' href='/help/search/tags'>Syntax help</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,50 @@
|
|||
<div class='tag-list'>
|
||||
{{#if this.results}}
|
||||
<table>
|
||||
<thead>
|
||||
<th class='names'>Tag name(s)</th>
|
||||
<th class='implications'>Implications</th>
|
||||
<th class='suggestions'>Suggestions</th>
|
||||
<th class='usages'>Usages</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each this.results}}
|
||||
<tr>
|
||||
<td class='names'>
|
||||
<ul>
|
||||
{{#each this.names}}
|
||||
<li><a href='/tag/{{this}}'>{{this}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</td>
|
||||
<td class='implications'>
|
||||
{{#if this.implications}}
|
||||
<ul>
|
||||
{{#each this.implications}}
|
||||
<li><a href='/tag/{{this}}'>{{this}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
-
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class='suggestions'>
|
||||
{{#if this.suggestions}}
|
||||
<ul>
|
||||
{{#each this.suggestions}}
|
||||
<li><a href='/tag/{{this}}'>{{this}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
-
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class='usages'>
|
||||
{{this.usages}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
||||
</div>
|
|
@ -1,15 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
const page = require('page');
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const topNavController = require('../controllers/top_nav_controller.js');
|
||||
const pageController = require('../controllers/page_controller.js');
|
||||
const TagListHeaderView = require('../views/tag_list_header_view.js');
|
||||
const TagListPageView = require('../views/tag_list_page_view.js');
|
||||
|
||||
class TagsController {
|
||||
registerRoutes() {
|
||||
page('/tags', (ctx, next) => { this.listTagsRoute(); });
|
||||
constructor() {
|
||||
this.tagListHeaderView = new TagListHeaderView();
|
||||
this.tagListPageView = new TagListPageView();
|
||||
}
|
||||
|
||||
listTagsRoute() {
|
||||
registerRoutes() {
|
||||
page(
|
||||
'/tags/:query?',
|
||||
(ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
|
||||
(ctx, next) => { this.listTagsRoute(ctx, next); });
|
||||
}
|
||||
|
||||
listTagsRoute(ctx, next) {
|
||||
topNavController.activate('tags');
|
||||
|
||||
pageController.run({
|
||||
state: ctx.state,
|
||||
requestPage: page => {
|
||||
return api.get(
|
||||
'/tags/?query={text}&page={page}&pageSize=50'.format({
|
||||
text: ctx.searchQuery.text,
|
||||
page: page}));
|
||||
},
|
||||
clientUrl: '/tags/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
searchQuery: ctx.searchQuery,
|
||||
headerRenderer: this.tagListHeaderView,
|
||||
pageRenderer: this.tagListPageView,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
const page = require('page');
|
||||
const keyboard = require('../util/keyboard.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
|
||||
class TagListHeaderView {
|
||||
constructor() {
|
||||
this.template = views.getTemplate('tag-list-header');
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
const target = ctx.target;
|
||||
const source = this.template(ctx);
|
||||
|
||||
const form = source.querySelector('form');
|
||||
|
||||
keyboard.bind('q', () => {
|
||||
form.querySelector('input').focus();
|
||||
});
|
||||
|
||||
form.addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
const searchTextInput = form.querySelector('[name=search-text]');
|
||||
const text = searchTextInput.value;
|
||||
searchTextInput.blur();
|
||||
page('/tags/' + misc.formatSearchQuery({text: text}));
|
||||
});
|
||||
|
||||
views.showView(target, source);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TagListHeaderView;
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
const views = require('../util/views.js');
|
||||
|
||||
class TagListPageView {
|
||||
constructor() {
|
||||
this.template = views.getTemplate('tag-list-page');
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
const target = ctx.target;
|
||||
const source = this.template(ctx);
|
||||
views.showView(target, source);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TagListPageView;
|
Loading…
Reference in New Issue