-
<%= ctx.makeThumbnail(user.avatarUrl) %>
+ <% if (ctx.canViewUsers) { %>
+
+ <% } %>
+ <%= ctx.makeThumbnail(user.avatarUrl) %>
+ <% if (ctx.canViewUsers) { %>
+
+ <% } %>
diff --git a/client/js/controllers/page_controller.js b/client/js/controllers/page_controller.js
index ee4f4f19..0db05b4e 100644
--- a/client/js/controllers/page_controller.js
+++ b/client/js/controllers/page_controller.js
@@ -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);
}
diff --git a/client/js/controllers/posts_controller.js b/client/js/controllers/posts_controller.js
index e4da2271..f65fd405 100644
--- a/client/js/controllers/posts_controller.js
+++ b/client/js/controllers/posts_controller.js
@@ -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();
diff --git a/client/js/controllers/tags_controller.js b/client/js/controllers/tags_controller.js
index bf202ea9..e0e3de1f 100644
--- a/client/js/controllers/tags_controller.js
+++ b/client/js/controllers/tags_controller.js
@@ -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'),
+ },
});
}
}
diff --git a/client/js/controllers/users_controller.js b/client/js/controllers/users_controller.js
index fc9bbf2d..8691eb36 100644
--- a/client/js/controllers/users_controller.js
+++ b/client/js/controllers/users_controller.js
@@ -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'),
+ },
});
}
diff --git a/client/js/controls/post_readonly_sidebar_control.js b/client/js/controls/post_readonly_sidebar_control.js
index ff49af21..fafa12bc 100644
--- a/client/js/controls/post_readonly_sidebar_control.js
+++ b/client/js/controls/post_readonly_sidebar_control.js
@@ -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(
diff --git a/client/js/util/views.js b/client/js/util/views.js
index 69f15dc9..370322f5 100644
--- a/client/js/util/views.js
+++ b/client/js/util/views.js
@@ -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) {
diff --git a/client/js/views/endless_page_view.js b/client/js/views/endless_page_view.js
index 6c54d3b0..482de23f 100644
--- a/client/js/views/endless_page_view.js
+++ b/client/js/views/endless_page_view.js
@@ -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) {
diff --git a/client/js/views/manual_page_view.js b/client/js/views/manual_page_view.js
index baeafc21..fe93bb8a 100644
--- a/client/js/views/manual_page_view.js
+++ b/client/js/views/manual_page_view.js
@@ -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);