client/upload: add QoL features for bulk uploads
* Continue uploading remaining posts in an upload list even when one fails * Allow option to continue uploading even when similar posts are found Closes #400
This commit is contained in:
commit
be0c867d25
4 changed files with 62 additions and 30 deletions
|
@ -13,8 +13,10 @@ $cancel-button-color = tomato
|
||||||
|
|
||||||
&.inactive input[type=submit],
|
&.inactive input[type=submit],
|
||||||
&.inactive .skip-duplicates
|
&.inactive .skip-duplicates
|
||||||
|
&.inactive .always-upload-similar
|
||||||
&.uploading input[type=submit],
|
&.uploading input[type=submit],
|
||||||
&.uploading .skip-duplicates,
|
&.uploading .skip-duplicates,
|
||||||
|
&.uploading .always-upload-similar
|
||||||
&:not(.uploading) .cancel
|
&:not(.uploading) .cancel
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
|
@ -39,6 +41,9 @@ $cancel-button-color = tomato
|
||||||
.skip-duplicates
|
.skip-duplicates
|
||||||
margin-left: 1em
|
margin-left: 1em
|
||||||
|
|
||||||
|
.always-upload-similar
|
||||||
|
margin-left: 1em
|
||||||
|
|
||||||
form>.messages
|
form>.messages
|
||||||
margin-top: 1em
|
margin-top: 1em
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,14 @@
|
||||||
}) %>
|
}) %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<span class='always-upload-similar'>
|
||||||
|
<%= ctx.makeCheckbox({
|
||||||
|
text: 'Always upload similar',
|
||||||
|
name: 'always-upload-similar',
|
||||||
|
checked: false,
|
||||||
|
}) %>
|
||||||
|
</span>
|
||||||
|
|
||||||
<input type='button' value='Cancel' class='cancel'/>
|
<input type='button' value='Cancel' class='cancel'/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ const PostUploadView = require("../views/post_upload_view.js");
|
||||||
const EmptyView = require("../views/empty_view.js");
|
const EmptyView = require("../views/empty_view.js");
|
||||||
|
|
||||||
const genericErrorMessage =
|
const genericErrorMessage =
|
||||||
"One of the posts needs your attention; " +
|
"One or more posts needs your attention; " +
|
||||||
'click "resume upload" when you\'re ready.';
|
'click "resume upload" when you\'re ready.';
|
||||||
|
|
||||||
class PostUploadController {
|
class PostUploadController {
|
||||||
|
@ -55,6 +55,7 @@ class PostUploadController {
|
||||||
_evtSubmit(e) {
|
_evtSubmit(e) {
|
||||||
this._view.disableForm();
|
this._view.disableForm();
|
||||||
this._view.clearMessages();
|
this._view.clearMessages();
|
||||||
|
let anyFailures = false;
|
||||||
|
|
||||||
e.detail.uploadables
|
e.detail.uploadables
|
||||||
.reduce(
|
.reduce(
|
||||||
|
@ -62,44 +63,51 @@ class PostUploadController {
|
||||||
promise.then(() =>
|
promise.then(() =>
|
||||||
this._uploadSinglePost(
|
this._uploadSinglePost(
|
||||||
uploadable,
|
uploadable,
|
||||||
e.detail.skipDuplicates
|
e.detail.skipDuplicates,
|
||||||
)
|
e.detail.alwaysUploadSimilar
|
||||||
|
).catch((error) => {
|
||||||
|
anyFailures = true;
|
||||||
|
if (error.uploadable) {
|
||||||
|
if (error.similarPosts) {
|
||||||
|
error.uploadable.lookalikes =
|
||||||
|
error.similarPosts;
|
||||||
|
this._view.updateUploadable(
|
||||||
|
error.uploadable
|
||||||
|
);
|
||||||
|
this._view.showInfo(
|
||||||
|
error.message,
|
||||||
|
error.uploadable
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this._view.showError(
|
||||||
|
error.message,
|
||||||
|
error.uploadable
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._view.showError(
|
||||||
|
error.message,
|
||||||
|
uploadable
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
),
|
),
|
||||||
Promise.resolve()
|
Promise.resolve()
|
||||||
)
|
)
|
||||||
.then(
|
.then(() => {
|
||||||
() => {
|
if (anyFailures) {
|
||||||
|
this._view.showError(genericErrorMessage);
|
||||||
|
this._view.enableForm();
|
||||||
|
} else {
|
||||||
this._view.clearMessages();
|
this._view.clearMessages();
|
||||||
misc.disableExitConfirmation();
|
misc.disableExitConfirmation();
|
||||||
const ctx = router.show(uri.formatClientLink("posts"));
|
const ctx = router.show(uri.formatClientLink("posts"));
|
||||||
ctx.controller.showSuccess("Posts uploaded.");
|
ctx.controller.showSuccess("Posts uploaded.");
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
if (error.uploadable) {
|
|
||||||
if (error.similarPosts) {
|
|
||||||
error.uploadable.lookalikes = error.similarPosts;
|
|
||||||
this._view.updateUploadable(error.uploadable);
|
|
||||||
this._view.showInfo(genericErrorMessage);
|
|
||||||
this._view.showInfo(
|
|
||||||
error.message,
|
|
||||||
error.uploadable
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this._view.showError(genericErrorMessage);
|
|
||||||
this._view.showError(
|
|
||||||
error.message,
|
|
||||||
error.uploadable
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._view.showError(error.message);
|
|
||||||
}
|
|
||||||
this._view.enableForm();
|
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_uploadSinglePost(uploadable, skipDuplicates) {
|
_uploadSinglePost(uploadable, skipDuplicates, alwaysUploadSimilar) {
|
||||||
progress.start();
|
progress.start();
|
||||||
let reverseSearchPromise = Promise.resolve();
|
let reverseSearchPromise = Promise.resolve();
|
||||||
if (!uploadable.lookalikesConfirmed) {
|
if (!uploadable.lookalikesConfirmed) {
|
||||||
|
@ -128,7 +136,10 @@ class PostUploadController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify about similar posts
|
// notify about similar posts
|
||||||
if (searchResult.similarPosts.length) {
|
if (
|
||||||
|
searchResult.similarPosts.length &&
|
||||||
|
!alwaysUploadSimilar
|
||||||
|
) {
|
||||||
let error = new Error(
|
let error = new Error(
|
||||||
`Found ${searchResult.similarPosts.length} similar ` +
|
`Found ${searchResult.similarPosts.length} similar ` +
|
||||||
"posts.\nYou can resume or discard this upload."
|
"posts.\nYou can resume or discard this upload."
|
||||||
|
|
|
@ -358,6 +358,8 @@ class PostUploadView extends events.EventTarget {
|
||||||
detail: {
|
detail: {
|
||||||
uploadables: this._uploadables,
|
uploadables: this._uploadables,
|
||||||
skipDuplicates: this._skipDuplicatesCheckboxNode.checked,
|
skipDuplicates: this._skipDuplicatesCheckboxNode.checked,
|
||||||
|
alwaysUploadSimilar: this._alwaysUploadSimilarCheckboxNode
|
||||||
|
.checked,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -421,6 +423,12 @@ class PostUploadView extends events.EventTarget {
|
||||||
return this._hostNode.querySelector("form [name=skip-duplicates]");
|
return this._hostNode.querySelector("form [name=skip-duplicates]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _alwaysUploadSimilarCheckboxNode() {
|
||||||
|
return this._hostNode.querySelector(
|
||||||
|
"form [name=always-upload-similar]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
get _submitButtonNode() {
|
get _submitButtonNode() {
|
||||||
return this._hostNode.querySelector("form [type=submit]");
|
return this._hostNode.querySelector("form [type=submit]");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue