client: refactor linking and routing
Print all links through new uri.js component Refactor the router to use more predictable parsing Fix linking to entities with weird names (that contain slashes, + etc.)
This commit is contained in:
parent
6714f05b49
commit
1acceb941d
65 changed files with 380 additions and 295 deletions
|
@ -1,7 +1,7 @@
|
|||
<div class='comment-container'>
|
||||
<div class='avatar'>
|
||||
<% if (ctx.user && ctx.user.name && ctx.canViewUsers) { %>
|
||||
<a href='/user/<%- encodeURIComponent(ctx.user.name) %>'>
|
||||
<a href='<%- ctx.formatClientLink('user', ctx.user.name) %>'>
|
||||
<% } %>
|
||||
|
||||
<%= ctx.makeThumbnail(ctx.user ? ctx.user.avatarUrl : null) %>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<nav class='readonly'><%
|
||||
%><strong><span class='nickname'><%
|
||||
%><% if (ctx.user && ctx.user.name && ctx.canViewUsers) { %><%
|
||||
%><a href='/user/<%- encodeURIComponent(ctx.user.name) %>'><%
|
||||
%><a href='<%- ctx.formatClientLink('user', ctx.user.name) %>'><%
|
||||
%><% } %><%
|
||||
|
||||
%><%- ctx.user ? ctx.user.name : 'Deleted user' %><%
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
--><li><!--
|
||||
--><div class='post-thumbnail'><!--
|
||||
--><% if (ctx.canViewPosts) { %><!--
|
||||
--><a href='/post/<%- encodeURIComponent(post.id) %>'><!--
|
||||
--><a href='<%- ctx.formatClientLink('post', post.id) %>'><!--
|
||||
--><% } %><!--
|
||||
--><%= ctx.makeThumbnail(post.thumbnailUrl) %><!--
|
||||
--><% if (ctx.canViewPosts) { %><!--
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<div class='content-wrapper' id='help'>
|
||||
<nav class='buttons primary'><!--
|
||||
--><ul><!--
|
||||
--><li data-name='about'><a href='/help/about'>About</a></li><!--
|
||||
--><li data-name='keyboard'><a href='/help/keyboard'>Keyboard</a></li><!--
|
||||
--><li data-name='search'><a href='/help/search'>Search syntax</a></li><!--
|
||||
--><li data-name='comments'><a href='/help/comments'>Comments</a></li><!--
|
||||
--><li data-name='tos'><a href='/help/tos'>Terms of service</a></li><!--
|
||||
--><li data-name='about'><a href='<%- ctx.formatClientLink('help', 'about') %>'>About</a></li><!--
|
||||
--><li data-name='keyboard'><a href='<%- ctx.formatClientLink('help', 'keyboard') %>'>Keyboard</a></li><!--
|
||||
--><li data-name='search'><a href='<%- ctx.formatClientLink('help', 'search') %>'>Search syntax</a></li><!--
|
||||
--><li data-name='comments'><a href='<%- ctx.formatClientLink('help', 'comments') %>'>Comments</a></li><!--
|
||||
--><li data-name='tos'><a href='<%- ctx.formatClientLink('help', 'tos') %>'>Terms of service</a></li><!--
|
||||
--></ul><!--
|
||||
--></nav>
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<nav class='buttons secondary'><!--
|
||||
--><ul><!--
|
||||
--><li data-name='default'><a href='/help/search'>General</a></li><!--
|
||||
--><li data-name='posts'><a href='/help/search/posts'>Posts</a></li><!--
|
||||
--><li data-name='users'><a href='/help/search/users'>Users</a></li><!--
|
||||
--><li data-name='tags'><a href='/help/search/tags'>Tags</a></li><!--
|
||||
--><li data-name='default'><a href='<%- ctx.formatClientLink('help', 'search') %>'>General</a></li><!--
|
||||
--><li data-name='posts'><a href='<%- ctx.formatClientLink('help', 'search', 'posts') %>'>Posts</a></li><!--
|
||||
--><li data-name='users'><a href='<%- ctx.formatClientLink('help', 'search', 'users') %>'>Users</a></li><!--
|
||||
--><li data-name='tags'><a href='<%- ctx.formatClientLink('help', 'search', 'tags') %>'>Tags</a></li><!--
|
||||
--></ul><!--
|
||||
--></nav>
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<%= ctx.makeTextInput({name: 'search-text', placeholder: 'enter some tags'}) %>
|
||||
<input type='submit' value='Search'/>
|
||||
<span class=sep>or</span>
|
||||
<a href='/posts'>browse all posts</a>
|
||||
<a href='<%- ctx.formatClientLink('posts') %>'>browse all posts</a>
|
||||
</form>
|
||||
<% } %>
|
||||
<div class='post-info-container'></div>
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
<li><%- ctx.postCount %> posts</li><span class='sep'>
|
||||
</span><li><%= ctx.makeFileSize(ctx.diskUsage) %></li><span class='sep'>
|
||||
</span><li>Build <a class='version' href='https://github.com/rr-/szurubooru/commits/master'><%- ctx.version %></a> from <%= ctx.makeRelativeTime(ctx.buildDate) %></li><span class='sep'>
|
||||
</span><% if (ctx.canListSnapshots) { %><li><a href='/history'>History</a></li><span class='sep'>
|
||||
</span><% if (ctx.canListSnapshots) { %><li><a href='<%- ctx.formatClientLink('history') %>'>History</a></li><span class='sep'>
|
||||
</span><% } %>
|
||||
</ul>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<div class='buttons'>
|
||||
<input type='submit' value='Log in'/>
|
||||
<% if (ctx.canSendMails) { %>
|
||||
<a class='append' href='/password-reset'>Forgot the password?</a>
|
||||
<a class='append' href='<%- ctx.formatClientLink('password-reset') %>'>Forgot the password?</a>
|
||||
<% } %>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class='not-found'>
|
||||
<h1>Not found</h1>
|
||||
<p><%- ctx.path %> is not a valid URL.</p>
|
||||
<p><a href='/'>Back to main page</a></p>
|
||||
<p><a href='<%- ctx.formatClientLink() %>'>Back to main page</a></p>
|
||||
</div>
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<h1>Post #<%- ctx.post.id %></h1>
|
||||
<nav class='buttons'><!--
|
||||
--><ul><!--
|
||||
--><li><a href='/post/<%- ctx.post.id %>'><i class='fa fa-reply'></i> Main view</a></li><!--
|
||||
--><li><a href='<%- ctx.formatClientLink('post', ctx.post.id) %>'><i class='fa fa-reply'></i> Main view</a></li><!--
|
||||
--><% if (ctx.canMerge) { %><!--
|
||||
--><li data-name='merge'><a href='/post/<%- ctx.post.id %>/merge'>Merge with…</a></li><!--
|
||||
--><li data-name='merge'><a href='<%- ctx.formatClientLink('post', ctx.post.id, 'merge') %>'>Merge with…</a></li><!--
|
||||
--><% } %><!--
|
||||
--></ul><!--
|
||||
--></nav>
|
||||
|
|
|
@ -67,14 +67,14 @@
|
|||
--><% for (let tag of ctx.post.tags) { %><!--
|
||||
--><li><!--
|
||||
--><% if (ctx.canViewTags) { %><!--
|
||||
--><a href='/tag/<%- encodeURIComponent(tag) %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
|
||||
--><a href='<%- ctx.formatClientLink('tag', tag) %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
|
||||
--><i class='fa fa-tag'></i><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canViewTags) { %><!--
|
||||
--></a><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canListPosts) { %><!--
|
||||
--><a href='/posts/query=<%- encodeURIComponent(tag) %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
|
||||
--><a href='<%- ctx.formatClientLink('posts', {query: tag}) %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
|
||||
--><% } %><!--
|
||||
--><%- tag %> <!--
|
||||
--><% if (ctx.canListPosts) { %><!--
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
%><input data-safety=sketchy type='button' class='mousetrap safety safety-sketchy <%- ctx.settings.listPosts.sketchy ? '' : 'disabled' %>'/><%
|
||||
%><input data-safety=unsafe type='button' class='mousetrap safety safety-unsafe <%- ctx.settings.listPosts.unsafe ? '' : 'disabled' %>'/><%
|
||||
%><wbr/><%
|
||||
%><a class='mousetrap button append' href='/help/search/posts'>Syntax help</a><%
|
||||
%><a class='mousetrap button append' href='<%- ctx.formatClientLink('help', 'search', 'posts') %>'>Syntax help</a><%
|
||||
%><% if (ctx.canMassTag) { %><%
|
||||
%><wbr/><%
|
||||
%><span class='masstag'><%
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<li>
|
||||
<a class='thumbnail-wrapper <%= post.tags.length > 0 ? "tags" : "no-tags" %>'
|
||||
title='@<%- post.id %> (<%- post.type %>) Tags: <%- post.tags.map(tag => '#' + tag).join(' ') || 'none' %>'
|
||||
href='<%= ctx.canViewPosts ? ctx.getPostUrl(post.id, ctx.parameters) : "" %>'>
|
||||
href='<%= ctx.canViewPosts ? ctx.getPostUrl(post.id, ctx.parameters) : '' %>'>
|
||||
<%= ctx.makeThumbnail(post.thumbnailUrl) %>
|
||||
<span class='type' data-type='<%- post.type %>'>
|
||||
<%- post.type %>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<ul class='input'>
|
||||
<li>
|
||||
<%= ctx.makeCheckbox({
|
||||
text: "Enable keyboard shortcuts <a class='append icon' href='/help/keyboard'><i class='fa fa-question-circle-o'></i></a>",
|
||||
text: "Enable keyboard shortcuts <a class='append icon' href='" + ctx.formatClientLink('help', 'keyboard') + "'><i class='fa fa-question-circle-o'></i></a>",
|
||||
name: 'keyboard-shortcuts',
|
||||
checked: ctx.browsingSettings.keyboardShortcuts,
|
||||
}) %>
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
<h1><%- ctx.tag.names[0] %></h1>
|
||||
<nav class='buttons'><!--
|
||||
--><ul><!--
|
||||
--><li data-name='summary'><a href='/tag/<%- encodeURIComponent(ctx.tag.names[0]) %>'>Summary</a></li><!--
|
||||
--><li data-name='summary'><a href='<%- ctx.formatClientLink('tag', ctx.tag.names[0]) %>'>Summary</a></li><!--
|
||||
--><% if (ctx.canEditAnything) { %><!--
|
||||
--><li data-name='edit'><a href='/tag/<%- encodeURIComponent(ctx.tag.names[0]) %>/edit'>Edit</a></li><!--
|
||||
--><li data-name='edit'><a href='<%- ctx.formatClientLink('tag', ctx.tag.names[0], 'edit') %>'>Edit</a></li><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canMerge) { %><!--
|
||||
--><li data-name='merge'><a href='/tag/<%- encodeURIComponent(ctx.tag.names[0]) %>/merge'>Merge with…</a></li><!--
|
||||
--><li data-name='merge'><a href='<%- ctx.formatClientLink('tag', ctx.tag.names[0], 'merge') %>'>Merge with…</a></li><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canDelete) { %><!--
|
||||
--><li data-name='delete'><a href='/tag/<%- encodeURIComponent(ctx.tag.names[0]) %>/delete'>Delete</a></li><!--
|
||||
--><li data-name='delete'><a href='<%- ctx.formatClientLink('tag', ctx.tag.names[0], 'delete') %>'>Delete</a></li><!--
|
||||
--><% } %><!--
|
||||
--></ul><!--
|
||||
--></nav>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</td>
|
||||
<td class='usages'>
|
||||
<% if (ctx.tagCategory.name) { %>
|
||||
<a href='/tags/query=category:<%- encodeURIComponent(ctx.tagCategory.name) %>'>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: 'category:' + ctx.tagCategory.name}) %>'>
|
||||
<%- ctx.tagCategory.tagCount %>
|
||||
</a>
|
||||
<% } else { %>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class='tag-delete'>
|
||||
<form>
|
||||
<p>This tag has <a href='/posts/query=<%- encodeURIComponent(ctx.tag.names[0]) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p>
|
||||
<p>This tag has <a href='<%- ctx.formatClientLink('posts', {query: ctx.tag.names[0]}) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p>
|
||||
|
||||
<ul class='input'>
|
||||
<li>
|
||||
|
|
|
@ -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/query=<%- encodeURIComponent(ctx.tag.names[0]) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p>
|
||||
<p>This tag has <a href='<%- ctx.formatClientLink('posts', {query: ctx.tag.names[0]}) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
<div class='buttons'>
|
||||
<input type='submit' value='Search'/>
|
||||
<a class='button append' href='/help/search/tags'>Syntax help</a>
|
||||
<a class='button append' href='<%- ctx.formatClientLink('help', 'search', 'tags') %>'>Syntax help</a>
|
||||
<% if (ctx.canEditTagCategories) { %>
|
||||
<a class='append' href='/tag-categories'>Tag categories</a>
|
||||
<a class='append' href='<%- ctx.formatClientLink('tag-categories') %>'>Tag categories</a>
|
||||
<% } %>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -4,37 +4,37 @@
|
|||
<thead>
|
||||
<th class='names'>
|
||||
<% if (ctx.query == 'sort:name' || !ctx.query) { %>
|
||||
<a href='/tags/query=-sort:name'>Tag name(s)</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: '-sort:name'}) %>'>Tag name(s)</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/query=sort:name'>Tag name(s)</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: 'sort:name'}) %>'>Tag name(s)</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='implications'>
|
||||
<% if (ctx.query == 'sort:implication-count') { %>
|
||||
<a href='/tags/query=-sort:implication-count'>Implications</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: '-sort:implication-count'}) %>'>Implications</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/query=sort:implication-count'>Implications</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: 'sort:implication-count'}) %>'>Implications</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='suggestions'>
|
||||
<% if (ctx.query == 'sort:suggestion-count') { %>
|
||||
<a href='/tags/query=-sort:suggestion-count'>Suggestions</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: '-sort:suggestion-count'}) %>'>Suggestions</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/query=sort:suggestion-count'>Suggestions</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: 'sort:suggestion-count'}) %>'>Suggestions</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='usages'>
|
||||
<% if (ctx.query == 'sort:usages') { %>
|
||||
<a href='/tags/query=-sort:usages'>Usages</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: '-sort:usages'}) %>'>Usages</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/query=sort:usages'>Usages</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: 'sort:usages'}) %>'>Usages</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='creation-time'>
|
||||
<% if (ctx.query == 'sort:creation-time') { %>
|
||||
<a href='/tags/query=-sort:creation-time'>Created on</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: '-sort:creation-time'}) %>'>Created on</a>
|
||||
<% } else { %>
|
||||
<a href='/tags/query=sort:creation-time'>Created on</a>
|
||||
<a href='<%- ctx.formatClientLink('tags', {query: 'sort:creation-time'}) %>'>Created on</a>
|
||||
<% } %>
|
||||
</th>
|
||||
</thead>
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<h1><%- ctx.user.name %></h1>
|
||||
<nav class='buttons'><!--
|
||||
--><ul><!--
|
||||
--><li data-name='summary'><a href='/user/<%- encodeURIComponent(ctx.user.name) %>'>Summary</a></li><!--
|
||||
--><li data-name='summary'><a href='<%- ctx.formatClientLink('user', ctx.user.name) %>'>Summary</a></li><!--
|
||||
--><% if (ctx.canEditAnything) { %><!--
|
||||
--><li data-name='edit'><a href='/user/<%- encodeURIComponent(ctx.user.name) %>/edit'>Account settings</a></li><!--
|
||||
--><li data-name='edit'><a href='<%- ctx.formatClientLink('user', ctx.user.name, 'edit') %>'>Account settings</a></li><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canDelete) { %><!--
|
||||
--><li data-name='delete'><a href='/user/<%- encodeURIComponent(ctx.user.name) %>/delete'>Account deletion</a></li><!--
|
||||
--><li data-name='delete'><a href='<%- ctx.formatClientLink('user', ctx.user.name, 'delete') %>'>Account deletion</a></li><!--
|
||||
--><% } %><!--
|
||||
--></ul><!--
|
||||
--></nav>
|
||||
|
|
|
@ -51,6 +51,6 @@
|
|||
<li><i class='fa fa-star-half-o'></i> vote up/down on posts and comments</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<p>By creating an account, you are agreeing to the <a href='/help/tos'>Terms of Service</a>.</p>
|
||||
<p>By creating an account, you are agreeing to the <a href='<%- ctx.formatClientLink('help', 'tos') %>'>Terms of Service</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
<nav>
|
||||
<p><strong>Quick links</strong></p>
|
||||
<ul>
|
||||
<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>
|
||||
<li><a href='<%- ctx.formatClientLink('posts', {query: 'submit:' + ctx.user.name}) %>'><%- ctx.user.uploadedPostCount %> uploads</a></li>
|
||||
<li><a href='<%- ctx.formatClientLink('posts', {query: 'fav:' + ctx.user.name}) %>'><%- ctx.user.favoritePostCount %> favorites</a></li>
|
||||
<li><a href='<%- ctx.formatClientLink('posts', {query: 'comment:' + 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/query=special:liked'><%- ctx.user.likedPostCount %> liked posts</a></li>
|
||||
<li><a href='/posts/query=special:disliked'><%- ctx.user.dislikedPostCount %> disliked posts</a></li>
|
||||
<li><a href='<%- ctx.formatClientLink('posts', {query: 'special:liked'}) %>'><%- ctx.user.likedPostCount %> liked posts</a></li>
|
||||
<li><a href='<%- ctx.formatClientLink('posts', {query: 'special:disliked'}) %>'><%- ctx.user.dislikedPostCount %> disliked posts</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<% } %>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<div class='buttons'>
|
||||
<input type='submit' value='Search'/>
|
||||
<a class='append' href='/help/search/users'>Syntax help</a>
|
||||
<a class='append' href='<%- ctx.formatClientLink('help', 'search', 'users') %>'>Syntax help</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
--><li>
|
||||
<div class='wrapper'>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
<a class='image' href='/user/<%- encodeURIComponent(user.name) %>'>
|
||||
<a class='image' href='<%- ctx.formatClientLink('user', user.name) %>'>
|
||||
<% } %>
|
||||
<%= ctx.makeThumbnail(user.avatarUrl) %>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<% } %>
|
||||
<div class='details'>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
<a href='/user/<%- encodeURIComponent(user.name) %>'>
|
||||
<a href='<%- ctx.formatClientLink('user', user.name) %>'>
|
||||
<% } %>
|
||||
<%- user.name %>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
|
|
|
@ -5,6 +5,7 @@ const request = require('superagent');
|
|||
const config = require('./config.js');
|
||||
const events = require('./events.js');
|
||||
const progress = require('./util/progress.js');
|
||||
const uri = require('./util/uri.js');
|
||||
|
||||
let fileTokens = {};
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const LoginView = require('../views/login_view.js');
|
||||
|
||||
|
@ -21,7 +22,7 @@ class LoginController {
|
|||
api.forget();
|
||||
api.login(e.detail.name, e.detail.password, e.detail.remember)
|
||||
.then(() => {
|
||||
const ctx = router.show('/');
|
||||
const ctx = router.show(uri.formatClientLink());
|
||||
ctx.controller.showSuccess('Logged in');
|
||||
}, error => {
|
||||
this._loginView.showError(error.message);
|
||||
|
@ -34,16 +35,16 @@ class LogoutController {
|
|||
constructor() {
|
||||
api.forget();
|
||||
api.logout();
|
||||
const ctx = router.show('/');
|
||||
const ctx = router.show(uri.formatClientLink());
|
||||
ctx.controller.showSuccess('Logged out');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/login', (ctx, next) => {
|
||||
router.enter(['login'], (ctx, next) => {
|
||||
ctx.controller = new LoginController();
|
||||
});
|
||||
router.enter('/logout', (ctx, next) => {
|
||||
router.enter(['logout'], (ctx, next) => {
|
||||
ctx.controller = new LogoutController();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const PostList = require('../models/post_list.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const PageController = require('../controllers/page_controller.js');
|
||||
|
@ -28,7 +28,7 @@ class CommentsController {
|
|||
getClientUrlForPage: page => {
|
||||
const parameters = Object.assign(
|
||||
{}, ctx.parameters, {page: page});
|
||||
return '/comments/' + misc.formatUrlParameters(parameters);
|
||||
return uri.formatClientLink('comments', parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return PostList.search(
|
||||
|
@ -69,7 +69,6 @@ class CommentsController {
|
|||
};
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/comments/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
router.enter(['comments'],
|
||||
(ctx, next) => { new CommentsController(ctx); });
|
||||
};
|
||||
|
|
|
@ -12,13 +12,13 @@ class HelpController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/help', (ctx, next) => {
|
||||
router.enter(['help'], (ctx, next) => {
|
||||
new HelpController();
|
||||
});
|
||||
router.enter('/help/:section', (ctx, next) => {
|
||||
router.enter(['help', ':section'], (ctx, next) => {
|
||||
new HelpController(ctx.parameters.section);
|
||||
});
|
||||
router.enter('/help/:section/:subsection', (ctx, next) => {
|
||||
router.enter(['help', ':section', ':subsection'], (ctx, next) => {
|
||||
new HelpController(ctx.parameters.section, ctx.parameters.subsection);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -44,7 +44,7 @@ class HomeController {
|
|||
};
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/', (ctx, next) => {
|
||||
router.enter([], (ctx, next) => {
|
||||
ctx.controller = new HomeController();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ class NotFoundController {
|
|||
};
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('*', (ctx, next) => {
|
||||
router.enter(null, (ctx, next) => {
|
||||
ctx.controller = new NotFoundController(ctx.canonicalPath);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const PasswordResetView = require('../views/password_reset_view.js');
|
||||
|
||||
|
@ -20,7 +21,7 @@ class PasswordResetController {
|
|||
this._passwordResetView.disableForm();
|
||||
api.forget();
|
||||
api.logout();
|
||||
api.get('/password-reset/' + e.detail.userNameOrEmail)
|
||||
api.get(uri.formatApiLink('password-reset', e.detail.userNameOrEmail))
|
||||
.then(() => {
|
||||
this._passwordResetView.showSuccess(
|
||||
'E-mail has been sent. To finish the procedure, ' +
|
||||
|
@ -37,26 +38,26 @@ class PasswordResetFinishController {
|
|||
api.forget();
|
||||
api.logout();
|
||||
let password = null;
|
||||
api.post('/password-reset/' + name, {token: token})
|
||||
api.post(uri.formatApiLink('password-reset', name), {token: token})
|
||||
.then(response => {
|
||||
password = response.password;
|
||||
return api.login(name, password, false);
|
||||
}).then(() => {
|
||||
const ctx = router.show('/');
|
||||
const ctx = router.show(uri.formatClientLink());
|
||||
ctx.controller.showSuccess('New password: ' + password);
|
||||
}, error => {
|
||||
const ctx = router.show('/');
|
||||
const ctx = router.show(uri.formatClientLink());
|
||||
ctx.controller.showError(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/password-reset', (ctx, next) => {
|
||||
router.enter(['password-reset'], (ctx, next) => {
|
||||
ctx.controller = new PasswordResetController();
|
||||
});
|
||||
router.enter(/\/password-reset\/([^:]+):([^:]+)$/, (ctx, next) => {
|
||||
ctx.controller = new PasswordResetFinishController(
|
||||
ctx.parameters[0], ctx.parameters[1]);
|
||||
router.enter(['password-reset', ':descriptor'], (ctx, next) => {
|
||||
const [name, token] = ctx.parameters.descriptor.split(':', 2);
|
||||
ctx.controller = new PasswordResetFinishController(name, token);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const settings = require('../models/settings.js');
|
||||
const Post = require('../models/post.js');
|
||||
const PostList = require('../models/post_list.js');
|
||||
|
@ -55,7 +56,8 @@ class PostDetailController extends BasePostController {
|
|||
misc.disableExitConfirmation();
|
||||
if (this._id !== e.detail.post.id) {
|
||||
router.replace(
|
||||
'/post/' + e.detail.post.id + '/' + section, null, false);
|
||||
uri.formatClientLink('post', e.detail.post.id, section),
|
||||
null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +69,9 @@ class PostDetailController extends BasePostController {
|
|||
this._installView(e.detail.post, 'merge');
|
||||
this._view.showSuccess('Post merged.');
|
||||
router.replace(
|
||||
'/post/' + e.detail.targetPost.id + '/merge', null, false);
|
||||
uri.formatClientLink(
|
||||
'post', e.detail.targetPost.id, 'merge'),
|
||||
null, false);
|
||||
}, error => {
|
||||
this._view.showError(error.message);
|
||||
this._view.enableForm();
|
||||
|
@ -77,7 +81,7 @@ class PostDetailController extends BasePostController {
|
|||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/post/:id/merge',
|
||||
['post', ':id', 'merge'],
|
||||
(ctx, next) => {
|
||||
ctx.controller = new PostDetailController(ctx, 'merge');
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
const api = require('../api.js');
|
||||
const settings = require('../models/settings.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const PostList = require('../models/post_list.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const PageController = require('../controllers/page_controller.js');
|
||||
|
@ -52,7 +52,7 @@ class PostListController {
|
|||
history.pushState(
|
||||
null,
|
||||
window.title,
|
||||
'/posts/' + misc.formatUrlParameters(e.detail.parameters));
|
||||
uri.formatClientLink('posts', e.detail.parameters));
|
||||
Object.assign(this._ctx.parameters, e.detail.parameters);
|
||||
this._syncPageController();
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ class PostListController {
|
|||
this._pageController.run({
|
||||
parameters: this._ctx.parameters,
|
||||
getClientUrlForPage: page => {
|
||||
return '/posts/' + misc.formatUrlParameters(
|
||||
return uri.formatClientLink('posts',
|
||||
Object.assign({}, this._ctx.parameters, {page: page}));
|
||||
},
|
||||
requestPage: page => {
|
||||
|
@ -114,7 +114,6 @@ class PostListController {
|
|||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/posts/:parameters(.*)?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
['posts'],
|
||||
(ctx, next) => { ctx.controller = new PostListController(ctx); });
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const settings = require('../models/settings.js');
|
||||
const Comment = require('../models/comment.js');
|
||||
|
@ -29,8 +30,8 @@ class PostMainController extends BasePostController {
|
|||
if (parameters.query) {
|
||||
ctx.state.parameters = parameters;
|
||||
const url = editMode ?
|
||||
'/post/' + ctx.parameters.id + '/edit' :
|
||||
'/post/' + ctx.parameters.id;
|
||||
uri.formatClientLink('post', ctx.parameters.id, 'edit') :
|
||||
uri.formatClientLink('post', ctx.parameters.id);
|
||||
router.replace(url, ctx.state, false);
|
||||
}
|
||||
|
||||
|
@ -124,7 +125,7 @@ class PostMainController extends BasePostController {
|
|||
}
|
||||
|
||||
_evtMergePost(e) {
|
||||
router.show('/post/' + e.detail.post.id + '/merge');
|
||||
router.show(uri.formatClientLink('post', e.detail.post.id, 'merge'));
|
||||
}
|
||||
|
||||
_evtDeletePost(e) {
|
||||
|
@ -133,7 +134,7 @@ class PostMainController extends BasePostController {
|
|||
e.detail.post.delete()
|
||||
.then(() => {
|
||||
misc.disableExitConfirmation();
|
||||
const ctx = router.show('/posts');
|
||||
const ctx = router.show(uri.formatClientLink('posts'));
|
||||
ctx.controller.showSuccess('Post deleted.');
|
||||
}, error => {
|
||||
this._view.sidebarControl.showError(error.message);
|
||||
|
@ -244,8 +245,7 @@ class PostMainController extends BasePostController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/post/:id/edit/:parameters(.*)?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
router.enter(['post', ':id', 'edit'],
|
||||
(ctx, next) => {
|
||||
// restore parameters from history state
|
||||
if (ctx.state.parameters) {
|
||||
|
@ -254,8 +254,7 @@ module.exports = router => {
|
|||
ctx.controller = new PostMainController(ctx, true);
|
||||
});
|
||||
router.enter(
|
||||
'/post/:id/:parameters(.*)?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
['post', ':id'],
|
||||
(ctx, next) => {
|
||||
// restore parameters from history state
|
||||
if (ctx.state.parameters) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const api = require('../api.js');
|
||||
const router = require('../router.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const progress = require('../util/progress.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
|
@ -61,7 +62,7 @@ class PostUploadController {
|
|||
.then(() => {
|
||||
this._view.clearMessages();
|
||||
misc.disableExitConfirmation();
|
||||
const ctx = router.show('/posts');
|
||||
const ctx = router.show(uri.formatClientLink('posts'));
|
||||
ctx.controller.showSuccess('Posts uploaded.');
|
||||
}, error => {
|
||||
if (error.uploadable) {
|
||||
|
@ -149,7 +150,7 @@ class PostUploadController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/upload', (ctx, next) => {
|
||||
router.enter(['upload'], (ctx, next) => {
|
||||
ctx.controller = new PostUploadController();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ class SettingsController {
|
|||
};
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/settings', (ctx, next) => {
|
||||
router.enter(['settings'], (ctx, next) => {
|
||||
ctx.controller = new SettingsController();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const SnapshotList = require('../models/snapshot_list.js');
|
||||
const PageController = require('../controllers/page_controller.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
|
@ -25,7 +25,7 @@ class SnapshotsController {
|
|||
getClientUrlForPage: page => {
|
||||
const parameters = Object.assign(
|
||||
{}, ctx.parameters, {page: page});
|
||||
return '/history/' + misc.formatUrlParameters(parameters);
|
||||
return uri.formatClientLink('history', parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return SnapshotList.search('', page, 25);
|
||||
|
@ -43,7 +43,6 @@ class SnapshotsController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/history/:parameters?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
router.enter(['history'],
|
||||
(ctx, next) => { ctx.controller = new SnapshotsController(ctx); });
|
||||
};
|
||||
|
|
|
@ -51,7 +51,7 @@ class TagCategoriesController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/tag-categories', (ctx, next) => {
|
||||
router.enter(['tag-categories'], (ctx, next) => {
|
||||
ctx.controller = new TagCategoriesController(ctx, next);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const tags = require('../tags.js');
|
||||
const Tag = require('../models/tag.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
|
@ -61,7 +62,8 @@ class TagController {
|
|||
misc.disableExitConfirmation();
|
||||
if (this._name !== e.detail.tag.names[0]) {
|
||||
router.replace(
|
||||
'/tag/' + e.detail.tag.names[0] + '/' + section, null, false);
|
||||
uri.formatClientLink('tag', e.detail.tag.names[0], section),
|
||||
null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +101,8 @@ class TagController {
|
|||
this._view.showSuccess('Tag merged.');
|
||||
this._view.enableForm();
|
||||
router.replace(
|
||||
'/tag/' + e.detail.targetTagName + '/merge', null, false);
|
||||
uri.formatClientLink('tag', e.detail.targetTagName, 'merge'),
|
||||
null, false);
|
||||
}, error => {
|
||||
this._view.showError(error.message);
|
||||
this._view.enableForm();
|
||||
|
@ -111,7 +114,7 @@ class TagController {
|
|||
this._view.disableForm();
|
||||
e.detail.tag.delete()
|
||||
.then(() => {
|
||||
const ctx = router.show('/tags/');
|
||||
const ctx = router.show(uri.formatClientLink('tags'));
|
||||
ctx.controller.showSuccess('Tag deleted.');
|
||||
}, error => {
|
||||
this._view.showError(error.message);
|
||||
|
@ -121,16 +124,16 @@ class TagController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/tag/:name(.+?)/edit', (ctx, next) => {
|
||||
router.enter(['tag', ':name', 'edit'], (ctx, next) => {
|
||||
ctx.controller = new TagController(ctx, 'edit');
|
||||
});
|
||||
router.enter('/tag/:name(.+?)/merge', (ctx, next) => {
|
||||
router.enter(['tag', ':name', 'merge'], (ctx, next) => {
|
||||
ctx.controller = new TagController(ctx, 'merge');
|
||||
});
|
||||
router.enter('/tag/:name(.+?)/delete', (ctx, next) => {
|
||||
router.enter(['tag', ':name', 'delete'], (ctx, next) => {
|
||||
ctx.controller = new TagController(ctx, 'delete');
|
||||
});
|
||||
router.enter('/tag/:name(.+)', (ctx, next) => {
|
||||
router.enter(['tag', ':name'], (ctx, next) => {
|
||||
ctx.controller = new TagController(ctx, 'summary');
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const TagList = require('../models/tag_list.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const PageController = require('../controllers/page_controller.js');
|
||||
|
@ -49,7 +49,7 @@ class TagListController {
|
|||
history.pushState(
|
||||
null,
|
||||
window.title,
|
||||
'/tags/' + misc.formatUrlParameters(e.detail.parameters));
|
||||
uri.formatClientLink('tags', e.detail.parameters));
|
||||
Object.assign(this._ctx.parameters, e.detail.parameters);
|
||||
this._syncPageController();
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ class TagListController {
|
|||
getClientUrlForPage: page => {
|
||||
const parameters = Object.assign(
|
||||
{}, this._ctx.parameters, {page: page});
|
||||
return '/tags/' + misc.formatUrlParameters(parameters);
|
||||
return uri.formatClientLink('tags', parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return TagList.search(
|
||||
|
@ -75,7 +75,6 @@ class TagListController {
|
|||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/tags/:parameters(.*)?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
['tags'],
|
||||
(ctx, next) => { ctx.controller = new TagListController(ctx); });
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const config = require('../config.js');
|
||||
const views = require('../util/views.js');
|
||||
|
@ -77,7 +78,8 @@ class UserController {
|
|||
misc.disableExitConfirmation();
|
||||
if (this._name !== e.detail.user.name) {
|
||||
router.replace(
|
||||
'/user/' + e.detail.user.name + '/' + section, null, false);
|
||||
uri.formatClientLink('user', e.detail.user.name, section),
|
||||
null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,10 +137,10 @@ class UserController {
|
|||
api.logout();
|
||||
}
|
||||
if (api.hasPrivilege('users:list')) {
|
||||
const ctx = router.show('/users');
|
||||
const ctx = router.show(uri.formatClientLink('users'));
|
||||
ctx.controller.showSuccess('Account deleted.');
|
||||
} else {
|
||||
const ctx = router.show('/');
|
||||
const ctx = router.show(uri.formatClientLink());
|
||||
ctx.controller.showSuccess('Account deleted.');
|
||||
}
|
||||
}, error => {
|
||||
|
@ -149,13 +151,13 @@ class UserController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/user/:name', (ctx, next) => {
|
||||
router.enter(['user', ':name'], (ctx, next) => {
|
||||
ctx.controller = new UserController(ctx, 'summary');
|
||||
});
|
||||
router.enter('/user/:name/edit', (ctx, next) => {
|
||||
router.enter(['user', ':name', 'edit'], (ctx, next) => {
|
||||
ctx.controller = new UserController(ctx, 'edit');
|
||||
});
|
||||
router.enter('/user/:name/delete', (ctx, next) => {
|
||||
router.enter(['user', ':name', 'delete'], (ctx, next) => {
|
||||
ctx.controller = new UserController(ctx, 'delete');
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const UserList = require('../models/user_list.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const PageController = require('../controllers/page_controller.js');
|
||||
|
@ -41,7 +41,7 @@ class UserListController {
|
|||
history.pushState(
|
||||
null,
|
||||
window.title,
|
||||
'/users/' + misc.formatUrlParameters(e.detail.parameters));
|
||||
uri.formatClientLink('users', e.detail.parameters));
|
||||
Object.assign(this._ctx.parameters, e.detail.parameters);
|
||||
this._syncPageController();
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class UserListController {
|
|||
getClientUrlForPage: page => {
|
||||
const parameters = Object.assign(
|
||||
{}, this._ctx.parameters, {page: page});
|
||||
return '/users/' + misc.formatUrlParameters(parameters);
|
||||
return uri.formatClientLink('users', parameters);
|
||||
},
|
||||
requestPage: page => {
|
||||
return UserList.search(this._ctx.parameters.query, page);
|
||||
|
@ -69,7 +69,6 @@ class UserListController {
|
|||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/users/:parameters(.*)?',
|
||||
(ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
|
||||
['users'],
|
||||
(ctx, next) => { ctx.controller = new UserListController(ctx); });
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const User = require('../models/user.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const RegistrationView = require('../views/registration_view.js');
|
||||
|
@ -32,7 +33,7 @@ class UserRegistrationController {
|
|||
api.forget();
|
||||
return api.login(e.detail.name, e.detail.password, false);
|
||||
}).then(() => {
|
||||
const ctx = router.show('/');
|
||||
const ctx = router.show(uri.formatClientLink());
|
||||
ctx.controller.showSuccess('Welcome aboard!');
|
||||
}, error => {
|
||||
this._view.showError(error.message);
|
||||
|
@ -42,7 +43,7 @@ class UserRegistrationController {
|
|||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter('/register', (ctx, next) => {
|
||||
router.enter(['register'], (ctx, next) => {
|
||||
new UserRegistrationController();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const api = require('../api.js');
|
||||
const tags = require('../tags.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const settings = require('../models/settings.js');
|
||||
const events = require('../events.js');
|
||||
const views = require('../util/views.js');
|
||||
|
@ -308,7 +309,7 @@ class TagInputControl extends events.EventTarget {
|
|||
tagLinkNode.classList.add(className);
|
||||
}
|
||||
tagLinkNode.setAttribute(
|
||||
'href', '/tag/' + encodeURIComponent(tagName));
|
||||
'href', uri.formatClientLink('tag', tagName));
|
||||
const tagIconNode = document.createElement('i');
|
||||
tagIconNode.classList.add('fa');
|
||||
tagIconNode.classList.add('fa-tag');
|
||||
|
@ -319,7 +320,7 @@ class TagInputControl extends events.EventTarget {
|
|||
searchLinkNode.classList.add(className);
|
||||
}
|
||||
searchLinkNode.setAttribute(
|
||||
'href', '/posts/query=' + encodeURIComponent(tagName));
|
||||
'href', uri.formatClientLink('posts', {query: tagName}));
|
||||
searchLinkNode.textContent = tagName + ' ';
|
||||
searchLinkNode.addEventListener('click', e => {
|
||||
e.preventDefault();
|
||||
|
@ -360,7 +361,9 @@ class TagInputControl extends events.EventTarget {
|
|||
if (!browsingSettings.tagSuggestions) {
|
||||
return;
|
||||
}
|
||||
api.get('/tag-siblings/' + tag.names[0], {noProgress: true})
|
||||
api.get(
|
||||
uri.formatApiLink('tag-siblings', tag.names[0]),
|
||||
{noProgress: true})
|
||||
.then(response => {
|
||||
return Promise.resolve(response.results);
|
||||
}, response => {
|
||||
|
|
|
@ -8,7 +8,7 @@ const router = require('./router.js');
|
|||
history.scrollRestoration = 'manual';
|
||||
|
||||
router.exit(
|
||||
/.*/,
|
||||
null,
|
||||
(ctx, next) => {
|
||||
ctx.state.scrollX = window.scrollX;
|
||||
ctx.state.scrollY = window.scrollY;
|
||||
|
@ -20,7 +20,7 @@ router.exit(
|
|||
|
||||
const mousetrap = require('mousetrap');
|
||||
router.enter(
|
||||
/.*/,
|
||||
null,
|
||||
(ctx, next) => {
|
||||
mousetrap.reset();
|
||||
next();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const events = require('../events.js');
|
||||
|
||||
class Comment extends events.EventTarget {
|
||||
|
@ -38,9 +39,9 @@ class Comment extends events.EventTarget {
|
|||
text: this._text,
|
||||
};
|
||||
let promise = this._id ?
|
||||
api.put('/comment/' + this._id, detail) :
|
||||
api.post(
|
||||
'/comments', Object.assign({postId: this._postId}, detail));
|
||||
api.put(uri.formatApiLink('comment', this.id), detail) :
|
||||
api.post(uri.formatApiLink('comments'),
|
||||
Object.assign({postId: this._postId}, detail));
|
||||
|
||||
return promise.then(response => {
|
||||
this._updateFromResponse(response);
|
||||
|
@ -55,7 +56,7 @@ class Comment extends events.EventTarget {
|
|||
|
||||
delete() {
|
||||
return api.delete(
|
||||
'/comment/' + this._id,
|
||||
uri.formatApiLink('comment', this.id),
|
||||
{version: this._version})
|
||||
.then(response => {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
|
@ -68,7 +69,9 @@ class Comment extends events.EventTarget {
|
|||
}
|
||||
|
||||
setScore(score) {
|
||||
return api.put('/comment/' + this._id + '/score', {score: score})
|
||||
return api.put(
|
||||
uri.formatApiLink('comment', this.id, 'score'),
|
||||
{score: score})
|
||||
.then(response => {
|
||||
this._updateFromResponse(response);
|
||||
this.dispatchEvent(new CustomEvent('changeScore', {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const Post = require('./post.js');
|
||||
|
||||
class Info {
|
||||
static get() {
|
||||
return api.get('/info')
|
||||
return api.get(uri.formatApiLink('info'))
|
||||
.then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const tags = require('../tags.js');
|
||||
const events = require('../events.js');
|
||||
const NoteList = require('./note_list.js');
|
||||
|
@ -69,7 +70,9 @@ class Post extends events.EventTarget {
|
|||
|
||||
static reverseSearch(content) {
|
||||
let apiPromise = api.post(
|
||||
'/posts/reverse-search', {}, {content: content});
|
||||
uri.formatApiLink('posts', 'reverse-search'),
|
||||
{},
|
||||
{content: content});
|
||||
let returnedPromise = apiPromise
|
||||
.then(response => {
|
||||
if (response.exactPost) {
|
||||
|
@ -85,7 +88,7 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
static get(id) {
|
||||
return api.get('/post/' + id)
|
||||
return api.get(uri.formatApiLink('post', id))
|
||||
.then(response => {
|
||||
return Promise.resolve(Post.fromResponse(response));
|
||||
});
|
||||
|
@ -149,8 +152,8 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
let apiPromise = this._id ?
|
||||
api.put('/post/' + this._id, detail, files) :
|
||||
api.post('/posts', detail, files);
|
||||
api.put(uri.formatApiLink('post', this.id), detail, files) :
|
||||
api.post(uri.formatApiLink('posts'), detail, files);
|
||||
|
||||
return apiPromise.then(response => {
|
||||
this._updateFromResponse(response);
|
||||
|
@ -176,14 +179,18 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
feature() {
|
||||
return api.post('/featured-post', {id: this._id})
|
||||
return api.post(
|
||||
uri.formatApiLink('featured-post'),
|
||||
{id: this._id})
|
||||
.then(response => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
delete() {
|
||||
return api.delete('/post/' + this._id, {version: this._version})
|
||||
return api.delete(
|
||||
uri.formatApiLink('post', this.id),
|
||||
{version: this._version})
|
||||
.then(response => {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
detail: {
|
||||
|
@ -195,9 +202,9 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
merge(targetId, useOldContent) {
|
||||
return api.get('/post/' + encodeURIComponent(targetId))
|
||||
return api.get(uri.formatApiLink('post', targetId))
|
||||
.then(response => {
|
||||
return api.post('/post-merge/', {
|
||||
return api.post(uri.formatApiLink('post-merge'), {
|
||||
removeVersion: this._version,
|
||||
remove: this._id,
|
||||
mergeToVersion: response.version,
|
||||
|
@ -216,7 +223,9 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
setScore(score) {
|
||||
return api.put('/post/' + this._id + '/score', {score: score})
|
||||
return api.put(
|
||||
uri.formatApiLink('post', this.id, 'score'),
|
||||
{score: score})
|
||||
.then(response => {
|
||||
const prevFavorite = this._ownFavorite;
|
||||
this._updateFromResponse(response);
|
||||
|
@ -237,7 +246,7 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
addToFavorites() {
|
||||
return api.post('/post/' + this.id + '/favorite')
|
||||
return api.post(uri.formatApiLink('post', this.id, 'favorite'))
|
||||
.then(response => {
|
||||
const prevScore = this._ownScore;
|
||||
this._updateFromResponse(response);
|
||||
|
@ -258,7 +267,7 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
removeFromFavorites() {
|
||||
return api.delete('/post/' + this.id + '/favorite')
|
||||
return api.delete(uri.formatApiLink('post', this.id, 'favorite'))
|
||||
.then(response => {
|
||||
const prevScore = this._ownScore;
|
||||
this._updateFromResponse(response);
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const AbstractList = require('./abstract_list.js');
|
||||
const Post = require('./post.js');
|
||||
|
||||
class PostList extends AbstractList {
|
||||
static getAround(id, searchQuery) {
|
||||
const url =
|
||||
`/post/${id}/around?fields=id` +
|
||||
`&query=${encodeURIComponent(searchQuery)}`;
|
||||
return api.get(url);
|
||||
return api.get(
|
||||
uri.formatApiLink(
|
||||
'post', id, 'around', {query: searchQuery, fields: 'id'}));
|
||||
}
|
||||
|
||||
static search(text, page, pageSize, fields) {
|
||||
const url =
|
||||
`/posts/?query=${encodeURIComponent(text)}` +
|
||||
`&page=${page}` +
|
||||
`&pageSize=${pageSize}` +
|
||||
`&fields=${fields.join(',')}`;
|
||||
return api.get(url).then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: PostList.fromResponse(response.results)}));
|
||||
});
|
||||
return api.get(
|
||||
uri.formatApiLink(
|
||||
'posts', {
|
||||
query: text,
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
fields: fields.join(','),
|
||||
}))
|
||||
.then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: PostList.fromResponse(response.results)}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const AbstractList = require('./abstract_list.js');
|
||||
const Snapshot = require('./snapshot.js');
|
||||
|
||||
class SnapshotList extends AbstractList {
|
||||
static search(text, page, pageSize) {
|
||||
const url =
|
||||
`/snapshots/?query=${encodeURIComponent(text)}` +
|
||||
`&page=${page}` +
|
||||
`&pageSize=${pageSize}`;
|
||||
return api.get(url).then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: SnapshotList.fromResponse(response.results)}));
|
||||
});
|
||||
return api.get(uri.formatApiLink(
|
||||
'snapshots', {query: text, page: page, pageSize: pageSize}))
|
||||
.then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: SnapshotList.fromResponse(response.results)}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const events = require('../events.js');
|
||||
const misc = require('../util/misc.js');
|
||||
|
||||
|
@ -33,7 +34,7 @@ class Tag extends events.EventTarget {
|
|||
}
|
||||
|
||||
static get(name) {
|
||||
return api.get('/tag/' + encodeURIComponent(name))
|
||||
return api.get(uri.formatApiLink('tag', name))
|
||||
.then(response => {
|
||||
return Promise.resolve(Tag.fromResponse(response));
|
||||
});
|
||||
|
@ -60,8 +61,8 @@ class Tag extends events.EventTarget {
|
|||
}
|
||||
|
||||
let promise = this._origName ?
|
||||
api.put('/tag/' + encodeURIComponent(this._origName), detail) :
|
||||
api.post('/tags', detail);
|
||||
api.put(uri.formatApiLink('tag', this._origName), detail) :
|
||||
api.post(uri.formatApiLink('tags'), detail);
|
||||
return promise
|
||||
.then(response => {
|
||||
this._updateFromResponse(response);
|
||||
|
@ -75,9 +76,9 @@ class Tag extends events.EventTarget {
|
|||
}
|
||||
|
||||
merge(targetName) {
|
||||
return api.get('/tag/' + encodeURIComponent(targetName))
|
||||
return api.get(uri.formatApiLink('tag', targetName))
|
||||
.then(response => {
|
||||
return api.post('/tag-merge/', {
|
||||
return api.post(uri.formatApiLink('tag-merge'), {
|
||||
removeVersion: this._version,
|
||||
remove: this._origName,
|
||||
mergeToVersion: response.version,
|
||||
|
@ -96,7 +97,7 @@ class Tag extends events.EventTarget {
|
|||
|
||||
delete() {
|
||||
return api.delete(
|
||||
'/tag/' + encodeURIComponent(this._origName),
|
||||
uri.formatApiLink('tag', this._origName),
|
||||
{version: this._version})
|
||||
.then(response => {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const events = require('../events.js');
|
||||
|
||||
class TagCategory extends events.EventTarget {
|
||||
|
@ -45,9 +46,9 @@ class TagCategory extends events.EventTarget {
|
|||
|
||||
let promise = this._origName ?
|
||||
api.put(
|
||||
'/tag-category/' + encodeURIComponent(this._origName),
|
||||
uri.formatApiLink('tag-category', this._origName),
|
||||
detail) :
|
||||
api.post('/tag-categories', detail);
|
||||
api.post(uri.formatApiLink('tag-categories'), detail);
|
||||
|
||||
return promise
|
||||
.then(response => {
|
||||
|
@ -63,7 +64,7 @@ class TagCategory extends events.EventTarget {
|
|||
|
||||
delete() {
|
||||
return api.delete(
|
||||
'/tag-category/' + encodeURIComponent(this._origName),
|
||||
uri.formatApiLink('tag-category', this._origName),
|
||||
{version: this._version})
|
||||
.then(response => {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const AbstractList = require('./abstract_list.js');
|
||||
const TagCategory = require('./tag_category.js');
|
||||
|
||||
|
@ -26,12 +27,13 @@ class TagCategoryList extends AbstractList {
|
|||
}
|
||||
|
||||
static get() {
|
||||
return api.get('/tag-categories/').then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: TagCategoryList.fromResponse(response.results)}));
|
||||
});
|
||||
return api.get(uri.formatApiLink('tag-categories'))
|
||||
.then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: TagCategoryList.fromResponse(response.results)}));
|
||||
});
|
||||
}
|
||||
|
||||
get defaultCategory() {
|
||||
|
@ -54,7 +56,10 @@ class TagCategoryList extends AbstractList {
|
|||
if (this._defaultCategory !== this._origDefaultCategory) {
|
||||
promises.push(
|
||||
api.put(
|
||||
`/tag-category/${this._defaultCategory.name}/default`));
|
||||
uri.formatApiLink(
|
||||
'tag-category',
|
||||
this._defaultCategory.name,
|
||||
'default')));
|
||||
}
|
||||
|
||||
return Promise.all(promises)
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const AbstractList = require('./abstract_list.js');
|
||||
const Tag = require('./tag.js');
|
||||
|
||||
class TagList extends AbstractList {
|
||||
static search(text, page, pageSize, fields) {
|
||||
const url =
|
||||
`/tags/?query=${encodeURIComponent(text)}` +
|
||||
`&page=${page}` +
|
||||
`&pageSize=${pageSize}` +
|
||||
`&fields=${fields.join(',')}`;
|
||||
return api.get(url).then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: TagList.fromResponse(response.results)}));
|
||||
});
|
||||
return api.get(
|
||||
uri.formatApiLink(
|
||||
'tags', {
|
||||
query: text,
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
fields: fields.join(','),
|
||||
}))
|
||||
.then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: TagList.fromResponse(response.results)}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const events = require('../events.js');
|
||||
|
||||
class User extends events.EventTarget {
|
||||
|
@ -40,7 +41,7 @@ class User extends events.EventTarget {
|
|||
}
|
||||
|
||||
static get(name) {
|
||||
return api.get('/user/' + encodeURIComponent(name))
|
||||
return api.get(uri.formatApiLink('user', name))
|
||||
.then(response => {
|
||||
return Promise.resolve(User.fromResponse(response));
|
||||
});
|
||||
|
@ -73,10 +74,8 @@ class User extends events.EventTarget {
|
|||
|
||||
let promise = this._orig._name ?
|
||||
api.put(
|
||||
'/user/' + encodeURIComponent(this._orig._name),
|
||||
detail,
|
||||
files) :
|
||||
api.post('/users', detail, files);
|
||||
uri.formatApiLink('user', this._orig._name), detail, files) :
|
||||
api.post(uri.formatApiLink('users'), detail, files);
|
||||
|
||||
return promise
|
||||
.then(response => {
|
||||
|
@ -92,7 +91,7 @@ class User extends events.EventTarget {
|
|||
|
||||
delete() {
|
||||
return api.delete(
|
||||
'/user/' + encodeURIComponent(this._orig._name),
|
||||
uri.formatApiLink('user', this._orig._name),
|
||||
{version: this._version})
|
||||
.then(response => {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const AbstractList = require('./abstract_list.js');
|
||||
const User = require('./user.js');
|
||||
|
||||
class UserList extends AbstractList {
|
||||
static search(text, page) {
|
||||
const url =
|
||||
`/users/?query=${encodeURIComponent(text)}` +
|
||||
`&page=${page}&pageSize=30`;
|
||||
return api.get(url).then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: UserList.fromResponse(response.results)}));
|
||||
});
|
||||
return api.get(
|
||||
uri.formatApiLink(
|
||||
'users', {query: text, page: page, pageSize: 30}))
|
||||
.then(response => {
|
||||
return Promise.resolve(Object.assign(
|
||||
{},
|
||||
response,
|
||||
{results: UserList.fromResponse(response.results)}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
// modified page.js by visionmedia
|
||||
// - changed regexes to components
|
||||
// - removed unused crap
|
||||
// - refactored to classes
|
||||
// - simplified method chains
|
||||
|
@ -9,19 +10,12 @@
|
|||
// - rename .save() to .replaceState()
|
||||
// - offer .url
|
||||
|
||||
const pathToRegexp = require('path-to-regexp');
|
||||
const clickEvent = document.ontouchstart ? 'touchstart' : 'click';
|
||||
const uri = require('./util/uri.js');
|
||||
let location = window.history.location || window.location;
|
||||
|
||||
const base = '';
|
||||
|
||||
function _decodeURLEncodedURIComponent(val) {
|
||||
if (typeof val !== 'string') {
|
||||
return val;
|
||||
}
|
||||
return decodeURIComponent(val.replace(/\+/g, ' '));
|
||||
}
|
||||
|
||||
function _isSameOrigin(href) {
|
||||
let origin = location.protocol + '//' + location.hostname;
|
||||
if (location.port) {
|
||||
|
@ -55,11 +49,28 @@ class Context {
|
|||
};
|
||||
|
||||
class Route {
|
||||
constructor(path, options) {
|
||||
options = options || {};
|
||||
this.path = (path === '*') ? '(.*)' : path;
|
||||
constructor(path) {
|
||||
this.method = 'GET';
|
||||
this.regexp = pathToRegexp(this.path, this.keys = [], options);
|
||||
this.path = path;
|
||||
|
||||
this.parameterNames = [];
|
||||
if (this.path === null) {
|
||||
this.regex = /.*/;
|
||||
} else {
|
||||
let parts = [];
|
||||
for (let component of this.path) {
|
||||
if (component[0] === ':') {
|
||||
parts.push('([^/]+)');
|
||||
this.parameterNames.push(component.substr(1));
|
||||
} else { // assert [a-z]+
|
||||
parts.push(component);
|
||||
}
|
||||
}
|
||||
let regexString = '^/' + parts.join('/');
|
||||
regexString += '(?:/*|/((?:(?:[a-z]+=[^/]+);)*(?:[a-z]+=[^/]+)))$';
|
||||
this.parameterNames.push('variable');
|
||||
this.regex = new RegExp(regexString);
|
||||
}
|
||||
}
|
||||
|
||||
middleware(fn) {
|
||||
|
@ -72,24 +83,39 @@ class Route {
|
|||
}
|
||||
|
||||
match(path, parameters) {
|
||||
const keys = this.keys;
|
||||
const qsIndex = path.indexOf('?');
|
||||
const pathname = ~qsIndex ? path.slice(0, qsIndex) : path;
|
||||
const m = this.regexp.exec(pathname);
|
||||
const match = this.regex.exec(pathname);
|
||||
|
||||
if (!m) {
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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(parameters, key.name))) {
|
||||
parameters[key.name] = val;
|
||||
try {
|
||||
for (let i = 1; i < match.length; i++) {
|
||||
const name = this.parameterNames[i - 1];
|
||||
const value = match[i];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name === 'variable') {
|
||||
for (let word of (value || '').split(/;/)) {
|
||||
const [key, subvalue] = word.split(/=/, 2);
|
||||
parameters[key] = uri.unescapeParam(subvalue);
|
||||
}
|
||||
} else {
|
||||
parameters[name] = uri.unescapeParam(value);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXX: it is very unfitting place for this
|
||||
parameters.query = parameters.query || '';
|
||||
parameters.page = parseInt(parameters.page || '1');
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const markdown = require('./markdown.js');
|
||||
const uri = require('./uri.js');
|
||||
|
||||
function decamelize(str, sep) {
|
||||
sep = sep === undefined ? '-' : sep;
|
||||
|
@ -99,44 +100,10 @@ function formatInlineMarkdown(text) {
|
|||
return markdown.formatInlineMarkdown(text);
|
||||
}
|
||||
|
||||
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}=${encodeURIComponent(value)}`);
|
||||
}
|
||||
}
|
||||
return result.join(';');
|
||||
}
|
||||
|
||||
function splitByWhitespace(str) {
|
||||
return str.split(/\s+/).filter(s => s);
|
||||
}
|
||||
|
||||
function parseUrlParameters(query) {
|
||||
let result = {};
|
||||
for (let word of (query || '').split(/;/)) {
|
||||
const [key, value] = word.split(/=/, 2);
|
||||
result[key] = value;
|
||||
}
|
||||
result.query = result.query || '';
|
||||
result.page = parseInt(result.page || '1');
|
||||
return result;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
function unindent(callSite, ...args) {
|
||||
function format(str) {
|
||||
let size = -1;
|
||||
|
@ -232,9 +199,6 @@ function dataURItoBlob(dataURI) {
|
|||
|
||||
module.exports = {
|
||||
range: range,
|
||||
formatUrlParameters: formatUrlParameters,
|
||||
parseUrlParameters: parseUrlParameters,
|
||||
parseUrlParametersRoute: parseUrlParametersRoute,
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
formatFileSize: formatFileSize,
|
||||
formatMarkdown: formatMarkdown,
|
||||
|
|
62
client/js/util/uri.js
Normal file
62
client/js/util/uri.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
'use strict';
|
||||
|
||||
function formatApiLink(...values) {
|
||||
let parts = [];
|
||||
for (let value of values) {
|
||||
if (value.constructor === Object) {
|
||||
// assert this is the last piece
|
||||
let variableParts = [];
|
||||
for (let key of Object.keys(value)) {
|
||||
if (value[key]) {
|
||||
variableParts.push(
|
||||
key + '=' + encodeURIComponent(value[key].toString()));
|
||||
}
|
||||
}
|
||||
if (variableParts.length) {
|
||||
parts.push('?' + variableParts.join('&'));
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
parts.push(encodeURIComponent(value.toString()));
|
||||
}
|
||||
}
|
||||
return '/' + parts.join('/');
|
||||
}
|
||||
|
||||
function escapeParam(text) {
|
||||
return encodeURIComponent(text).replace(/%/g, '$');
|
||||
}
|
||||
|
||||
function unescapeParam(text) {
|
||||
return decodeURIComponent(text.replace(/\$/g, '%'));
|
||||
}
|
||||
|
||||
function formatClientLink(...values) {
|
||||
let parts = [];
|
||||
for (let value of values) {
|
||||
if (value.constructor === Object) {
|
||||
// assert this is the last piece
|
||||
let variableParts = [];
|
||||
for (let key of Object.keys(value)) {
|
||||
if (value[key]) {
|
||||
variableParts.push(
|
||||
key + '=' + escapeParam(value[key].toString()));
|
||||
}
|
||||
}
|
||||
if (variableParts.length) {
|
||||
parts.push(variableParts.join(';'));
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
parts.push(escapeParam(value.toString()));
|
||||
}
|
||||
}
|
||||
return '/' + parts.join('/');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatClientLink: formatClientLink,
|
||||
formatApiLink: formatApiLink,
|
||||
escapeParam: escapeParam,
|
||||
unescapeParam: unescapeParam,
|
||||
};
|
|
@ -6,6 +6,7 @@ const templates = require('../templates.js');
|
|||
const tags = require('../tags.js');
|
||||
const domParser = new DOMParser();
|
||||
const misc = require('./misc.js');
|
||||
const uri = require('./uri.js');
|
||||
|
||||
function _imbueId(options) {
|
||||
if (!options.id) {
|
||||
|
@ -152,19 +153,15 @@ function makeNumericInput(options) {
|
|||
}
|
||||
|
||||
function getPostUrl(id, parameters) {
|
||||
let url = '/post/' + encodeURIComponent(id);
|
||||
if (parameters && parameters.query) {
|
||||
url += '/query=' + encodeURIComponent(parameters.query);
|
||||
}
|
||||
return url;
|
||||
return uri.formatClientLink(
|
||||
'post', id,
|
||||
parameters ? {query: parameters.query} : {});
|
||||
}
|
||||
|
||||
function getPostEditUrl(id, parameters) {
|
||||
let url = '/post/' + encodeURIComponent(id) + '/edit';
|
||||
if (parameters && parameters.query) {
|
||||
url += '/query=' + encodeURIComponent(parameters.query);
|
||||
}
|
||||
return url;
|
||||
return uri.formatClientLink(
|
||||
'post', id, 'edit',
|
||||
parameters ? {query: parameters.query} : {});
|
||||
}
|
||||
|
||||
function makePostLink(id, includeHash) {
|
||||
|
@ -175,7 +172,7 @@ function makePostLink(id, includeHash) {
|
|||
return api.hasPrivilege('posts:view') ?
|
||||
makeElement(
|
||||
'a',
|
||||
{'href': '/post/' + encodeURIComponent(id)},
|
||||
{href: uri.formatClientLink('post', id)},
|
||||
misc.escapeHtml(text)) :
|
||||
misc.escapeHtml(text);
|
||||
}
|
||||
|
@ -191,13 +188,13 @@ function makeTagLink(name, includeHash) {
|
|||
makeElement(
|
||||
'a',
|
||||
{
|
||||
'href': '/tag/' + encodeURIComponent(name),
|
||||
'class': misc.makeCssName(category, 'tag'),
|
||||
href: uri.formatClientLink('tag', name),
|
||||
class: misc.makeCssName(category, 'tag'),
|
||||
},
|
||||
misc.escapeHtml(text)) :
|
||||
makeElement(
|
||||
'span',
|
||||
{'class': misc.makeCssName(category, 'tag')},
|
||||
{class: misc.makeCssName(category, 'tag')},
|
||||
misc.escapeHtml(text));
|
||||
}
|
||||
|
||||
|
@ -206,7 +203,7 @@ function makeUserLink(user) {
|
|||
text += user && user.name ? misc.escapeHtml(user.name) : 'Anonymous';
|
||||
const link = user && api.hasPrivilege('users:view') ?
|
||||
makeElement(
|
||||
'a', {'href': '/user/' + encodeURIComponent(user.name)}, text) :
|
||||
'a', {href: uri.formatClientLink('user', user.name)}, text) :
|
||||
text;
|
||||
return makeElement('span', {class: 'user'}, link);
|
||||
}
|
||||
|
@ -385,6 +382,7 @@ function getTemplate(templatePath) {
|
|||
makeElement: makeElement,
|
||||
makeCssName: misc.makeCssName,
|
||||
makeNumericInput: makeNumericInput,
|
||||
formatClientLink: uri.formatClientLink
|
||||
});
|
||||
return htmlToDom(templateFactory(ctx));
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const router = require('../router.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const views = require('../util/views.js');
|
||||
const PostContentControl = require('../controls/post_content_control.js');
|
||||
const PostNotesOverlayControl
|
||||
|
@ -88,7 +88,7 @@ class HomeView {
|
|||
_evtFormSubmit(e) {
|
||||
e.preventDefault();
|
||||
this._searchInputNode.blur();
|
||||
router.show('/posts/' + misc.formatUrlParameters({
|
||||
router.show(uri.formatClientLink('posts', {
|
||||
query: this._searchInputNode.value}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
const router = require('../router.js');
|
||||
const keyboard = require('../util/keyboard.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
|
||||
const holderTemplate = views.getTemplate('manual-pager');
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const router = require('../router.js');
|
||||
const views = require('../util/views.js');
|
||||
const uri = require('../util/uri.js');
|
||||
const keyboard = require('../util/keyboard.js');
|
||||
const PostContentControl = require('../controls/post_content_control.js');
|
||||
const PostNotesOverlayControl =
|
||||
|
@ -61,19 +62,19 @@ class PostMainView {
|
|||
|
||||
keyboard.bind('e', () => {
|
||||
if (ctx.editMode) {
|
||||
router.show('/post/' + ctx.post.id);
|
||||
router.show(uri.formatClientLink('post', ctx.post.id));
|
||||
} else {
|
||||
router.show('/post/' + ctx.post.id + '/edit');
|
||||
router.show(uri.formatClientLink('post', ctx.post.id, 'edit'));
|
||||
}
|
||||
});
|
||||
keyboard.bind(['a', 'left'], () => {
|
||||
if (ctx.prevPostId) {
|
||||
router.show('/post/' + ctx.prevPostId);
|
||||
router.show(uri.formatClientLink('post', ctx.prevPostId));
|
||||
}
|
||||
});
|
||||
keyboard.bind(['d', 'right'], () => {
|
||||
if (ctx.nextPostId) {
|
||||
router.show('/post/' + ctx.nextPostId);
|
||||
router.show(uri.formatClientLink('post', ctx.nextPostId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const events = require('../events.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const search = require('../util/search.js');
|
||||
const views = require('../util/views.js');
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
"merge": "^1.2.0",
|
||||
"mousetrap": "^1.5.3",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^1.5.1",
|
||||
"stylus": "^0.54.2",
|
||||
"superagent": "^1.8.3",
|
||||
"uglify-js": "git://github.com/mishoo/UglifyJS2.git#harmony",
|
||||
|
|
Loading…
Reference in a new issue