mirror of
https://github.com/rr-/szurubooru.git
synced 2025-07-17 08:26:24 +00:00
Implement pool merging
This commit is contained in:
@ -15,7 +15,7 @@
|
||||
background: $top-navigation-color
|
||||
.names
|
||||
width: 84%
|
||||
.usages
|
||||
.post-count
|
||||
text-align: center
|
||||
width: 8%
|
||||
.creation-time
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class='content-wrapper' id='pool'>
|
||||
<h1><%- ctx.pool.first_name %></h1>
|
||||
<h1><%- ctx.pool.names[0] %></h1>
|
||||
<nav class='buttons'><!--
|
||||
--><ul><!--
|
||||
--><li data-name='summary'><a href='<%- ctx.formatClientLink('pool', ctx.pool.id) %>'>Summary</a></li><!--
|
||||
|
@ -11,9 +11,9 @@
|
||||
</th>
|
||||
<th class='post-count'>
|
||||
<% if (ctx.parameters.query == 'sort:post-count') { %>
|
||||
<a href='<%- ctx.formatClientLink('pools', {query: '-sort:post-count'}) %>'>Post Count</a>
|
||||
<a href='<%- ctx.formatClientLink('pools', {query: '-sort:post-count'}) %>'>Post count</a>
|
||||
<% } else { %>
|
||||
<a href='<%- ctx.formatClientLink('pools', {query: 'sort:post-count'}) %>'>Post Count</a>
|
||||
<a href='<%- ctx.formatClientLink('pools', {query: 'sort:post-count'}) %>'>Post count</a>
|
||||
<% } %>
|
||||
</th>
|
||||
<th class='creation-time'>
|
||||
|
@ -105,13 +105,13 @@ class PoolController {
|
||||
this._view.clearMessages();
|
||||
this._view.disableForm();
|
||||
e.detail.pool
|
||||
.merge(e.detail.targetPoolName, e.detail.addAlias)
|
||||
.merge(e.detail.targetPoolId, e.detail.addAlias)
|
||||
.then(() => {
|
||||
this._view.showSuccess('Pool merged.');
|
||||
this._view.enableForm();
|
||||
router.replace(
|
||||
uri.formatClientLink(
|
||||
'pool', e.detail.targetPoolName, 'merge'),
|
||||
'pool', e.detail.targetPoolId, 'merge'),
|
||||
null, false);
|
||||
}, error => {
|
||||
this._view.showError(error.message);
|
||||
|
@ -64,10 +64,6 @@ class PoolInputControl extends events.EventTarget {
|
||||
verticalShift: -2
|
||||
});
|
||||
|
||||
// dom events
|
||||
this._poolInputNode.addEventListener(
|
||||
'keydown', e => this._evtInputKeyDown(e));
|
||||
|
||||
// show
|
||||
this._hostNode.style.display = 'none';
|
||||
this._hostNode.parentNode.insertBefore(
|
||||
@ -117,23 +113,6 @@ class PoolInputControl extends events.EventTarget {
|
||||
this.dispatchEvent(new CustomEvent('change'));
|
||||
}
|
||||
|
||||
_evtAddPoolButtonClick(e) {
|
||||
// TODO
|
||||
// e.preventDefault();
|
||||
// this.addPoolByName(this._poolInputNode.value, SOURCE_USER_INPUT);
|
||||
// this._poolInputNode.value = '';
|
||||
}
|
||||
|
||||
_evtInputKeyDown(e) {
|
||||
// TODO
|
||||
if (e.which == KEY_RETURN || e.which == KEY_SPACE) {
|
||||
e.preventDefault();
|
||||
// this._hideAutoComplete();
|
||||
// this.addPoolByText(this._poolInputNode.value, SOURCE_USER_INPUT);
|
||||
// this._poolInputNode.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
_createListItemNode(pool) {
|
||||
const className = pool.category ?
|
||||
misc.makeCssName(pool.category, 'pool') :
|
||||
@ -159,10 +138,6 @@ class PoolInputControl extends events.EventTarget {
|
||||
'href', uri.formatClientLink(
|
||||
'posts', {query: "pool:" + pool.id}));
|
||||
searchLinkNode.textContent = pool.names[0] + ' ';
|
||||
searchLinkNode.addEventListener('click', e => {
|
||||
// TODO?
|
||||
// e.preventDefault();
|
||||
});
|
||||
|
||||
const usagesNode = document.createElement('span');
|
||||
usagesNode.classList.add('pool-usages');
|
||||
|
@ -8,6 +8,7 @@ const TagList = require('./tag_list.js');
|
||||
const NoteList = require('./note_list.js');
|
||||
const CommentList = require('./comment_list.js');
|
||||
const PoolList = require('./pool_list.js');
|
||||
const Pool = require('./pool.js');
|
||||
const misc = require('../util/misc.js');
|
||||
|
||||
class Post extends events.EventTarget {
|
||||
@ -98,22 +99,36 @@ class Post extends events.EventTarget {
|
||||
|
||||
_savePoolPosts() {
|
||||
const difference = (a, b) => a.filter(post => !b.hasPoolId(post.id));
|
||||
|
||||
// find the pools where the post was added or removed
|
||||
const added = difference(this.pools, this._orig._pools);
|
||||
const removed = difference(this._orig._pools, this.pools);
|
||||
|
||||
let ops = [];
|
||||
|
||||
// update each pool's list of posts
|
||||
for (let pool of added) {
|
||||
if (!pool.posts.hasPostId(this._id)) {
|
||||
pool.posts.addById(this._id);
|
||||
ops.push(pool.save());
|
||||
}
|
||||
let op = Pool.get(pool.id).then(response => {
|
||||
if (!response.posts.hasPostId(this._id)) {
|
||||
response.posts.addById(this._id);
|
||||
return response.save();
|
||||
} else {
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
});
|
||||
ops.push(op);
|
||||
}
|
||||
|
||||
for (let pool of removed) {
|
||||
if (pool.posts.hasPostId(this._id)) {
|
||||
pool.posts.removeById(this._id);
|
||||
ops.push(pool.save());
|
||||
}
|
||||
let op = Pool.get(pool.id).then(response => {
|
||||
if (response.posts.hasPostId(this._id)) {
|
||||
response.posts.removeById(this._id);
|
||||
return response.save();
|
||||
} else {
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
});
|
||||
ops.push(op);
|
||||
}
|
||||
|
||||
return Promise.all(ops);
|
||||
@ -156,34 +171,34 @@ class Post extends events.EventTarget {
|
||||
}
|
||||
|
||||
let apiPromise = this._id ?
|
||||
api.put(uri.formatApiLink('post', this.id), detail, files) :
|
||||
api.post(uri.formatApiLink('posts'), detail, files);
|
||||
api.put(uri.formatApiLink('post', this.id), detail, files) :
|
||||
api.post(uri.formatApiLink('posts'), detail, files);
|
||||
|
||||
return apiPromise.then(response => {
|
||||
if (this._pools !== this._orig._pools) {
|
||||
if (misc.arraysDiffer(this._pools, this._orig._pools)) {
|
||||
return this._savePoolPosts()
|
||||
.then(() => Promise.resolve(response));
|
||||
.then(() => Promise.resolve(response));
|
||||
}
|
||||
return Promise.resolve(response);
|
||||
}).then(response => {
|
||||
this._updateFromResponse(response);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('change', {detail: {post: this}}));
|
||||
new CustomEvent('change', {detail: {post: this}}));
|
||||
if (this._newContent) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('changeContent', {detail: {post: this}}));
|
||||
new CustomEvent('changeContent', {detail: {post: this}}));
|
||||
}
|
||||
if (this._newThumbnail) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('changeThumbnail', {detail: {post: this}}));
|
||||
new CustomEvent('changeThumbnail', {detail: {post: this}}));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}, error => {
|
||||
if (error.response &&
|
||||
error.response.name === 'PostAlreadyUploadedError') {
|
||||
error.response.name === 'PostAlreadyUploadedError') {
|
||||
error.message =
|
||||
`Post already uploaded (@${error.response.otherPostId})`;
|
||||
`Post already uploaded (@${error.response.otherPostId})`;
|
||||
}
|
||||
return Promise.reject(error);
|
||||
});
|
||||
@ -191,118 +206,118 @@ class Post extends events.EventTarget {
|
||||
|
||||
feature() {
|
||||
return api.post(
|
||||
uri.formatApiLink('featured-post'),
|
||||
{id: this._id})
|
||||
.then(response => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
uri.formatApiLink('featured-post'),
|
||||
{id: this._id})
|
||||
.then(response => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
delete() {
|
||||
return api.delete(
|
||||
uri.formatApiLink('post', this.id),
|
||||
{version: this._version})
|
||||
.then(response => {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
uri.formatApiLink('post', this.id),
|
||||
{version: this._version})
|
||||
.then(response => {
|
||||
this.dispatchEvent(new CustomEvent('delete', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
merge(targetId, useOldContent) {
|
||||
return api.get(uri.formatApiLink('post', targetId))
|
||||
.then(response => {
|
||||
return api.post(uri.formatApiLink('post-merge'), {
|
||||
removeVersion: this._version,
|
||||
remove: this._id,
|
||||
mergeToVersion: response.version,
|
||||
mergeTo: targetId,
|
||||
replaceContent: useOldContent,
|
||||
.then(response => {
|
||||
return api.post(uri.formatApiLink('post-merge'), {
|
||||
removeVersion: this._version,
|
||||
remove: this._id,
|
||||
mergeToVersion: response.version,
|
||||
mergeTo: targetId,
|
||||
replaceContent: useOldContent,
|
||||
});
|
||||
}).then(response => {
|
||||
this._updateFromResponse(response);
|
||||
this.dispatchEvent(new CustomEvent('change', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
}).then(response => {
|
||||
this._updateFromResponse(response);
|
||||
this.dispatchEvent(new CustomEvent('change', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
setScore(score) {
|
||||
return api.put(
|
||||
uri.formatApiLink('post', this.id, 'score'),
|
||||
{score: score})
|
||||
.then(response => {
|
||||
const prevFavorite = this._ownFavorite;
|
||||
this._updateFromResponse(response);
|
||||
if (this._ownFavorite !== prevFavorite) {
|
||||
uri.formatApiLink('post', this.id, 'score'),
|
||||
{score: score})
|
||||
.then(response => {
|
||||
const prevFavorite = this._ownFavorite;
|
||||
this._updateFromResponse(response);
|
||||
if (this._ownFavorite !== prevFavorite) {
|
||||
this.dispatchEvent(new CustomEvent('changeFavorite', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('changeScore', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addToFavorites() {
|
||||
return api.post(uri.formatApiLink('post', this.id, 'favorite'))
|
||||
.then(response => {
|
||||
const prevScore = this._ownScore;
|
||||
this._updateFromResponse(response);
|
||||
if (this._ownScore !== prevScore) {
|
||||
this.dispatchEvent(new CustomEvent('changeScore', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('changeFavorite', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('changeScore', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addToFavorites() {
|
||||
return api.post(uri.formatApiLink('post', this.id, 'favorite'))
|
||||
.then(response => {
|
||||
const prevScore = this._ownScore;
|
||||
this._updateFromResponse(response);
|
||||
if (this._ownScore !== prevScore) {
|
||||
this.dispatchEvent(new CustomEvent('changeScore', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('changeFavorite', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
removeFromFavorites() {
|
||||
return api.delete(uri.formatApiLink('post', this.id, 'favorite'))
|
||||
.then(response => {
|
||||
const prevScore = this._ownScore;
|
||||
this._updateFromResponse(response);
|
||||
if (this._ownScore !== prevScore) {
|
||||
this.dispatchEvent(new CustomEvent('changeScore', {
|
||||
.then(response => {
|
||||
const prevScore = this._ownScore;
|
||||
this._updateFromResponse(response);
|
||||
if (this._ownScore !== prevScore) {
|
||||
this.dispatchEvent(new CustomEvent('changeScore', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('changeFavorite', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('changeFavorite', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
});
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
mutateContentUrl() {
|
||||
this._contentUrl =
|
||||
this._orig._contentUrl +
|
||||
'?bypass-cache=' +
|
||||
Math.round(Math.random() * 1000);
|
||||
this._orig._contentUrl +
|
||||
'?bypass-cache=' +
|
||||
Math.round(Math.random() * 1000);
|
||||
}
|
||||
|
||||
_updateFromResponse(response) {
|
||||
|
@ -14,6 +14,7 @@ class PoolMergeView extends events.EventTarget {
|
||||
|
||||
this._pool = ctx.pool;
|
||||
this._hostNode = ctx.hostNode;
|
||||
this._target_pool_id = null;
|
||||
ctx.poolNamePattern = api.getPoolNameRegex();
|
||||
views.replaceContent(this._hostNode, template(ctx));
|
||||
|
||||
@ -22,9 +23,11 @@ class PoolMergeView extends events.EventTarget {
|
||||
this._autoCompleteControl = new PoolAutoCompleteControl(
|
||||
this._targetPoolFieldNode,
|
||||
{
|
||||
confirm: pool =>
|
||||
confirm: pool => {
|
||||
this._target_pool_id = pool.id;
|
||||
this._autoCompleteControl.replaceSelectedText(
|
||||
pool.names[0], false),
|
||||
pool.names[0], false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -56,7 +59,7 @@ class PoolMergeView extends events.EventTarget {
|
||||
this.dispatchEvent(new CustomEvent('submit', {
|
||||
detail: {
|
||||
pool: this._pool,
|
||||
targetPoolName: this._targetPoolFieldNode.value
|
||||
targetPoolId: this._target_pool_id
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
Reference in New Issue
Block a user