client/general: refactor URL parameter handling
This commit is contained in:
parent
cd1f4709f0
commit
5ac5eb5503
31 changed files with 132 additions and 127 deletions
|
@ -3,11 +3,7 @@
|
|||
<nav class='buttons'>
|
||||
<article class='next-post'>
|
||||
<% if (ctx.nextPostId) { %>
|
||||
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
|
||||
<a href='/post/<%- encodeURIComponent(ctx.nextPostId) %>/text=<%- encodeURIComponent(ctx.searchQuery.text) %>'>
|
||||
<% } else { %>
|
||||
<a href='/post/<%- encodeURIComponent(ctx.nextPostId) %>'>
|
||||
<% } %>
|
||||
<a href='<%= ctx.getPostUrl(ctx.nextPostId, ctx.parameters) %>'>
|
||||
<% } else { %>
|
||||
<a class='inactive'>
|
||||
<% } %>
|
||||
|
@ -17,11 +13,7 @@
|
|||
</article>
|
||||
<article class='previous-post'>
|
||||
<% if (ctx.prevPostId) { %>
|
||||
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
|
||||
<a href='/post/<%- encodeURIComponent(ctx.prevPostId) %>/text=<%- encodeURIComponent(ctx.searchQuery.text) %>'>
|
||||
<% } else { %>
|
||||
<a href='/post/<%- encodeURIComponent(ctx.prevPostId) %>'>
|
||||
<% } %>
|
||||
<a href='<%= ctx.getPostUrl(ctx.prevPostId, ctx.parameters) %>'>
|
||||
<% } else { %>
|
||||
<a class='inactive'>
|
||||
<% } %>
|
||||
|
@ -37,11 +29,7 @@
|
|||
</a>
|
||||
<% } else { %>
|
||||
<% if (ctx.canEditPosts) { %>
|
||||
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
|
||||
<a href='/post/<%- encodeURIComponent(ctx.post.id) %>/edit/text=<%- encodeURIComponent(ctx.searchQuery.text) %>'>
|
||||
<% } else { %>
|
||||
<a href='/post/<%- encodeURIComponent(ctx.post.id) %>/edit'>
|
||||
<% } %>
|
||||
<a href='<%= ctx.getPostEditUrl(ctx.post.id, ctx.parameters) %>'>
|
||||
<% } else { %>
|
||||
<a class='inactive'>
|
||||
<% } %>
|
||||
|
|
|
@ -51,11 +51,7 @@
|
|||
<ul><!--
|
||||
--><% for (let post of ctx.post.relations) { %><!--
|
||||
--><li><!--
|
||||
--><% if (ctx.searchQuery && ctx.searchQuery.text) { %><!--
|
||||
--><a href='/post/<%- encodeURIComponent(post.id) %>/text=<%- encodeURIComponent(ctx.searchQuery.text) %>'><!--
|
||||
--><% } else { %><!--
|
||||
--><a href='/post/<%- encodeURIComponent(post.id) %>'><!--
|
||||
--><% } %><!--
|
||||
--><a href='<%= ctx.getPostUrl(post.id, ctx.parameters) %>'><!--
|
||||
--><%= ctx.makeThumbnail(post.thumbnailUrl) %><!--
|
||||
--></a><!--
|
||||
--></li><!--
|
||||
|
@ -77,7 +73,7 @@
|
|||
--></a><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canListPosts) { %><!--
|
||||
--><a href='/posts/text=<%- encodeURIComponent(tag) %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
|
||||
--><a href='/posts/query=<%- encodeURIComponent(tag) %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
|
||||
--><% } %><!--
|
||||
--><%- tag %><!--
|
||||
--><% if (ctx.canListPosts) { %><!--
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class='post-list-header'>
|
||||
<form class='horizontal search'>
|
||||
<%= ctx.makeTextInput({text: 'Search query', id: 'search-text', name: 'search-text', value: ctx.searchQuery.text}) %>
|
||||
<%= ctx.makeTextInput({text: 'Search query', id: 'search-text', name: 'search-text', value: ctx.parameters.query}) %>
|
||||
<input class='mousetrap' type='submit' value='Search'/>
|
||||
<input data-safety=safe type='button' class='mousetrap safety safety-safe <%- ctx.settings.listPosts.safe ? '' : 'disabled' %>'/>
|
||||
<input data-safety=sketchy type='button' class='mousetrap safety safety-sketchy <%- ctx.settings.listPosts.sketchy ? '' : 'disabled' %>'/>
|
||||
|
@ -9,12 +9,12 @@
|
|||
</form>
|
||||
<% if (ctx.canMassTag) { %>
|
||||
<form class='masstag horizontal'>
|
||||
<% if (ctx.searchQuery.tag) { %>
|
||||
<% if (ctx.parameters.tag) { %>
|
||||
<span class='append'>Tagging with:</span>
|
||||
<% } else { %>
|
||||
<a class='mousetrap button append open-masstag' href='#'>Mass tag</a>
|
||||
<% } %>
|
||||
<%= ctx.makeTextInput({name: 'masstag', value: ctx.searchQuery.tag}) %>
|
||||
<%= ctx.makeTextInput({name: 'masstag', value: ctx.parameters.tag}) %>
|
||||
<input class='mousetrap start-tagging' type='submit' value='Start tagging'/>
|
||||
<a class='mousetrap button append stop-tagging' href='#'>Stop tagging</a>
|
||||
</form>
|
||||
|
|
|
@ -4,11 +4,7 @@
|
|||
<% for (let post of ctx.results) { %>
|
||||
<li>
|
||||
<% if (ctx.canViewPosts) { %>
|
||||
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
|
||||
<a class='thumbnail-wrapper' href='/post/<%- encodeURIComponent(post.id) %>/text=<%- encodeURIComponent(ctx.searchQuery.text) %>' title='@<%- post.id %> (<%- post.type %>) Tags: <%- post.tags.map(tag => '#' + tag).join(' ') %>'>
|
||||
<% } else { %>
|
||||
<a class='thumbnail-wrapper' href='/post/<%- encodeURIComponent(post.id) %>' title='@<%- post.id %> (<%- post.type %>) Tags: <%- post.tags.map(tag => '#' + tag).join(' ') %>'>
|
||||
<% } %>
|
||||
<a class='thumbnail-wrapper' href='<%= ctx.getPostUrl(post.id, ctx.parameters) %>' title='@<%- post.id %> (<%- post.type %>) Tags: <%- post.tags.map(tag => '#' + tag).join(' ') %>'>
|
||||
<% } else { %>
|
||||
<a class='thumbnail-wrapper'>
|
||||
<% } %>
|
||||
|
@ -39,7 +35,7 @@
|
|||
</span>
|
||||
<% } %>
|
||||
</a>
|
||||
<% if (ctx.searchQuery && ctx.searchQuery.tag) { %>
|
||||
<% if (ctx.parameters && ctx.parameters.tag) { %>
|
||||
<a data-post-id='<%= post.id %>' class='masstag'>
|
||||
</a>
|
||||
<% } %>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</td>
|
||||
<td class='usages'>
|
||||
<% if (ctx.tagCategory.name) { %>
|
||||
<a href='/tags/text=category:<%- encodeURIComponent(ctx.tagCategory.name) %>'>
|
||||
<a href='/tags/query=category:<%- encodeURIComponent(ctx.tagCategory.name) %>'>
|
||||
<%- ctx.tagCategory.tagCount %>
|
||||
</a>
|
||||
<% } else { %>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<form>
|
||||
<% if (ctx.tag.postCount) { %>
|
||||
<p>For extra <s>paranoia</s> safety, only tags that are unused can be deleted.</p>
|
||||
<p>Check <a href='/posts/text=<%- encodeURIComponent(ctx.tag.names[0]) %>'>which posts</a> are tagged with <%- ctx.tag.names[0] %>.</p>
|
||||
<p>Check <a href='/posts/query=<%- encodeURIComponent(ctx.tag.names[0]) %>'>which posts</a> are tagged with <%- ctx.tag.names[0] %>.</p>
|
||||
<% } else { %>
|
||||
<div class='input'>
|
||||
<ul>
|
||||
|
|
|
@ -36,6 +36,6 @@
|
|||
<section class='description'>
|
||||
<hr/>
|
||||
<%= ctx.makeMarkdown(ctx.tag.description || 'This tag has no description yet.') %>
|
||||
<p>This tag has <a href='/posts/text=<%- encodeURIComponent(ctx.tag.names[0]) %>'><%- ctx.tag.postCount %> usages</a>.</p>
|
||||
<p>This tag has <a href='/posts/query=<%- encodeURIComponent(ctx.tag.names[0]) %>'><%- ctx.tag.postCount %> usages</a>.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class='input'>
|
||||
<ul>
|
||||
<li>
|
||||
<%= ctx.makeTextInput({text: 'Search query', id: 'search-text', name: 'search-text', value: ctx.searchQuery.text}) %>
|
||||
<%= ctx.makeTextInput({text: 'Search query', id: 'search-text', name: 'search-text', value: ctx.parameters.query}) %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -4,37 +4,37 @@
|
|||
<thead>
|
||||
<th class='names'>
|
||||
<% if (ctx.query == 'sort:name' || !ctx.query) { %>
|
||||
<a href='/tags/text=-sort:name'>Tag name(s)</a>
|
||||
<a href='/tags/query=-sort:name'>Tag name(s)</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/text=sort:name'>Tag name(s)</a>
|
||||
<a href='/tags/query=sort:name'>Tag name(s)</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='implications'>
|
||||
<% if (ctx.query == 'sort:implication-count') { %>
|
||||
<a href='/tags/text=-sort:implication-count'>Implications</a>
|
||||
<a href='/tags/query=-sort:implication-count'>Implications</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/text=sort:implication-count'>Implications</a>
|
||||
<a href='/tags/query=sort:implication-count'>Implications</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='suggestions'>
|
||||
<% if (ctx.query == 'sort:suggestion-count') { %>
|
||||
<a href='/tags/text=-sort:suggestion-count'>Suggestions</a>
|
||||
<a href='/tags/query=-sort:suggestion-count'>Suggestions</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/text=sort:suggestion-count'>Suggestions</a>
|
||||
<a href='/tags/query=sort:suggestion-count'>Suggestions</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='usages'>
|
||||
<% if (ctx.query == 'sort:usages') { %>
|
||||
<a href='/tags/text=-sort:usages'>Usages</a>
|
||||
<a href='/tags/query=-sort:usages'>Usages</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/text=sort:usages'>Usages</a>
|
||||
<a href='/tags/query=sort:usages'>Usages</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='edit-time'>
|
||||
<% if (ctx.query == 'sort:last-edit-time') { %>
|
||||
<a href='/tags/text=-sort:last-edit-time'>Edit time</a>
|
||||
<a href='/tags/query=-sort:last-edit-time'>Edit time</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/text=sort:last-edit-time'>Edit time</a>
|
||||
<a href='/tags/query=sort:last-edit-time'>Edit time</a>
|
||||
<% } %>
|
||||
</th>
|
||||
</thead>
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
<nav>
|
||||
<p><strong>Quick links</strong></p>
|
||||
<ul>
|
||||
<li><a href='/posts/text=submit:<%- encodeURIComponent(ctx.user.name) %>'><%- ctx.user.uploadedPostCount %> uploads</a></li>
|
||||
<li><a href='/posts/text=fav:<%- encodeURIComponent(ctx.user.name) %>'><%- ctx.user.favoritePostCount %> favorites</a></li>
|
||||
<li><a href='/posts/text=comment:<%- encodeURIComponent(ctx.user.name) %>'><%- ctx.user.commentCount %> comments</a></li>
|
||||
<li><a href='/posts/query=submit:<%- encodeURIComponent(ctx.user.name) %>'><%- ctx.user.uploadedPostCount %> uploads</a></li>
|
||||
<li><a href='/posts/query=fav:<%- encodeURIComponent(ctx.user.name) %>'><%- ctx.user.favoritePostCount %> favorites</a></li>
|
||||
<li><a href='/posts/query=comment:<%- encodeURIComponent(ctx.user.name) %>'><%- ctx.user.commentCount %> comments</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
@ -20,8 +20,8 @@
|
|||
<nav>
|
||||
<p><strong>Only visible to you</strong></p>
|
||||
<ul>
|
||||
<li><a href='/posts/text=special:liked'><%- ctx.user.likedPostCount %> liked posts</a></li>
|
||||
<li><a href='/posts/text=special:disliked'><%- ctx.user.dislikedPostCount %> disliked posts</a></li>
|
||||
<li><a href='/posts/query=special:liked'><%- ctx.user.likedPostCount %> liked posts</a></li>
|
||||
<li><a href='/posts/query=special:disliked'><%- ctx.user.dislikedPostCount %> disliked posts</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<% } %>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class='input'>
|
||||
<ul>
|
||||
<li>
|
||||
<%= ctx.makeTextInput({text: 'Search query', id: 'search-text', name: 'search-text', value: ctx.searchQuery.text}) %>
|
||||
<%= ctx.makeTextInput({text: 'Search query', id: 'search-text', name: 'search-text', value: ctx.parameters.query}) %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -14,11 +14,11 @@ class CommentsController {
|
|||
topNavigation.activate('comments');
|
||||
|
||||
this._pageController = new PageController({
|
||||
searchQuery: ctx.searchQuery,
|
||||
parameters: ctx.parameters,
|
||||
getClientUrlForPage: page => {
|
||||
const searchQuery = Object.assign(
|
||||
{}, ctx.searchQuery, {page: page});
|
||||
return '/comments/' + misc.formatSearchQuery(searchQuery);
|
||||
const parameters = Object.assign(
|
||||
{}, ctx.parameters, {page: page});
|
||||
return '/comments/' + misc.formatUrlParameters(parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return PostList.search(
|
||||
|
@ -63,7 +63,7 @@ class CommentsController {
|
|||
};
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/comments/:query?',
|
||||
(ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
|
||||
router.enter('/comments/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
(ctx, next) => { new CommentsController(ctx); });
|
||||
};
|
||||
|
|
|
@ -15,9 +15,9 @@ module.exports = router => {
|
|||
new HelpController();
|
||||
});
|
||||
router.enter('/help/:section', (ctx, next) => {
|
||||
new HelpController(ctx.params.section);
|
||||
new HelpController(ctx.parameters.section);
|
||||
});
|
||||
router.enter('/help/:section/:subsection', (ctx, next) => {
|
||||
new HelpController(ctx.params.section, ctx.params.subsection);
|
||||
new HelpController(ctx.parameters.section, ctx.parameters.subsection);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ class PageController {
|
|||
constructor(ctx) {
|
||||
const extendedContext = {
|
||||
getClientUrlForPage: ctx.getClientUrlForPage,
|
||||
searchQuery: ctx.searchQuery,
|
||||
parameters: ctx.parameters,
|
||||
};
|
||||
|
||||
ctx.headerContext = Object.assign({}, extendedContext);
|
||||
|
|
|
@ -58,6 +58,6 @@ module.exports = router => {
|
|||
});
|
||||
router.enter(/\/password-reset\/([^:]+):([^:]+)$/, (ctx, next) => {
|
||||
ctx.controller = new PasswordResetFinishController(
|
||||
ctx.params[0], ctx.params[1]);
|
||||
ctx.parameters[0], ctx.parameters[1]);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,14 +11,14 @@ const PostView = require('../views/post_view.js');
|
|||
const EmptyView = require('../views/empty_view.js');
|
||||
|
||||
class PostController {
|
||||
constructor(id, editMode, searchQuery) {
|
||||
constructor(id, editMode, parameters) {
|
||||
topNavigation.activate('posts');
|
||||
|
||||
Promise.all([
|
||||
Post.get(id),
|
||||
PostList.getAround(
|
||||
id, this._decorateSearchQuery(
|
||||
searchQuery ? searchQuery.text : '')),
|
||||
parameters ? parameters.query : '')),
|
||||
]).then(responses => {
|
||||
const [post, aroundResponse] = responses;
|
||||
this._post = post;
|
||||
|
@ -30,7 +30,7 @@ class PostController {
|
|||
canEditPosts: api.hasPrivilege('posts:edit'),
|
||||
canListComments: api.hasPrivilege('comments:list'),
|
||||
canCreateComments: api.hasPrivilege('comments:create'),
|
||||
searchQuery: searchQuery,
|
||||
parameters: parameters,
|
||||
});
|
||||
if (this._view.sidebarControl) {
|
||||
this._view.sidebarControl.addEventListener(
|
||||
|
@ -149,17 +149,17 @@ class PostController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/post/:id/edit/:query?',
|
||||
(ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
|
||||
router.enter('/post/:id/edit/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
(ctx, next) => {
|
||||
ctx.controller = new PostController(
|
||||
ctx.params.id, true, ctx.searchQuery);
|
||||
ctx.parameters.id, true, ctx.parameters);
|
||||
});
|
||||
router.enter(
|
||||
'/post/:id/:query?',
|
||||
(ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
|
||||
'/post/:id/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
(ctx, next) => {
|
||||
ctx.controller = new PostController(
|
||||
ctx.params.id, false, ctx.searchQuery);
|
||||
ctx.parameters.id, false, ctx.parameters);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -19,15 +19,15 @@ class PostListController {
|
|||
|
||||
this._ctx = ctx;
|
||||
this._pageController = new PageController({
|
||||
searchQuery: ctx.searchQuery,
|
||||
parameters: ctx.parameters,
|
||||
getClientUrlForPage: page => {
|
||||
const searchQuery = Object.assign(
|
||||
{}, ctx.searchQuery, {page: page});
|
||||
return '/posts/' + misc.formatSearchQuery(searchQuery);
|
||||
const parameters = Object.assign(
|
||||
{}, ctx.parameters, {page: page});
|
||||
return '/posts/' + misc.formatUrlParameters(parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return PostList.search(
|
||||
this._decorateSearchQuery(ctx.searchQuery.text),
|
||||
this._decorateSearchQuery(ctx.parameters.query),
|
||||
page, 40, fields);
|
||||
},
|
||||
headerRenderer: headerCtx => {
|
||||
|
@ -51,7 +51,7 @@ class PostListController {
|
|||
}
|
||||
|
||||
get _massTagTags() {
|
||||
return (this._ctx.searchQuery.tag || '').split(/\s+/).filter(s => s);
|
||||
return (this._ctx.parameters.tag || '').split(/\s+/).filter(s => s);
|
||||
}
|
||||
|
||||
_evtTag(e) {
|
||||
|
@ -91,7 +91,7 @@ class PostListController {
|
|||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/posts/:query?',
|
||||
(ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
|
||||
'/posts/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
(ctx, next) => { ctx.controller = new PostListController(ctx); });
|
||||
};
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
const api = require('../api.js');
|
||||
const tags = require('../tags.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const TagCategoryList = require('../models/tag_category_list.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const TagCategoriesView = require('../views/tag_categories_view.js');
|
||||
|
|
|
@ -10,10 +10,10 @@ const EmptyView = require('../views/empty_view.js');
|
|||
|
||||
class TagController {
|
||||
constructor(ctx, section) {
|
||||
Tag.get(ctx.params.name).then(tag => {
|
||||
Tag.get(ctx.parameters.name).then(tag => {
|
||||
topNavigation.activate('tags');
|
||||
|
||||
this._name = ctx.params.name;
|
||||
this._name = ctx.parameters.name;
|
||||
tag.addEventListener('change', e => this._evtSaved(e));
|
||||
|
||||
const categories = {};
|
||||
|
|
|
@ -16,14 +16,14 @@ class TagListController {
|
|||
topNavigation.activate('tags');
|
||||
|
||||
this._pageController = new PageController({
|
||||
searchQuery: ctx.searchQuery,
|
||||
parameters: ctx.parameters,
|
||||
getClientUrlForPage: page => {
|
||||
const searchQuery = Object.assign(
|
||||
{}, ctx.searchQuery, {page: page});
|
||||
return '/tags/' + misc.formatSearchQuery(searchQuery);
|
||||
const parameters = Object.assign(
|
||||
{}, ctx.parameters, {page: page});
|
||||
return '/tags/' + misc.formatUrlParameters(parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return TagList.search(ctx.searchQuery.text, page, 50, fields);
|
||||
return TagList.search(ctx.parameters.query, page, 50, fields);
|
||||
},
|
||||
headerRenderer: headerCtx => {
|
||||
Object.assign(headerCtx, {
|
||||
|
@ -49,7 +49,7 @@ class TagListController {
|
|||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/tags/:query?',
|
||||
(ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
|
||||
'/tags/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
(ctx, next) => { ctx.controller = new TagListController(ctx); });
|
||||
};
|
||||
|
|
|
@ -11,11 +11,11 @@ const EmptyView = require('../views/empty_view.js');
|
|||
|
||||
class UserController {
|
||||
constructor(ctx, section) {
|
||||
User.get(ctx.params.name).then(user => {
|
||||
User.get(ctx.parameters.name).then(user => {
|
||||
const isLoggedIn = api.isLoggedIn(user);
|
||||
const infix = isLoggedIn ? 'self' : 'any';
|
||||
|
||||
this._name = ctx.params.name;
|
||||
this._name = ctx.parameters.name;
|
||||
user.addEventListener('change', e => this._evtSaved(e));
|
||||
|
||||
const myRankIndex = api.user ?
|
||||
|
|
|
@ -13,14 +13,14 @@ class UserListController {
|
|||
topNavigation.activate('users');
|
||||
|
||||
this._pageController = new PageController({
|
||||
searchQuery: ctx.searchQuery,
|
||||
parameters: ctx.parameters,
|
||||
getClientUrlForPage: page => {
|
||||
const searchQuery = Object.assign(
|
||||
{}, ctx.searchQuery, {page: page});
|
||||
return '/users/' + misc.formatSearchQuery(searchQuery);
|
||||
const parameters = Object.assign(
|
||||
{}, ctx.parameters, {page: page});
|
||||
return '/users/' + misc.formatUrlParameters(parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return UserList.search(ctx.searchQuery.text, page);
|
||||
return UserList.search(ctx.parameters.query, page);
|
||||
},
|
||||
headerRenderer: headerCtx => {
|
||||
return new UsersHeaderView(headerCtx);
|
||||
|
@ -41,7 +41,7 @@ class UserListController {
|
|||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/users/:query?',
|
||||
(ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
|
||||
'/users/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
(ctx, next) => { ctx.controller = new UserListController(ctx); });
|
||||
};
|
||||
|
|
|
@ -39,7 +39,7 @@ class Context {
|
|||
this.title = document.title;
|
||||
this.state = state || {};
|
||||
this.state.path = path;
|
||||
this.params = {};
|
||||
this.parameters = {};
|
||||
}
|
||||
|
||||
pushState() {
|
||||
|
@ -61,14 +61,14 @@ class Route {
|
|||
|
||||
middleware(fn) {
|
||||
return (ctx, next) => {
|
||||
if (this.match(ctx.path, ctx.params)) {
|
||||
if (this.match(ctx.path, ctx.parameters)) {
|
||||
return fn(ctx, next);
|
||||
}
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
match(path, params) {
|
||||
match(path, parameters) {
|
||||
const keys = this.keys;
|
||||
const qsIndex = path.indexOf('?');
|
||||
const pathname = ~qsIndex ? path.slice(0, qsIndex) : path;
|
||||
|
@ -81,8 +81,9 @@ class Route {
|
|||
for (let i = 1, len = m.length; i < len; ++i) {
|
||||
const key = keys[i - 1];
|
||||
const val = _decodeURLEncodedURIComponent(m[i]);
|
||||
if (val !== undefined || !(hasOwnProperty.call(params, key.name))) {
|
||||
params[key.name] = val;
|
||||
if (val !== undefined ||
|
||||
!(hasOwnProperty.call(parameters, key.name))) {
|
||||
parameters[key.name] = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ function formatMarkdown(text) {
|
|||
'$1[$2]($2)');
|
||||
text = text.replace(/\]\(@(\d+)\)/g, '](/post/$1)');
|
||||
text = text.replace(/\]\(\+([a-zA-Z0-9_-]+)\)/g, '](/user/$1)');
|
||||
text = text.replace(/\]\(#([a-zA-Z0-9_-]+)\)/g, '](/posts/text=$1)');
|
||||
text = text.replace(/\]\(#([a-zA-Z0-9_-]+)\)/g, '](/posts/query=$1)');
|
||||
return text;
|
||||
};
|
||||
|
||||
|
@ -131,7 +131,7 @@ function formatMarkdown(text) {
|
|||
//search permalinks
|
||||
text = text.replace(
|
||||
/\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig,
|
||||
'<a href="/posts/text=$1"><code>$1</code></a>');
|
||||
'<a href="/posts/query=$1"><code>$1</code></a>');
|
||||
//spoilers
|
||||
text = text.replace(
|
||||
/\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig,
|
||||
|
@ -149,10 +149,13 @@ function formatMarkdown(text) {
|
|||
return postDecorator(marked(preDecorator(text), options));
|
||||
}
|
||||
|
||||
function formatSearchQuery(dict) {
|
||||
function formatUrlParameters(dict) {
|
||||
let result = [];
|
||||
for (let key of Object.keys(dict)) {
|
||||
const value = dict[key];
|
||||
if (key === 'parameters') {
|
||||
continue;
|
||||
}
|
||||
if (value) {
|
||||
result.push(`${key}=${value}`);
|
||||
}
|
||||
|
@ -160,19 +163,23 @@ function formatSearchQuery(dict) {
|
|||
return result.join(';');
|
||||
}
|
||||
|
||||
function parseSearchQuery(query) {
|
||||
function parseUrlParameters(query) {
|
||||
let result = {};
|
||||
for (let word of (query || '').split(/;/)) {
|
||||
const [key, value] = word.split(/=/, 2);
|
||||
result[key] = value;
|
||||
}
|
||||
result.text = result.text || '';
|
||||
result.query = result.query || '';
|
||||
result.page = parseInt(result.page || '1');
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseSearchQueryRoute(ctx, next) {
|
||||
ctx.searchQuery = parseSearchQuery(ctx.params.query || '');
|
||||
function parseUrlParametersRoute(ctx, next) {
|
||||
// ctx.parameters = {"user":...,"action":...} from /users/:user/:action
|
||||
// ctx.parameters.parameters = value of :parameters as per /url/:parameters
|
||||
Object.assign(
|
||||
ctx.parameters,
|
||||
parseUrlParameters(ctx.parameters.parameters));
|
||||
next();
|
||||
}
|
||||
|
||||
|
@ -235,9 +242,9 @@ function escapeHtml(unsafe) {
|
|||
|
||||
module.exports = {
|
||||
range: range,
|
||||
formatSearchQuery: formatSearchQuery,
|
||||
parseSearchQuery: parseSearchQuery,
|
||||
parseSearchQueryRoute: parseSearchQueryRoute,
|
||||
formatUrlParameters: formatUrlParameters,
|
||||
parseUrlParameters: parseUrlParameters,
|
||||
parseUrlParametersRoute: parseUrlParametersRoute,
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
formatFileSize: formatFileSize,
|
||||
formatMarkdown: formatMarkdown,
|
||||
|
|
|
@ -146,6 +146,22 @@ function makeColorInput(options) {
|
|||
'label', {class: 'color'}, colorInput + textInput);
|
||||
}
|
||||
|
||||
function getPostUrl(id, parameters) {
|
||||
let url = '/post/' + encodeURIComponent(id);
|
||||
if (parameters && parameters.query) {
|
||||
url += '/query=' + encodeURIComponent(parameters.query);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
function getPostEditUrl(id, parameters) {
|
||||
let url = '/post/' + encodeURIComponent(id) + '/edit';
|
||||
if (parameters && parameters.query) {
|
||||
url += '/query=' + encodeURIComponent(parameters.query);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
function makePostLink(id) {
|
||||
const text = '@' + id;
|
||||
return api.hasPrivilege('posts:view') ?
|
||||
|
@ -303,6 +319,8 @@ function getTemplate(templatePath) {
|
|||
ctx = {};
|
||||
}
|
||||
Object.assign(ctx, {
|
||||
getPostUrl: getPostUrl,
|
||||
getPostEditUrl: getPostEditUrl,
|
||||
makeRelativeTime: makeRelativeTime,
|
||||
makeFileSize: makeFileSize,
|
||||
makeMarkdown: makeMarkdown,
|
||||
|
|
|
@ -30,7 +30,7 @@ class EndlessPageView {
|
|||
ctx.headerRenderer(ctx.headerContext);
|
||||
}
|
||||
|
||||
this._loadPage(ctx, ctx.searchQuery.page, true);
|
||||
this._loadPage(ctx, ctx.parameters.page, true);
|
||||
this._probePageLoad(ctx);
|
||||
}
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ class HomeView {
|
|||
_evtFormSubmit(e) {
|
||||
e.preventDefault();
|
||||
this._searchInputNode.blur();
|
||||
router.show('/posts/' + misc.formatSearchQuery({
|
||||
text: this._searchInputNode.value}));
|
||||
router.show('/posts/' + misc.formatUrlParameters({
|
||||
query: this._searchInputNode.value}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ class ManualPageView {
|
|||
const pageHeaderHolderNode
|
||||
= sourceNode.querySelector('.page-header-holder');
|
||||
const pageNavNode = sourceNode.querySelector('.page-nav');
|
||||
const currentPage = ctx.searchQuery.page;
|
||||
const currentPage = ctx.parameters.page;
|
||||
|
||||
ctx.headerContext.hostNode = pageHeaderHolderNode;
|
||||
if (ctx.headerRenderer) {
|
||||
|
|
|
@ -53,7 +53,7 @@ class PostsHeaderView {
|
|||
'click', e => this._evtStopTaggingClick(e));
|
||||
this._massTagFormNode.addEventListener(
|
||||
'submit', e => this._evtMassTagFormSubmit(e));
|
||||
this._toggleMassTagVisibility(!!ctx.searchQuery.tag);
|
||||
this._toggleMassTagVisibility(!!ctx.parameters.tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,9 +96,9 @@ class PostsHeaderView {
|
|||
|
||||
_evtStopTaggingClick(e) {
|
||||
e.preventDefault();
|
||||
router.show('/posts/' + misc.formatSearchQuery({
|
||||
text: this._ctx.searchQuery.text,
|
||||
page: this._ctx.searchQuery.page,
|
||||
router.show('/posts/' + misc.formatUrlParameters({
|
||||
query: this._ctx.parameters.query,
|
||||
page: this._ctx.parameters.page,
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ class PostsHeaderView {
|
|||
e.preventDefault();
|
||||
const text = this._queryInputNode.value;
|
||||
this._queryInputNode.blur();
|
||||
router.show('/posts/' + misc.formatSearchQuery({text: text}));
|
||||
router.show('/posts/' + misc.formatUrlParameters({query: text}));
|
||||
}
|
||||
|
||||
_evtMassTagFormSubmit(e) {
|
||||
|
@ -125,10 +125,10 @@ class PostsHeaderView {
|
|||
const text = this._queryInputNode.value;
|
||||
const tag = this._massTagInputNode.value;
|
||||
this._massTagInputNode.blur();
|
||||
router.show('/posts/' + misc.formatSearchQuery({
|
||||
text: text,
|
||||
router.show('/posts/' + misc.formatUrlParameters({
|
||||
query: text,
|
||||
tag: tag,
|
||||
page: this._ctx.searchQuery.page,
|
||||
page: this._ctx.parameters.page,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ class TagsHeaderView {
|
|||
e.preventDefault();
|
||||
this._queryInputNode.blur();
|
||||
router.show(
|
||||
'/tags/' + misc.formatSearchQuery({
|
||||
text: this._queryInputNode.value,
|
||||
'/tags/' + misc.formatUrlParameters({
|
||||
query: this._queryInputNode.value,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ class UsersHeaderView {
|
|||
e.preventDefault();
|
||||
this._queryInputNode.blur();
|
||||
router.show(
|
||||
'/users/' + misc.formatSearchQuery({
|
||||
text: this._queryInputNode.value,
|
||||
'/users/' + misc.formatUrlParameters({
|
||||
query: this._queryInputNode.value,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue