From 9ce6c45690453027131f3d37df04ae0dbc43c503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 30 Jun 2015 15:41:39 +0200 Subject: [PATCH] add sessions for already uploaded files and implement manual deletion --- js/actions/coa_actions.js | 2 - .../react_s3_fine_uploader.js | 65 +++++++++++++++++-- js/constants/api_urls.js | 3 +- js/fetchers/s3_fetcher.js | 17 +++++ js/utils/fetch_api_utils.js | 35 ++++++++++ 5 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 js/fetchers/s3_fetcher.js diff --git a/js/actions/coa_actions.js b/js/actions/coa_actions.js index b475aeb7..ed8971d3 100644 --- a/js/actions/coa_actions.js +++ b/js/actions/coa_actions.js @@ -15,7 +15,6 @@ class CoaActions { CoaFetcher.fetchOne(id) .then((res) => { this.actions.updateCoa(res.coa); - console.log(res.coa); }) .catch((err) => { console.log(err); @@ -25,7 +24,6 @@ class CoaActions { CoaFetcher.create(edition.bitcoin_id) .then((res) => { this.actions.updateCoa(res.coa); - console.log(res.coa); }) .catch((err) => { console.log(err); diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index 534702b3..ec13c9f6 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -9,6 +9,7 @@ import fetch from 'isomorphic-fetch'; import AppConstants from '../../constants/application_constants'; import { getCookie } from '../../utils/fetch_api_utils'; +import S3Fetcher from '../../fetchers/s3_fetcher'; import fineUploader from 'fineUploader'; import FileDragAndDrop from './file_drag_and_drop'; @@ -184,7 +185,8 @@ var ReactS3FineUploader = React.createClass({ onRetry: this.onRetry, onAutoRetry: this.onAutoRetry, onManualRetry: this.onManualRetry, - onDeleteComplete: this.onDeleteComplete + onDeleteComplete: this.onDeleteComplete, + onSessionRequestComplete: this.onSessionRequestComplete } }; }, @@ -332,7 +334,7 @@ var ReactS3FineUploader = React.createClass({ }, onProgress(id, name, uploadedBytes, totalBytes) { - var newState = React.addons.update(this.state, { + let newState = React.addons.update(this.state, { filesToUpload: { [id]: { progress: { $set: (uploadedBytes / totalBytes) * 100} } } @@ -340,12 +342,61 @@ var ReactS3FineUploader = React.createClass({ this.setState(newState); }, + onSessionRequestComplete(response, success) { + if(success) { + // fetch blobs for images + response = response.map((file) => { + file.url = file.s3Url; + file.status = 'online'; + file.progress = 100; + return file; + }); + + // add file to filesToUpload + let updatedFilesToUpload = this.state.filesToUpload.concat(response); + + // refresh all files ids, + updatedFilesToUpload = updatedFilesToUpload.map((file, i) => { + file.id = i; + return file; + }); + + let newState = React.addons.update(this.state, {filesToUpload: {$set: updatedFilesToUpload}}); + this.setState(newState); + } else { + let notification = new GlobalNotificationModel('Could not load attached files (Further data)', 'success', 5000); + GlobalNotificationActions.appendGlobalNotification(notification); + + throw new Error('The session request failed', response); + } + }, + handleDeleteFile(fileId) { - // delete file from server - this.state.uploader.deleteFile(fileId); - // this is being continues in onDeleteFile, as - // fineuploaders deleteFile does not return a correct callback or - // promise + // In some instances (when the file was already uploaded and is just displayed to the user) + // fineuploader does not register an id on the file (we do, don't be confused by this!). + // Since you can only delete a file by its id, we have to implement this method ourselves + // + // So, if an id is not present, we delete the file manually + // To check which files are already uploaded from previous sessions we check their status. + // If they are, it is "online" + + if(this.state.filesToUpload[fileId].status !== 'online') { + // delete file from server + this.state.uploader.deleteFile(fileId); + // this is being continues in onDeleteFile, as + // fineuploaders deleteFile does not return a correct callback or + // promise + } else { + let fileToDelete = this.state.filesToUpload[fileId]; + S3Fetcher + .deleteFile(fileToDelete.s3Key, fileToDelete.s3Bucket) + .then((res) => { + console.log(res); + }) + .catch((err) => { + console.log(err); + }); + } }, handleCancelFile(fileId) { diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index 46626f2d..97da32e2 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -40,7 +40,8 @@ let apiUrls = { 'users_signup': AppConstants.apiEndpoint + 'users/', 'users_username': AppConstants.apiEndpoint + 'users/username/', 'wallet_settings': AppConstants.apiEndpoint + 'users/wallet_settings/', - 'whitelabel_settings': AppConstants.apiEndpoint + 'whitelabel/settings/${subdomain}/' + 'whitelabel_settings': AppConstants.apiEndpoint + 'whitelabel/settings/${subdomain}/', + 'delete_s3_file': AppConstants.serverUrl + 's3/delete/' }; export default apiUrls; diff --git a/js/fetchers/s3_fetcher.js b/js/fetchers/s3_fetcher.js new file mode 100644 index 00000000..e6f50b72 --- /dev/null +++ b/js/fetchers/s3_fetcher.js @@ -0,0 +1,17 @@ +'use strict'; + +import requests from '../utils/requests'; + +let S3Fetcher = { + /** + * Fetch the registered applications of a user from the API. + */ + deleteFile(key, bucket) { + return requests.delete('delete_s3_file', { + key, + bucket + }); + } +}; + +export default S3Fetcher; diff --git a/js/utils/fetch_api_utils.js b/js/utils/fetch_api_utils.js index 68f8fe6d..a4939770 100644 --- a/js/utils/fetch_api_utils.js +++ b/js/utils/fetch_api_utils.js @@ -69,4 +69,39 @@ export function getCookie(name) { if (parts.length === 2) { return parts.pop().split(';').shift(); } +} + +/* + + Given a url for an image, this method fetches it and returns a promise that resolves to + a blob object. + It can be used to create a 64base encoded data url. + + Taken from: http://jsfiddle.net/jan_miksovsky/yy7zs/ + + */ +export function fetchImageAsBlob(url) { + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + + xhr.open('GET', url, true); + + // Ask for the result as an ArrayBuffer. + xhr.responseType = 'arraybuffer'; + + xhr.onreadystatechange = function() { + if(xhr.readyState === 4 && xhr.status >= 400) { + reject(xhr.statusText); + } + }; + + xhr.onload = function() { + // Obtain a blob: URL for the image data. + let arrayBufferView = new Uint8Array(this.response); + let blob = new Blob([arrayBufferView], {type: 'image/jpeg'}); + resolve(blob); + }; + + xhr.send(); + }); } \ No newline at end of file