Implement pool merging
This commit is contained in:
		
							parent
							
								
									ffba010ae4
								
							
						
					
					
						commit
						6b8e3f251f
					
				@ -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
 | 
			
		||||
            },
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,6 @@ from szurubooru import config, db, model, errors, rest
 | 
			
		||||
from szurubooru.func import util, pool_categories, serialization, posts
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PoolNotFoundError(errors.NotFoundError):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
@ -35,6 +34,10 @@ class InvalidPoolDescriptionError(errors.ValidationError):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InvalidPoolRelationError(errors.ValidationError):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _verify_name_validity(name: str) -> None:
 | 
			
		||||
    if util.value_exceeds_column_size(name, model.PoolName.name):
 | 
			
		||||
        raise InvalidPoolNameError('Name is too long.')
 | 
			
		||||
@ -211,45 +214,18 @@ def merge_pools(source_pool: model.Pool, target_pool: model.Pool) -> None:
 | 
			
		||||
        raise InvalidPoolRelationError('Cannot merge pool with itself.')
 | 
			
		||||
 | 
			
		||||
    def merge_posts(source_pool_id: int, target_pool_id: int) -> None:
 | 
			
		||||
        pass
 | 
			
		||||
        # alias1 = model.PostPool
 | 
			
		||||
        # alias2 = sa.orm.util.aliased(model.PostPool)
 | 
			
		||||
        # update_stmt = (
 | 
			
		||||
        #     sa.sql.expression.update(alias1)
 | 
			
		||||
        #     .where(alias1.pool_id == source_pool_id))
 | 
			
		||||
        # update_stmt = (
 | 
			
		||||
        #     update_stmt
 | 
			
		||||
        #     .where(
 | 
			
		||||
        #         ~sa.exists()
 | 
			
		||||
        #         .where(alias1.post_id == alias2.post_id)
 | 
			
		||||
        #         .where(alias2.pool_id == target_pool_id)))
 | 
			
		||||
        # update_stmt = update_stmt.values(pool_id=target_pool_id)
 | 
			
		||||
        # db.session.execute(update_stmt)
 | 
			
		||||
 | 
			
		||||
    def merge_relations(
 | 
			
		||||
            table: model.Base, source_pool_id: int, target_pool_id: int) -> None:
 | 
			
		||||
        alias1 = table
 | 
			
		||||
        alias2 = sa.orm.util.aliased(table)
 | 
			
		||||
        alias1 = model.PoolPost
 | 
			
		||||
        alias2 = sa.orm.util.aliased(model.PoolPost)
 | 
			
		||||
        update_stmt = (
 | 
			
		||||
            sa.sql.expression.update(alias1)
 | 
			
		||||
            .where(alias1.parent_id == source_pool_id)
 | 
			
		||||
            .where(alias1.child_id != target_pool_id)
 | 
			
		||||
            .where(
 | 
			
		||||
                ~sa.exists()
 | 
			
		||||
                .where(alias2.child_id == alias1.child_id)
 | 
			
		||||
                .where(alias2.parent_id == target_pool_id))
 | 
			
		||||
            .values(parent_id=target_pool_id))
 | 
			
		||||
        db.session.execute(update_stmt)
 | 
			
		||||
 | 
			
		||||
            .where(alias1.pool_id == source_pool_id))
 | 
			
		||||
        update_stmt = (
 | 
			
		||||
            sa.sql.expression.update(alias1)
 | 
			
		||||
            .where(alias1.child_id == source_pool_id)
 | 
			
		||||
            .where(alias1.parent_id != target_pool_id)
 | 
			
		||||
            update_stmt
 | 
			
		||||
            .where(
 | 
			
		||||
                ~sa.exists()
 | 
			
		||||
                .where(alias2.parent_id == alias1.parent_id)
 | 
			
		||||
                .where(alias2.child_id == target_pool_id))
 | 
			
		||||
            .values(child_id=target_pool_id))
 | 
			
		||||
                .where(alias1.post_id == alias2.post_id)
 | 
			
		||||
                .where(alias2.pool_id == target_pool_id)))
 | 
			
		||||
        update_stmt = update_stmt.values(pool_id=target_pool_id)
 | 
			
		||||
        db.session.execute(update_stmt)
 | 
			
		||||
 | 
			
		||||
    merge_posts(source_pool.pool_id, target_pool.pool_id)
 | 
			
		||||
@ -316,7 +292,6 @@ def update_pool_description(pool: model.Pool, description: str) -> None:
 | 
			
		||||
    pool.description = description or None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def update_pool_posts(pool: model.Pool, post_ids: List[int]) -> None:
 | 
			
		||||
    assert pool
 | 
			
		||||
    if _check_post_duplication(post_ids):
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user