UNPKG

zotero-web-library

Version:

Web library from zotero.org

309 lines (292 loc) 9.53 kB
'use strict'; var log = require('libzotero/lib/Log').Logger('zotero-web-library:uploadDialog'); var React = require('react'); var LoadingSpinner = require('./LoadingSpinner.js'); var BootstrapModalWrapper = require('./BootstrapModalWrapper.js'); var UploadAttachmentDialog = React.createClass({ displayName: 'UploadAttachmentDialog', componentWillMount: function componentWillMount() { var reactInstance = this; var library = this.props.library; library.listen('uploadAttachment', function () { log.debug('got uploadAttachment event; opening upload dialog'); reactInstance.setState({ itemKey: Zotero.state.getUrlVar('itemKey') }); reactInstance.openDialog(); }, {}); }, getInitialState: function getInitialState() { return { title: '', fileInfo: null, filename: '', filesize: 0, contentType: null, percentLoaded: 0, uploading: false }; }, upload: function upload() { log.debug('uploadFunction', 3); var reactInstance = this; var library = this.props.library; //callback for when everything in the upload form is filled //grab file blob //grab file data given by user //create or modify attachment item //Item.uploadExistingFile or uploadChildAttachment var fileInfo = this.state.fileInfo; var specifiedTitle = this.state.title; var progressCallback = function progressCallback(e) { log.debug('fullUpload.upload.onprogress', 3); var percentLoaded = Math.round(e.loaded / e.total * 100); reactInstance.setState({ percentLoaded: percentLoaded }); }; this.setState({ uploading: true }); //upload new copy of file if we're modifying an attachment //create child and upload file if we're modifying a top level item var itemKey = Zotero.state.getUrlVar('itemKey'); var item = library.items.getItem(itemKey); var uploadPromise; if (!item.get('parentItem')) { log.debug('no parentItem', 3); //get template item var childItem = new Zotero.Item(); childItem.associateWithLibrary(library); uploadPromise = childItem.initEmpty('attachment', 'imported_file').then(function (childItem) { log.debug('templateItemDeferred callback', 3); childItem.set('title', specifiedTitle); return item.uploadChildAttachment(childItem, fileInfo, progressCallback); }); } else if (item.get('itemType') == 'attachment' && item.get('linkMode') == 'imported_file') { log.debug('imported_file attachment', 3); uploadPromise = item.uploadFile(fileInfo, progressCallback); } uploadPromise.then(function () { log.debug('uploadSuccess', 3); library.trigger('uploadSuccessful'); reactInstance.closeDialog(); }).catch(reactInstance.failureHandler).then(function () { reactInstance.closeDialog(); }); }, handleUploadFailure: function handleUploadFailure(failure) { log.debug('Upload failed', 3); log.debug(failure, 3); Zotero.ui.jsNotificationMessage('There was a problem uploading your file.', 'error'); switch (failure.code) { case 400: Zotero.ui.jsNotificationMessage('Bad Input. 400', 'error'); break; case 403: Zotero.ui.jsNotificationMessage('You do not have permission to edit files', 'error'); break; case 409: Zotero.ui.jsNotificationMessage('The library is currently locked. Please try again in a few minutes.', 'error'); break; case 412: Zotero.ui.jsNotificationMessage('File conflict. Remote file has changed', 'error'); break; case 413: Zotero.ui.jsNotificationMessage('Requested upload would exceed storage quota.', 'error'); break; case 428: Zotero.ui.jsNotificationMessage('Precondition required error', 'error'); break; case 429: Zotero.ui.jsNotificationMessage('Too many uploads pending. Please try again in a few minutes', 'error'); break; default: Zotero.ui.jsNotificationMessage('Unknown error uploading file. ' + failure.code, 'error'); } }, handleFiles: function handleFiles(files) { log.debug('attachmentUpload handleFiles', 3); var reactInstance = this; if (typeof files == 'undefined' || files.length === 0) { return false; } var file = files[0]; Zotero.file.getFileInfo(file).then(function (fileInfo) { log.debug(fileInfo); reactInstance.setState({ fileInfo: fileInfo, filename: fileInfo.filename, filesize: fileInfo.filesize, contentType: fileInfo.contentType }); }); return; }, handleDrop: function handleDrop(evt) { log.debug('fileuploaddroptarget drop callback', 3); evt.stopPropagation(); evt.preventDefault(); //clear file input so drag/drop and input don't show conflicting information var e = evt.originalEvent; var dt = e.dataTransfer; var files = dt.files; this.handleFiles(files); }, handleFileInputChange: function handleFileInputChange(evt) { log.debug('fileuploaddroptarget callback 1', 3); evt.stopPropagation(); evt.preventDefault(); var files = this.refs.fileInput.files; this.handleFiles(files); }, handleTitleChange: function handleTitleChange(evt) { this.setState({ title: evt.target.value }); }, openDialog: function openDialog() { this.refs.modal.open(); }, closeDialog: function closeDialog(evt) { this.refs.modal.close(); }, render: function render() { var library = this.props.library; return React.createElement( BootstrapModalWrapper, { ref: 'modal' }, React.createElement( 'div', { id: 'upload-attachment-dialog', className: 'upload-attachment-dialog', role: 'dialog', title: 'Upload Attachment', 'data-keyboard': 'true' }, React.createElement( 'div', { className: 'modal-dialog' }, React.createElement( 'div', { className: 'modal-content' }, React.createElement( 'div', { className: 'modal-header' }, React.createElement( 'button', { type: 'button', className: 'close', 'data-dismiss': 'modal', 'aria-hidden': 'true' }, '×' ), React.createElement( 'h3', { className: 'modal-title' }, 'Upload Attachment' ) ), React.createElement( 'div', { className: 'upload-attachment-div modal-body', 'data-role': 'content' }, React.createElement( 'form', { className: 'attachmentuploadForm zform' }, React.createElement( 'h3', null, 'Select a file for upload or drag and drop below' ), React.createElement( 'span', { className: 'btn btn-primary btn-file' }, 'Choose File', React.createElement('input', { onChange: this.handleFileInputChange, ref: 'fileInput', type: 'file', id: 'fileuploadinput', className: 'fileuploadinput', multiple: true }) ), React.createElement( 'div', { onDrop: this.handleDrop, id: 'fileuploaddroptarget', className: 'fileuploaddroptarget' }, React.createElement( 'h3', null, 'Drop your file here' ), React.createElement('h3', { id: 'droppedfilename', className: 'droppedfilename' }), React.createElement(LoadingSpinner, { loading: this.state.uploading }) ), React.createElement( 'div', { id: 'attachmentuploadfileinfo', className: 'attachmentuploadfileinfo' }, React.createElement( 'table', { className: 'table table-striped' }, React.createElement( 'tbody', null, React.createElement( 'tr', null, React.createElement( 'th', null, 'Title' ), React.createElement( 'td', null, React.createElement('input', { onChange: this.handleTitleChange, id: 'upload-file-title-input', className: 'upload-file-title-input form-control', type: 'text' }) ) ), React.createElement( 'tr', null, React.createElement( 'th', null, 'Size' ), React.createElement( 'td', { className: 'uploadfilesize' }, this.state.filesize ) ), React.createElement( 'tr', null, React.createElement( 'th', null, 'Type' ), React.createElement( 'td', { className: 'uploadfiletype' }, this.state.contentType ) ), React.createElement( 'tr', null, React.createElement( 'th', null, 'Upload' ), React.createElement( 'td', { className: 'uploadprogress' }, React.createElement('meter', { min: '0', max: '100', id: 'uploadprogressmeter', value: this.state.percentLoaded }) ) ) ) ) ) ) ), React.createElement( 'div', { className: 'modal-footer' }, React.createElement( 'button', { type: 'button', className: 'btn btn-default', 'data-dismiss': 'modal', 'aria-hidden': 'true' }, 'Close' ), React.createElement( 'button', { onClick: this.upload, type: 'button', className: 'btn btn-primary uploadButton' }, 'Upload' ) ) ) ) ) ); } }); module.exports = UploadAttachmentDialog;