54e3099c56
- Controller lifetime is bound to route lifetime - View lifetime is bound to controller lifetime - Control lifetime is bound to view lifetime - Enhanced event dispatching - Enhanced responsiveness in some places - Views communicate user input to controllers via new event system
171 lines
5.8 KiB
JavaScript
171 lines
5.8 KiB
JavaScript
'use strict';
|
|
|
|
const api = require('../api.js');
|
|
const tags = require('../tags.js');
|
|
const views = require('../util/views.js');
|
|
|
|
class PostReadonlySidebarControl {
|
|
constructor(hostNode, post, postContentControl) {
|
|
this._hostNode = hostNode;
|
|
this._post = post;
|
|
this._postContentControl = postContentControl;
|
|
this._template = views.getTemplate('post-readonly-sidebar');
|
|
this._scoreTemplate = views.getTemplate('score');
|
|
this._favTemplate = views.getTemplate('fav');
|
|
|
|
this.install();
|
|
}
|
|
|
|
install() {
|
|
const sourceNode = this._template({
|
|
post: this._post,
|
|
getTagCategory: this._getTagCategory,
|
|
getTagUsages: this._getTagUsages,
|
|
canListPosts: api.hasPrivilege('posts:list'),
|
|
canViewTags: api.hasPrivilege('tags:view'),
|
|
});
|
|
|
|
views.replaceContent(
|
|
sourceNode.querySelector('.score-container'),
|
|
this._scoreTemplate({
|
|
score: this._post.score,
|
|
ownScore: this._post.ownScore,
|
|
canScore: api.hasPrivilege('posts:score'),
|
|
}));
|
|
|
|
views.replaceContent(
|
|
sourceNode.querySelector('.fav-container'),
|
|
this._favTemplate({
|
|
favoriteCount: this._post.favoriteCount,
|
|
ownFavorite: this._post.ownFavorite,
|
|
canFavorite: api.hasPrivilege('posts:favorite'),
|
|
}));
|
|
|
|
const upvoteButton = sourceNode.querySelector('.upvote');
|
|
const downvoteButton = sourceNode.querySelector('.downvote');
|
|
const addFavButton = sourceNode.querySelector('.add-favorite');
|
|
const remFavButton = sourceNode.querySelector('.remove-favorite');
|
|
const fitBothButton = sourceNode.querySelector('.fit-both');
|
|
const fitOriginalButton = sourceNode.querySelector('.fit-original');
|
|
const fitWidthButton = sourceNode.querySelector('.fit-width');
|
|
const fitHeightButton = sourceNode.querySelector('.fit-height');
|
|
|
|
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(
|
|
'click', this._eventRequestProxy(
|
|
() => this._addToFavorites()));
|
|
}
|
|
if (remFavButton) {
|
|
remFavButton.addEventListener(
|
|
'click', this._eventRequestProxy(
|
|
() => this._removeFromFavorites()));
|
|
}
|
|
|
|
fitBothButton.addEventListener(
|
|
'click', this._eventZoomProxy(
|
|
() => this._postContentControl.fitBoth()));
|
|
fitOriginalButton.addEventListener(
|
|
'click', this._eventZoomProxy(
|
|
() => this._postContentControl.fitOriginal()));
|
|
fitWidthButton.addEventListener(
|
|
'click', this._eventZoomProxy(
|
|
() => this._postContentControl.fitWidth()));
|
|
fitHeightButton.addEventListener(
|
|
'click', this._eventZoomProxy(
|
|
() => this._postContentControl.fitHeight()));
|
|
|
|
views.replaceContent(this._hostNode, sourceNode);
|
|
|
|
this._syncFitButton();
|
|
}
|
|
|
|
_eventZoomProxy(func) {
|
|
return e => {
|
|
e.preventDefault();
|
|
e.target.blur();
|
|
func();
|
|
this._syncFitButton();
|
|
};
|
|
}
|
|
|
|
_eventRequestProxy(promise) {
|
|
return e => {
|
|
e.preventDefault();
|
|
promise().then(() => {
|
|
this.install();
|
|
});
|
|
};
|
|
}
|
|
|
|
_syncFitButton() {
|
|
const funcToClassName = {};
|
|
funcToClassName[this._postContentControl.fitBoth] = 'fit-both';
|
|
funcToClassName[this._postContentControl.fitOriginal] = 'fit-original';
|
|
funcToClassName[this._postContentControl.fitWidth] = 'fit-width';
|
|
funcToClassName[this._postContentControl.fitHeight] = 'fit-height';
|
|
const className = funcToClassName[
|
|
this._postContentControl._currentFitFunction];
|
|
const oldNode = this._hostNode.querySelector('.zoom a.active');
|
|
const newNode = this._hostNode.querySelector(`.zoom a.${className}`);
|
|
if (oldNode) {
|
|
oldNode.classList.remove('active');
|
|
}
|
|
newNode.classList.add('active');
|
|
}
|
|
|
|
_getTagUsages(name) {
|
|
const tag = tags.getTagByName(name);
|
|
return tag ? tag.usages : 0;
|
|
}
|
|
|
|
_getTagCategory(name) {
|
|
const tag = tags.getTagByName(name);
|
|
return tag ? tag.category : 'unknown';
|
|
}
|
|
|
|
_setScore(score) {
|
|
return this._requestAndRefresh(
|
|
() => api.put('/post/' + this._post.id + '/score', {score: score}));
|
|
}
|
|
|
|
_addToFavorites() {
|
|
return this._requestAndRefresh(
|
|
() => api.post('/post/' + this._post.id + '/favorite'));
|
|
}
|
|
|
|
_removeFromFavorites() {
|
|
return this._requestAndRefresh(
|
|
() => api.delete('/post/' + this._post.id + '/favorite'));
|
|
}
|
|
|
|
_requestAndRefresh(requestPromise) {
|
|
return new Promise((resolve, reject) => {
|
|
requestPromise()
|
|
.then(
|
|
response => { return api.get('/post/' + this._post.id); },
|
|
response => { return Promise.reject(response); })
|
|
.then(
|
|
response => {
|
|
this._post = response;
|
|
resolve();
|
|
},
|
|
response => {
|
|
reject();
|
|
window.alert(response.description);
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports = PostReadonlySidebarControl;
|