Implement updating pools of a post from details sidebar

This commit is contained in:
Ruin0x11 2020-05-04 14:44:16 -07:00
parent 8795279a73
commit ffba010ae4
10 changed files with 79 additions and 35 deletions

View file

@ -35,7 +35,7 @@ const app_manifest = {
src: baseUrl() + 'img/android-chrome-192x192.png', src: baseUrl() + 'img/android-chrome-192x192.png',
type: 'image/png', type: 'image/png',
sizes: '192x192' sizes: '192x192'
}, },
{ {
src: baseUrl() + 'img/android-chrome-512x512.png', src: baseUrl() + 'img/android-chrome-512x512.png',
type: 'image/png', type: 'image/png',
@ -301,8 +301,12 @@ function makeOutputDirs() {
makeOutputDirs(); makeOutputDirs();
bundleConfig(); bundleConfig();
bundleBinaryAssets(); if (!process.argv.includes('--no-binary-assets')) {
bundleWebAppFiles(); bundleBinaryAssets();
}
if (!process.argv.includes('--no-web-app-files')) {
bundleWebAppFiles();
}
if (!process.argv.includes('--no-html')) { if (!process.argv.includes('--no-html')) {
bundleHtml(); bundleHtml();
} }

View file

@ -4,7 +4,7 @@
--><li data-name='posts'><a href='<%- ctx.formatClientLink('help', 'search', 'posts') %>'>Posts</a></li><!-- --><li data-name='posts'><a href='<%- ctx.formatClientLink('help', 'search', 'posts') %>'>Posts</a></li><!--
--><li data-name='users'><a href='<%- ctx.formatClientLink('help', 'search', 'users') %>'>Users</a></li><!-- --><li data-name='users'><a href='<%- ctx.formatClientLink('help', 'search', 'users') %>'>Users</a></li><!--
--><li data-name='tags'><a href='<%- ctx.formatClientLink('help', 'search', 'tags') %>'>Tags</a></li><!-- --><li data-name='tags'><a href='<%- ctx.formatClientLink('help', 'search', 'tags') %>'>Tags</a></li><!--
--><li data-name='pools'><a href='<%- ctx.formatClientLink('help', 'search', 'pools') %>'>Pools</a></li><!-- --><li data-name='pools'><a href='<%- ctx.formatClientLink('help', 'search', 'pools') %>'>Pools></li><!--
--></ul><!-- --></ul><!--
--></nav> --></nav>

View file

@ -26,6 +26,7 @@
<%= ctx.makeTextInput({ <%= ctx.makeTextInput({
text: 'Posts', text: 'Posts',
value: '', value: '',
placeholder: 'space-separated post IDs',
}) %> }) %>
</li> </li>
</ul> </ul>

View file

@ -32,6 +32,7 @@
<% if (ctx.canEditPosts) { %> <% if (ctx.canEditPosts) { %>
<%= ctx.makeTextInput({ <%= ctx.makeTextInput({
text: 'Posts', text: 'Posts',
placeholder: 'space-separated post IDs',
value: ctx.pool.posts.map(post => post.id).join(' ') value: ctx.pool.posts.map(post => post.id).join(' ')
}) %> }) %>
<% } %> <% } %>

View file

@ -73,6 +73,12 @@
</section> </section>
<% } %> <% } %>
<% if (ctx.canEditPoolPosts) { %>
<section class='pools'>
<%= ctx.makeTextInput({}) %>
</section>
<% } %>
<% if (ctx.canEditPostNotes) { %> <% if (ctx.canEditPostNotes) { %>
<section class='notes'> <section class='notes'>
<a href class='add'>Add a note</a> <a href class='add'>Add a note</a>
@ -87,12 +93,6 @@
</section> </section>
<% } %> <% } %>
<% if (ctx.canEditPoolPosts) { %>
<section class='pools'>
<%= ctx.makeTextInput({}) %>
</section>
<% } %>
<% if (ctx.canEditPostContent) { %> <% if (ctx.canEditPostContent) { %>
<section class='post-content'> <section class='post-content'>
<label>Content</label> <label>Content</label>

View file

@ -34,7 +34,7 @@ class PoolAutoCompleteControl extends AutoCompleteControl {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
PoolList.search( PoolList.search(
query, 0, this._options.maxResults, query, 0, this._options.maxResults,
['id', 'names', 'category', 'postCount']) ['id', 'names', 'category', 'postCount', 'version'])
.then( .then(
response => resolve( response => resolve(
_poolListToMatches(response.results, this._options)), _poolListToMatches(response.results, this._options)),

View file

@ -80,27 +80,6 @@ class PoolInputControl extends events.EventTarget {
} }
} }
addPoolByText(text, source) {
for (let poolName of text.split(/\s+/).filter(word => word).reverse()) {
this.addPoolByName(poolName, source);
}
}
addPoolByName(name, source) {
name = name.trim();
if (!name) {
return;
}
return Pool.get(name).then(pool => {
return this.addPool(pool, source);
}, () => {
const pool = new Pool();
pool.names = [name];
pool.category = null;
return this.addPool(pool, source);
});
}
addPool(pool, source) { addPool(pool, source) {
if (source != SOURCE_INIT && this.pools.hasPoolId(pool.id)) { if (source != SOURCE_INIT && this.pools.hasPoolId(pool.id)) {
return Promise.resolve(); return Promise.resolve();
@ -178,10 +157,11 @@ class PoolInputControl extends events.EventTarget {
} }
searchLinkNode.setAttribute( searchLinkNode.setAttribute(
'href', uri.formatClientLink( 'href', uri.formatClientLink(
'posts', {query: uri.escapeColons(pool.names[0])})); 'posts', {query: "pool:" + pool.id}));
searchLinkNode.textContent = pool.names[0] + ' '; searchLinkNode.textContent = pool.names[0] + ' ';
searchLinkNode.addEventListener('click', e => { searchLinkNode.addEventListener('click', e => {
e.preventDefault(); // TODO?
// e.preventDefault();
}); });
const usagesNode = document.createElement('span'); const usagesNode = document.createElement('span');

View file

@ -86,6 +86,10 @@ class AbstractList extends events.EventTarget {
return this._list.map(...args); return this._list.map(...args);
} }
filter(...args) {
return this._list.filter(...args);
}
[Symbol.iterator]() { [Symbol.iterator]() {
return this._list[Symbol.iterator](); return this._list[Symbol.iterator]();
} }

View file

@ -96,6 +96,29 @@ class Post extends events.EventTarget {
}); });
} }
_savePoolPosts() {
const difference = (a, b) => a.filter(post => !b.hasPoolId(post.id));
const added = difference(this.pools, this._orig._pools);
const removed = difference(this._orig._pools, this.pools);
let ops = [];
for (let pool of added) {
if (!pool.posts.hasPostId(this._id)) {
pool.posts.addById(this._id);
ops.push(pool.save());
}
}
for (let pool of removed) {
if (pool.posts.hasPostId(this._id)) {
pool.posts.removeById(this._id);
ops.push(pool.save());
}
}
return Promise.all(ops);
}
save(anonymous) { save(anonymous) {
const files = {}; const files = {};
const detail = {version: this._version}; const detail = {version: this._version};
@ -131,13 +154,18 @@ class Post extends events.EventTarget {
if (this._source !== this._orig._source) { if (this._source !== this._orig._source) {
detail.source = this._source; detail.source = this._source;
} }
// TODO pools
let apiPromise = this._id ? let apiPromise = this._id ?
api.put(uri.formatApiLink('post', this.id), detail, files) : api.put(uri.formatApiLink('post', this.id), detail, files) :
api.post(uri.formatApiLink('posts'), detail, files); api.post(uri.formatApiLink('posts'), detail, files);
return apiPromise.then(response => { return apiPromise.then(response => {
if (this._pools !== this._orig._pools) {
return this._savePoolPosts()
.then(() => Promise.resolve(response));
}
return Promise.resolve(response);
}).then(response => {
this._updateFromResponse(response); this._updateFromResponse(response);
this.dispatchEvent( this.dispatchEvent(
new CustomEvent('change', {detail: {post: this}})); new CustomEvent('change', {detail: {post: this}}));
@ -149,6 +177,7 @@ class Post extends events.EventTarget {
this.dispatchEvent( this.dispatchEvent(
new CustomEvent('changeThumbnail', {detail: {post: this}})); new CustomEvent('changeThumbnail', {detail: {post: this}}));
} }
return Promise.resolve(); return Promise.resolve();
}, error => { }, error => {
if (error.response && if (error.response &&

View file

@ -49,6 +49,31 @@ class PostList extends AbstractList {
return text.trim(); return text.trim();
} }
hasPostId(testId) {
for (let post of this._list) {
if (post.id === testId) {
return true;
}
}
return false;
}
addById(id) {
if (this.hasPostId(id)) {
return;
}
let post = new Post.fromResponse({id: id});
this.add(post);
}
removeById(testId) {
for (let post of this._list) {
if (post.id === testId) {
this.remove(post);
}
}
}
} }
PostList._itemClass = Post; PostList._itemClass = Post;