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