diff --git a/client/build.js b/client/build.js
index 44d8c010..19c7aeb3 100755
--- a/client/build.js
+++ b/client/build.js
@@ -35,7 +35,7 @@ const app_manifest = {
src: baseUrl() + 'img/android-chrome-192x192.png',
type: 'image/png',
sizes: '192x192'
- },
+ },
{
src: baseUrl() + 'img/android-chrome-512x512.png',
type: 'image/png',
@@ -301,8 +301,12 @@ function makeOutputDirs() {
makeOutputDirs();
bundleConfig();
-bundleBinaryAssets();
-bundleWebAppFiles();
+if (!process.argv.includes('--no-binary-assets')) {
+ bundleBinaryAssets();
+}
+if (!process.argv.includes('--no-web-app-files')) {
+ bundleWebAppFiles();
+}
if (!process.argv.includes('--no-html')) {
bundleHtml();
}
diff --git a/client/html/help_search.tpl b/client/html/help_search.tpl
index d8708b01..f228ee35 100644
--- a/client/html/help_search.tpl
+++ b/client/html/help_search.tpl
@@ -4,7 +4,7 @@
-->
'>Posts'>Users'>Tags'>Pools'>Pools>
diff --git a/client/html/pool_create.tpl b/client/html/pool_create.tpl
index bf84dc92..3c04545c 100644
--- a/client/html/pool_create.tpl
+++ b/client/html/pool_create.tpl
@@ -26,6 +26,7 @@
<%= ctx.makeTextInput({
text: 'Posts',
value: '',
+ placeholder: 'space-separated post IDs',
}) %>
diff --git a/client/html/pool_edit.tpl b/client/html/pool_edit.tpl
index 1cbb62e3..c9f2adb9 100644
--- a/client/html/pool_edit.tpl
+++ b/client/html/pool_edit.tpl
@@ -32,6 +32,7 @@
<% if (ctx.canEditPosts) { %>
<%= ctx.makeTextInput({
text: 'Posts',
+ placeholder: 'space-separated post IDs',
value: ctx.pool.posts.map(post => post.id).join(' ')
}) %>
<% } %>
diff --git a/client/html/post_edit_sidebar.tpl b/client/html/post_edit_sidebar.tpl
index 458a6f08..07dcf6f8 100644
--- a/client/html/post_edit_sidebar.tpl
+++ b/client/html/post_edit_sidebar.tpl
@@ -73,6 +73,12 @@
<% } %>
+ <% if (ctx.canEditPoolPosts) { %>
+
+ <%= ctx.makeTextInput({}) %>
+
+ <% } %>
+
<% if (ctx.canEditPostNotes) { %>
<% } %>
- <% if (ctx.canEditPoolPosts) { %>
-
- <%= ctx.makeTextInput({}) %>
-
- <% } %>
-
<% if (ctx.canEditPostContent) { %>
diff --git a/client/js/controls/pool_auto_complete_control.js b/client/js/controls/pool_auto_complete_control.js
index 0230c41d..d8ffa96a 100644
--- a/client/js/controls/pool_auto_complete_control.js
+++ b/client/js/controls/pool_auto_complete_control.js
@@ -34,7 +34,7 @@ class PoolAutoCompleteControl extends AutoCompleteControl {
return new Promise((resolve, reject) => {
PoolList.search(
query, 0, this._options.maxResults,
- ['id', 'names', 'category', 'postCount'])
+ ['id', 'names', 'category', 'postCount', 'version'])
.then(
response => resolve(
_poolListToMatches(response.results, this._options)),
diff --git a/client/js/controls/pool_input_control.js b/client/js/controls/pool_input_control.js
index 09fcf63e..f53c8c96 100644
--- a/client/js/controls/pool_input_control.js
+++ b/client/js/controls/pool_input_control.js
@@ -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) {
if (source != SOURCE_INIT && this.pools.hasPoolId(pool.id)) {
return Promise.resolve();
@@ -178,10 +157,11 @@ class PoolInputControl extends events.EventTarget {
}
searchLinkNode.setAttribute(
'href', uri.formatClientLink(
- 'posts', {query: uri.escapeColons(pool.names[0])}));
+ 'posts', {query: "pool:" + pool.id}));
searchLinkNode.textContent = pool.names[0] + ' ';
searchLinkNode.addEventListener('click', e => {
- e.preventDefault();
+ // TODO?
+ // e.preventDefault();
});
const usagesNode = document.createElement('span');
diff --git a/client/js/models/abstract_list.js b/client/js/models/abstract_list.js
index 10edd612..fb4dec8b 100644
--- a/client/js/models/abstract_list.js
+++ b/client/js/models/abstract_list.js
@@ -86,6 +86,10 @@ class AbstractList extends events.EventTarget {
return this._list.map(...args);
}
+ filter(...args) {
+ return this._list.filter(...args);
+ }
+
[Symbol.iterator]() {
return this._list[Symbol.iterator]();
}
diff --git a/client/js/models/post.js b/client/js/models/post.js
index e547954e..e3388ece 100644
--- a/client/js/models/post.js
+++ b/client/js/models/post.js
@@ -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) {
const files = {};
const detail = {version: this._version};
@@ -131,13 +154,18 @@ class Post extends events.EventTarget {
if (this._source !== this._orig._source) {
detail.source = this._source;
}
- // TODO pools
let apiPromise = this._id ?
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) {
+ return this._savePoolPosts()
+ .then(() => Promise.resolve(response));
+ }
+ return Promise.resolve(response);
+ }).then(response => {
this._updateFromResponse(response);
this.dispatchEvent(
new CustomEvent('change', {detail: {post: this}}));
@@ -149,6 +177,7 @@ class Post extends events.EventTarget {
this.dispatchEvent(
new CustomEvent('changeThumbnail', {detail: {post: this}}));
}
+
return Promise.resolve();
}, error => {
if (error.response &&
diff --git a/client/js/models/post_list.js b/client/js/models/post_list.js
index 74f089f3..65d0de2a 100644
--- a/client/js/models/post_list.js
+++ b/client/js/models/post_list.js
@@ -49,6 +49,31 @@ class PostList extends AbstractList {
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;