client/general: respect privileges
This commit is contained in:
parent
0842d90ca2
commit
7566d2e0f3
12 changed files with 141 additions and 66 deletions
|
@ -28,7 +28,11 @@
|
|||
<span class='vim-nav-hint'>Back to view mode</span>
|
||||
</a>
|
||||
<% } else { %>
|
||||
<a href='/post/<%= ctx.post.id %>/edit'>
|
||||
<% if (ctx.canEditPosts) { %>
|
||||
<a href='/post/<%= ctx.post.id %>/edit'>
|
||||
<% } else { %>
|
||||
<a class='inactive'>
|
||||
<% } %>
|
||||
<i class='fa fa-pencil'></i>
|
||||
<span class='vim-nav-hint'>Edit post</span>
|
||||
</a>
|
||||
|
|
|
@ -39,30 +39,42 @@
|
|||
|
||||
<section class='social'>
|
||||
<div class='score'>
|
||||
<a class='upvote' href='#'>
|
||||
<% if (ctx.post.ownScore == 1) { %>
|
||||
<i class='fa fa-thumbs-up'></i>
|
||||
<% } else { %>
|
||||
<% if (ctx.canScorePosts) { %>
|
||||
<a class='upvote' href='#'>
|
||||
<% if (ctx.post.ownScore == 1) { %>
|
||||
<i class='fa fa-thumbs-up'></i>
|
||||
<% } else { %>
|
||||
<i class='fa fa-thumbs-o-up'></i>
|
||||
<% } %>
|
||||
<span class='hint'></span>
|
||||
</a>
|
||||
<% } else { %>
|
||||
<a class='upvote inactive'>
|
||||
<i class='fa fa-thumbs-o-up'></i>
|
||||
<% } %>
|
||||
<span class='hint'></span>
|
||||
</a>
|
||||
</a>
|
||||
<% } %>
|
||||
<span class='value'><%= ctx.post.score %></span>
|
||||
<a class='downvote' href='#'>
|
||||
<% if (ctx.post.ownScore == -1) { %>
|
||||
<i class='fa fa-thumbs-down'></i>
|
||||
<% } else { %>
|
||||
<i class='fa fa-thumbs-o-down'></i>
|
||||
<% } %>
|
||||
<span class='hint'></span>
|
||||
</a>
|
||||
<% if (ctx.canScorePosts) { %>
|
||||
<a class='downvote' href='#'>
|
||||
<% if (ctx.post.ownScore == -1) { %>
|
||||
<i class='fa fa-thumbs-down'></i>
|
||||
<% } else { %>
|
||||
<i class='fa fa-thumbs-o-down'></i>
|
||||
<% } %>
|
||||
<span class='hint'></span>
|
||||
</a>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class='fav'>
|
||||
<% if (ctx.post.ownFavorite) { %>
|
||||
<a class='remove-favorite' href='#'><i class='fa fa-heart'></i></a>
|
||||
<% if (ctx.canFavoritePosts) { %>
|
||||
<% if (ctx.post.ownFavorite) { %>
|
||||
<a class='remove-favorite' href='#'><i class='fa fa-heart'></i></a>
|
||||
<% } else { %>
|
||||
<a class='add-favorite' href='#'><i class='fa fa-heart-o'></i></a>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<a class='add-favorite' href='#'><i class='fa fa-heart-o'></i></a>
|
||||
<a class='add-favorite inactive'><i class='fa fa-heart-o'></i></a>
|
||||
<% } %>
|
||||
<span class='value'><%= ctx.post.favoriteCount %></span>
|
||||
</div>
|
||||
|
@ -74,12 +86,20 @@
|
|||
<ul><!--
|
||||
--><% for (let tag of ctx.post.tags) { %><!--
|
||||
--><li><!--
|
||||
--><% if (ctx.canViewTags) { %><!--
|
||||
--><a href='/tag/<%= tag %>' class='tag-<%= ctx.getTagCategory(tag) %>'><!--
|
||||
--><i class='fa fa-tag'></i><!--
|
||||
--></a><!--
|
||||
--><a href='/posts/text=<%= tag %>' class='tag-<%= ctx.getTagCategory(tag) %>'><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canListPosts) { %><!--
|
||||
--></a><!--
|
||||
--><% } %><!--
|
||||
--><% if (ctx.canListPosts) { %><!--
|
||||
--><a href='/posts/text=<%= tag %>' class='tag-<%= ctx.getTagCategory(tag) %>'><!--
|
||||
--><% } %><!--
|
||||
--><%= tag %><!--
|
||||
--></a><!--
|
||||
--><% if (ctx.canListPosts) { %><!--
|
||||
--></a><!--
|
||||
--><% } %><!--
|
||||
--><span class='count'><%= ctx.getTagUsages(tag) %></span><!--
|
||||
--></li><!--
|
||||
--><% } %><!--
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
<ul>
|
||||
<% for (let post of ctx.results) { %>
|
||||
<li>
|
||||
<a href='/post/<%= post.id %>' title='@<%= post.id %> (<%= post.type %>) Tags: <%= post.tags.map(tag => '#' + tag).join(' ') %>'>
|
||||
<% if (ctx.canViewPosts) { %>
|
||||
<a href='/post/<%= post.id %>' title='@<%= post.id %> (<%= post.type %>) Tags: <%= post.tags.map(tag => '#' + tag).join(' ') %>'>
|
||||
<% } else { %>
|
||||
<a>
|
||||
<% } %>
|
||||
<%= ctx.makeThumbnail(post.thumbnailUrl) %>
|
||||
<span class='type' data-type='<%= post.type %>'>
|
||||
<%= post.type %>
|
||||
|
|
|
@ -3,9 +3,22 @@
|
|||
--><% for (let user of ctx.results) { %><!--
|
||||
--><li>
|
||||
<div class='wrapper'>
|
||||
<a class='image' href='/user/<%= user.name %>'><%= ctx.makeThumbnail(user.avatarUrl) %></a>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
<a class='image' href='/user/<%= user.name %>'>
|
||||
<% } %>
|
||||
<%= ctx.makeThumbnail(user.avatarUrl) %>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
</a>
|
||||
<% } %>
|
||||
<div class='details'>
|
||||
<a href='/user/<%= user.name %>'><%= user.name %></a><br/>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
<a href='/user/<%= user.name %>'>
|
||||
<% } %>
|
||||
<%= user.name %>
|
||||
<% if (ctx.canViewUsers) { %>
|
||||
</a>
|
||||
<% } %>
|
||||
<br/>
|
||||
Registered: <%= ctx.makeRelativeTime(user.creationTime) %><br/>
|
||||
Last seen: <%= ctx.makeRelativeTime(user.lastLoginTime) %>
|
||||
</div>
|
||||
|
|
|
@ -24,6 +24,17 @@ class PageController {
|
|||
|
||||
run(ctx) {
|
||||
this._pageView.unrender();
|
||||
|
||||
ctx.headerContext = ctx.headerContext || {};
|
||||
Object.assign(ctx.headerContext, {
|
||||
searchQuery: ctx.searchQuery,
|
||||
});
|
||||
|
||||
ctx.pageContext = ctx.pageContext || {};
|
||||
Object.assign(ctx.pageContext, {
|
||||
searchQuery: ctx.searchQuery,
|
||||
});
|
||||
|
||||
this._pageView.render(ctx);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ class PostsController {
|
|||
topNavController.activate('posts');
|
||||
|
||||
pageController.run({
|
||||
state: ctx.state,
|
||||
searchQuery: ctx.searchQuery,
|
||||
clientUrl: '/posts/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
requestPage: page => {
|
||||
const text = this._decorateSearchQuery(ctx.searchQuery.text);
|
||||
return api.get(
|
||||
|
@ -50,11 +52,11 @@ class PostsController {
|
|||
`id,type,tags,score,favoriteCount,` +
|
||||
`commentCount,thumbnailUrl`);
|
||||
},
|
||||
clientUrl: '/posts/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
searchQuery: ctx.searchQuery,
|
||||
headerRenderer: this._postsHeaderView,
|
||||
pageRenderer: this._postsPageView,
|
||||
pageContext: {
|
||||
canViewPosts: api.hasPrivilege('posts:view'),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -71,6 +73,7 @@ class PostsController {
|
|||
editMode: editMode,
|
||||
nextPostId: aroundResponse.next ? aroundResponse.next.id : null,
|
||||
prevPostId: aroundResponse.prev ? aroundResponse.prev.id : null,
|
||||
canEditPosts: api.hasPrivilege('posts:edit'),
|
||||
});
|
||||
}, response => {
|
||||
this._emptyView.render();
|
||||
|
|
|
@ -202,18 +202,19 @@ class TagsController {
|
|||
topNavController.activate('tags');
|
||||
|
||||
pageController.run({
|
||||
state: ctx.state,
|
||||
searchQuery: ctx.searchQuery,
|
||||
clientUrl: '/tags/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
requestPage: page => {
|
||||
const text = ctx.searchQuery.text;
|
||||
return api.get(
|
||||
`/tags/?query=${text}&page=${page}&pageSize=50`);
|
||||
},
|
||||
clientUrl: '/tags/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
searchQuery: ctx.searchQuery,
|
||||
headerRenderer: this._tagsHeaderView,
|
||||
pageRenderer: this._tagsPageView,
|
||||
canEditTagCategories: api.hasPrivilege('tagCategories:edit'),
|
||||
headerContext: {
|
||||
canEditTagCategories: api.hasPrivilege('tagCategories:edit'),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,17 +65,19 @@ class UsersController {
|
|||
topNavController.activate('users');
|
||||
|
||||
pageController.run({
|
||||
state: ctx.state,
|
||||
searchQuery: ctx.searchQuery,
|
||||
clientUrl: '/users/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
requestPage: page => {
|
||||
const text = ctx.searchQuery.text;
|
||||
return api.get(
|
||||
`/users/?query=${text}&page=${page}&pageSize=30`);
|
||||
},
|
||||
clientUrl: '/users/' + misc.formatSearchQuery({
|
||||
text: ctx.searchQuery.text, page: '{page}'}),
|
||||
searchQuery: ctx.searchQuery,
|
||||
headerRenderer: this._usersHeaderView,
|
||||
pageRenderer: this._usersPageView,
|
||||
pageContext: {
|
||||
canViewUsers: api.hasPrivilege('users:view'),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ class PostReadonlySidebarControl {
|
|||
post: this._post,
|
||||
getTagCategory: this._getTagCategory,
|
||||
getTagUsages: this._getTagUsages,
|
||||
canListPosts: api.hasPrivilege('posts:list'),
|
||||
canScorePosts: api.hasPrivilege('posts:score'),
|
||||
canFavoritePosts: api.hasPrivilege('posts:favorite'),
|
||||
canViewTags: api.hasPrivilege('tags:view'),
|
||||
});
|
||||
const upvoteButton = sourceNode.querySelector('.upvote');
|
||||
const downvoteButton = sourceNode.querySelector('.downvote')
|
||||
|
@ -29,12 +33,16 @@ class PostReadonlySidebarControl {
|
|||
const fitWidthButton = sourceNode.querySelector('.fit-width')
|
||||
const fitHeightButton = sourceNode.querySelector('.fit-height');
|
||||
|
||||
upvoteButton.addEventListener(
|
||||
'click', this._eventRequestProxy(
|
||||
() => this._setScore(this._post.ownScore === 1 ? 0 : 1)));
|
||||
downvoteButton.addEventListener(
|
||||
'click', this._eventRequestProxy(
|
||||
() => this._setScore(this._post.ownScore === -1 ? 0 : -1)));
|
||||
if (upvoteButton) {
|
||||
upvoteButton.addEventListener(
|
||||
'click', this._eventRequestProxy(
|
||||
() => this._setScore(this._post.ownScore === 1 ? 0 : 1)));
|
||||
}
|
||||
if (downvoteButton) {
|
||||
downvoteButton.addEventListener(
|
||||
'click', this._eventRequestProxy(
|
||||
() => this._setScore(this._post.ownScore === -1 ? 0 : -1)));
|
||||
}
|
||||
|
||||
if (addFavButton) {
|
||||
addFavButton.addEventListener(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
require('../util/polyfill.js');
|
||||
const api = require('../api.js');
|
||||
const templates = require('../templates.js');
|
||||
const tags = require('../tags.js');
|
||||
const events = require('../events.js');
|
||||
|
@ -137,25 +138,35 @@ function makeColorInput(options) {
|
|||
}
|
||||
|
||||
function makePostLink(id) {
|
||||
return makeNonVoidElement('a', {
|
||||
'href': '/post/' + id,
|
||||
}, '@' + id);
|
||||
const text = '@' + id;
|
||||
return api.hasPrivilege('posts:view') ?
|
||||
makeNonVoidElement('a', {'href': '/post/' + id}, text) :
|
||||
text;
|
||||
}
|
||||
|
||||
function makeTagLink(name) {
|
||||
const tag = tags.getTagByName(name);
|
||||
let category = tag ? tag.category : 'unknown';
|
||||
return makeNonVoidElement('a', {
|
||||
'href': '/tag/' + name,
|
||||
'class': 'tag-' + category,
|
||||
}, name);
|
||||
const category = tag ? tag.category : 'unknown';
|
||||
return api.hasPrivilege('tags:view') ?
|
||||
makeNonVoidElement(
|
||||
'a', {
|
||||
'href': '/tag/' + name,
|
||||
'class': 'tag-' + category,
|
||||
}, name) :
|
||||
makeNonVoidElement(
|
||||
'span', {
|
||||
'class': 'tag-' + category,
|
||||
},
|
||||
name);
|
||||
}
|
||||
|
||||
function makeUserLink(user) {
|
||||
let link = api.hasPrivilege('users:view') ?
|
||||
makeNonVoidElement('a', {'href': '/user/' + user.name}, user.name) :
|
||||
user.name;
|
||||
return makeNonVoidElement('span', {class: 'user'},
|
||||
makeThumbnail(user.avatarUrl) +
|
||||
makeNonVoidElement(
|
||||
'a', {'href': '/user/' + user.name}, user.name));
|
||||
link);
|
||||
}
|
||||
|
||||
function makeFlexboxAlign(options) {
|
||||
|
|
|
@ -24,9 +24,8 @@ class EndlessPageView {
|
|||
this._active = true;
|
||||
this._working = 0;
|
||||
|
||||
let headerRendererCtx = ctx;
|
||||
headerRendererCtx.target = pageHeaderHolder;
|
||||
ctx.headerRenderer.render(headerRendererCtx);
|
||||
ctx.headerContext.target = pageHeaderHolder;
|
||||
ctx.headerRenderer.render(ctx.headerContext);
|
||||
|
||||
const threshold = window.innerHeight / 3;
|
||||
|
||||
|
@ -115,10 +114,10 @@ class EndlessPageView {
|
|||
});
|
||||
pageNode.setAttribute('data-page', pageNumber);
|
||||
|
||||
let pageRendererCtx = response;
|
||||
pageRendererCtx.target = pageNode.querySelector(
|
||||
Object.assign(ctx.pageContext, response);
|
||||
ctx.pageContext.target = pageNode.querySelector(
|
||||
'.page-content-holder');
|
||||
ctx.pageRenderer.render(pageRendererCtx);
|
||||
ctx.pageRenderer.render(ctx.pageContext);
|
||||
|
||||
if (pageNumber < this.minPageShown ||
|
||||
this.minPageShown === null) {
|
||||
|
|
|
@ -69,14 +69,13 @@ class ManualPageView {
|
|||
const pageNav = source.querySelector('.page-nav');
|
||||
const currentPage = ctx.searchQuery.page;
|
||||
|
||||
let headerRendererCtx = ctx;
|
||||
headerRendererCtx.target = pageHeaderHolder;
|
||||
ctx.headerRenderer.render(headerRendererCtx);
|
||||
ctx.headerContext.target = pageHeaderHolder;
|
||||
ctx.headerRenderer.render(ctx.headerContext);
|
||||
|
||||
ctx.requestPage(currentPage).then(response => {
|
||||
let pageRendererCtx = response;
|
||||
pageRendererCtx.target = pageContentHolder;
|
||||
ctx.pageRenderer.render(pageRendererCtx);
|
||||
Object.assign(ctx.pageContext, response);
|
||||
ctx.pageContext.target = pageContentHolder;
|
||||
ctx.pageRenderer.render(ctx.pageContext);
|
||||
|
||||
const totalPages = Math.ceil(response.total / response.pageSize);
|
||||
const pageNumbers = _getVisiblePageNumbers(currentPage, totalPages);
|
||||
|
|
Loading…
Reference in a new issue