From 7648f479a9660794700a51dc9f9ca51264a1dd71 Mon Sep 17 00:00:00 2001 From: rr- Date: Thu, 29 Sep 2016 22:26:37 +0200 Subject: [PATCH] client/posts: add 'skip duplicates' to upload form Closes #102 --- client/css/post-upload.styl | 16 ++++--- client/html/post_upload.tpl | 15 +++++- .../js/controllers/post_upload_controller.js | 47 ++++++++++++------- client/js/views/post_upload_view.js | 24 +++++++--- 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/client/css/post-upload.styl b/client/css/post-upload.styl index 7bf9fbe..b9d18a5 100644 --- a/client/css/post-upload.styl +++ b/client/css/post-upload.styl @@ -9,9 +9,12 @@ $cancel-button-color = tomato margin: 0 auto text-align: left - &.inactive - input[type=submit] - display: none + &.inactive input[type=submit], + &.inactive .skip-duplicates + &.uploading input[type=submit], + &.uploading .skip-duplicates, + &:not(.uploading) .cancel + display: none .dropper-container margin: 0 auto @@ -21,18 +24,17 @@ $cancel-button-color = tomato input[type=submit] margin-top: 1em - &[disabled] - display: none .cancel margin-top: 1em background: $cancel-button-color border-color: $cancel-button-color - &[disabled] - display: none &:focus border: 2px solid $text-color + .skip-duplicates + margin-left: 1em + .messages margin-top: 1em diff --git a/client/html/post_upload.tpl b/client/html/post_upload.tpl index 1dcfba4..f1ed88f 100644 --- a/client/html/post_upload.tpl +++ b/client/html/post_upload.tpl @@ -2,8 +2,19 @@
- - +
+ + + + <%= ctx.makeCheckbox({ + text: 'Skip duplicates', + name: 'skip-duplicates', + checked: false, + }) %> + + + +
diff --git a/client/js/controllers/post_upload_controller.js b/client/js/controllers/post_upload_controller.js index 4defd5e..3ec86a9 100644 --- a/client/js/controllers/post_upload_controller.js +++ b/client/js/controllers/post_upload_controller.js @@ -48,25 +48,36 @@ class PostUploadController { this._view.clearMessages(); e.detail.uploadables.reduce((promise, uploadable) => { - return promise.then( - () => { - let post = new Post(); - post.safety = uploadable.safety; - if (uploadable.url) { - post.newContentUrl = uploadable.url; - } else { - post.newContent = uploadable.file; - } - let modelPromise = post.save(uploadable.anonymous); - this._lastPromise = modelPromise; - return modelPromise - .then(() => { - this._view.removeUploadable(uploadable); + return promise.then(() => { + let post = new Post(); + post.safety = uploadable.safety; + if (uploadable.url) { + post.newContentUrl = uploadable.url; + } else { + post.newContent = uploadable.file; + } + + let modelPromise = post.save(uploadable.anonymous); + this._lastPromise = modelPromise; + + return modelPromise + .then(() => { + this._view.removeUploadable(uploadable); + return Promise.resolve(); + }).catch(errorMessage => { + // XXX: + // lame, API eats error codes so we need to match + // messages instead + if (e.detail.skipDuplicates && + errorMessage.match(/already uploaded/)) { return Promise.resolve(); - }); - }); - }, Promise.resolve()).then( - () => { + } + return Promise.reject(errorMessage); + }); + }); + }, Promise.resolve()) + + .then(() => { misc.disableExitConfirmation(); const ctx = router.show('/posts'); ctx.controller.showSuccess('Posts uploaded.'); diff --git a/client/js/views/post_upload_view.js b/client/js/views/post_upload_view.js index 98b8021..fd60f4e 100644 --- a/client/js/views/post_upload_view.js +++ b/client/js/views/post_upload_view.js @@ -137,7 +137,6 @@ class PostUploadView extends events.EventTarget { views.replaceContent(this._hostNode, template()); views.syncScrollPosition(); - this._enabled = true; this._cancelButtonNode.disabled = true; this._uploadables = new Map(); @@ -162,13 +161,13 @@ class PostUploadView extends events.EventTarget { enableForm() { views.enableForm(this._formNode); this._cancelButtonNode.disabled = true; - this._enabled = true; + this._formNode.classList.remove('uploading'); } disableForm() { views.disableForm(this._formNode); this._cancelButtonNode.disabled = false; - this._enabled = false; + this._formNode.classList.add('uploading'); } clearMessages() { @@ -245,7 +244,7 @@ class PostUploadView extends events.EventTarget { _evtRemoveClick(e, uploadable) { e.preventDefault(); - if (!this._enabled) { + if (this._uploading) { return; } this.removeUploadable(uploadable); @@ -253,7 +252,7 @@ class PostUploadView extends events.EventTarget { _evtMoveUpClick(e, uploadable) { e.preventDefault(); - if (!this._enabled) { + if (this._uploading) { return; } let sortedUploadables = this._getSortedUploadables(); @@ -268,7 +267,7 @@ class PostUploadView extends events.EventTarget { _evtMoveDownClick(e, uploadable) { e.preventDefault(); - if (!this._enabled) { + if (this._uploading) { return; } let sortedUploadables = this._getSortedUploadables(); @@ -306,7 +305,10 @@ class PostUploadView extends events.EventTarget { this.dispatchEvent( new CustomEvent( eventType, - {detail: {uploadables: this._getSortedUploadables()}})); + {detail: { + uploadables: this._getSortedUploadables(), + skipDuplicates: this._skipDuplicatesCheckboxNode.checked, + }})); } _createRowNode(uploadable) { @@ -342,6 +344,10 @@ class PostUploadView extends events.EventTarget { rowNode.querySelector('.thumbnail').childNodes); } + get _uploading() { + return this._formNode.classList.contains('uploading'); + } + get _listNode() { return this._hostNode.querySelector('.uploadables-container'); } @@ -350,6 +356,10 @@ class PostUploadView extends events.EventTarget { return this._hostNode.querySelector('form'); } + get _skipDuplicatesCheckboxNode() { + return this._hostNode.querySelector('form [name=skip-duplicates]'); + } + get _submitButtonNode() { return this._hostNode.querySelector('form [type=submit]'); }