mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
Remove ReactS3FineUploader's dependency on react-router's location
ReactS3FineUploader used to check the current url’s query params to determine which method it should use to upload, but this decision means the component is tightly coupled with react-router and history.js. A major pain point is having to propagate the location prop all the way down to this component even when it’s not necessary. Now, ReactS3FineUploader’s parent elements can either parse the current query params themselves or, if they have a location from react-router, simply use the location. Added a few utils to help parse url params.
This commit is contained in:
parent
e145e50228
commit
d23331d9b9
@ -20,8 +20,7 @@ let FurtherDetailsFileuploader = React.createClass({
|
|||||||
submitFile: React.PropTypes.func,
|
submitFile: React.PropTypes.func,
|
||||||
isReadyForFormSubmission: React.PropTypes.func,
|
isReadyForFormSubmission: React.PropTypes.func,
|
||||||
editable: React.PropTypes.bool,
|
editable: React.PropTypes.bool,
|
||||||
multiple: React.PropTypes.bool,
|
multiple: React.PropTypes.bool
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -89,11 +88,10 @@ let FurtherDetailsFileuploader = React.createClass({
|
|||||||
}}
|
}}
|
||||||
areAssetsDownloadable={true}
|
areAssetsDownloadable={true}
|
||||||
areAssetsEditable={this.props.editable}
|
areAssetsEditable={this.props.editable}
|
||||||
multiple={this.props.multiple}
|
multiple={this.props.multiple} />
|
||||||
location={this.props.location}/>
|
|
||||||
</Property>
|
</Property>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default FurtherDetailsFileuploader;
|
export default FurtherDetailsFileuploader;
|
||||||
|
@ -28,8 +28,7 @@ let CreateContractForm = React.createClass({
|
|||||||
fileClassToUpload: React.PropTypes.shape({
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
singular: React.PropTypes.string,
|
singular: React.PropTypes.string,
|
||||||
plural: React.PropTypes.string
|
plural: React.PropTypes.string
|
||||||
}),
|
})
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
@ -87,8 +86,7 @@ let CreateContractForm = React.createClass({
|
|||||||
areAssetsEditable={true}
|
areAssetsEditable={true}
|
||||||
setIsUploadReady={this.setIsUploadReady}
|
setIsUploadReady={this.setIsUploadReady}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
fileClassToUpload={this.props.fileClassToUpload}
|
fileClassToUpload={this.props.fileClassToUpload} />
|
||||||
location={this.props.location}/>
|
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='name'
|
name='name'
|
||||||
@ -110,4 +108,4 @@ let CreateContractForm = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default CreateContractForm;
|
export default CreateContractForm;
|
||||||
|
@ -26,12 +26,15 @@ let RegisterPieceForm = React.createClass({
|
|||||||
isFineUploaderActive: React.PropTypes.bool,
|
isFineUploaderActive: React.PropTypes.bool,
|
||||||
isFineUploaderEditable: React.PropTypes.bool,
|
isFineUploaderEditable: React.PropTypes.bool,
|
||||||
enableLocalHashing: React.PropTypes.bool,
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
children: React.PropTypes.element,
|
|
||||||
onLoggedOut: React.PropTypes.func,
|
onLoggedOut: React.PropTypes.func,
|
||||||
|
|
||||||
// For this form to work with SlideContainer, we sometimes have to disable it
|
// For this form to work with SlideContainer, we sometimes have to disable it
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
location: React.PropTypes.object
|
location: React.PropTypes.object,
|
||||||
|
children: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
|
React.PropTypes.element
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -116,7 +119,7 @@ let RegisterPieceForm = React.createClass({
|
|||||||
onLoggedOut={this.props.onLoggedOut}
|
onLoggedOut={this.props.onLoggedOut}
|
||||||
disabled={!this.props.isFineUploaderEditable}
|
disabled={!this.props.isFineUploaderEditable}
|
||||||
enableLocalHashing={enableLocalHashing}
|
enableLocalHashing={enableLocalHashing}
|
||||||
location={this.props.location}/>
|
uploadMethod={this.props.location.query.method} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='artist_name'
|
name='artist_name'
|
||||||
|
@ -37,6 +37,7 @@ let InputFineUploader = React.createClass({
|
|||||||
onLoggedOut: React.PropTypes.func,
|
onLoggedOut: React.PropTypes.func,
|
||||||
|
|
||||||
enableLocalHashing: React.PropTypes.bool,
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
|
uploadMethod: React.PropTypes.string,
|
||||||
|
|
||||||
// provided by Property
|
// provided by Property
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
@ -46,8 +47,7 @@ let InputFineUploader = React.createClass({
|
|||||||
fileClassToUpload: React.PropTypes.shape({
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
singular: React.PropTypes.string,
|
singular: React.PropTypes.string,
|
||||||
plural: React.PropTypes.string
|
plural: React.PropTypes.string
|
||||||
}),
|
})
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
@ -107,10 +107,10 @@ let InputFineUploader = React.createClass({
|
|||||||
}}
|
}}
|
||||||
onInactive={this.props.onLoggedOut}
|
onInactive={this.props.onLoggedOut}
|
||||||
enableLocalHashing={this.props.enableLocalHashing}
|
enableLocalHashing={this.props.enableLocalHashing}
|
||||||
fileClassToUpload={this.props.fileClassToUpload}
|
uploadMethod={this.props.uploadMethod}
|
||||||
location={this.props.location}/>
|
fileClassToUpload={this.props.fileClassToUpload} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default InputFineUploader;
|
export default InputFineUploader;
|
||||||
|
@ -20,8 +20,7 @@ import { getLangText } from '../../utils/lang_utils';
|
|||||||
|
|
||||||
let ContractSettingsUpdateButton = React.createClass({
|
let ContractSettingsUpdateButton = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
contract: React.PropTypes.object,
|
contract: React.PropTypes.object
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
submitFile(file) {
|
submitFile(file) {
|
||||||
@ -90,10 +89,9 @@ let ContractSettingsUpdateButton = React.createClass({
|
|||||||
plural: getLangText('UPDATE')
|
plural: getLangText('UPDATE')
|
||||||
}}
|
}}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
submitFile={this.submitFile}
|
submitFile={this.submitFile} />
|
||||||
location={this.props.location}/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ContractSettingsUpdateButton;
|
export default ContractSettingsUpdateButton;
|
||||||
|
@ -27,6 +27,7 @@ let FileDragAndDrop = React.createClass({
|
|||||||
areAssetsEditable: React.PropTypes.bool,
|
areAssetsEditable: React.PropTypes.bool,
|
||||||
|
|
||||||
enableLocalHashing: React.PropTypes.bool,
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
|
uploadMethod: React.PropTypes.string,
|
||||||
|
|
||||||
// triggers a FileDragAndDrop-global spinner
|
// triggers a FileDragAndDrop-global spinner
|
||||||
hashingProgress: React.PropTypes.number,
|
hashingProgress: React.PropTypes.number,
|
||||||
@ -41,8 +42,7 @@ let FileDragAndDrop = React.createClass({
|
|||||||
plural: React.PropTypes.string
|
plural: React.PropTypes.string
|
||||||
}),
|
}),
|
||||||
|
|
||||||
allowedExtensions: React.PropTypes.string,
|
allowedExtensions: React.PropTypes.string
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDragOver(event) {
|
handleDragOver(event) {
|
||||||
@ -137,19 +137,19 @@ let FileDragAndDrop = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
let { filesToUpload,
|
const {
|
||||||
dropzoneInactive,
|
filesToUpload,
|
||||||
className,
|
dropzoneInactive,
|
||||||
hashingProgress,
|
className,
|
||||||
handleCancelHashing,
|
hashingProgress,
|
||||||
multiple,
|
handleCancelHashing,
|
||||||
enableLocalHashing,
|
multiple,
|
||||||
fileClassToUpload,
|
enableLocalHashing,
|
||||||
areAssetsDownloadable,
|
uploadMethod,
|
||||||
areAssetsEditable,
|
fileClassToUpload,
|
||||||
allowedExtensions,
|
areAssetsDownloadable,
|
||||||
location
|
areAssetsEditable,
|
||||||
} = this.props;
|
allowedExtensions } = this.props;
|
||||||
|
|
||||||
// has files only is true if there are files that do not have the status deleted or canceled
|
// has files only is true if there are files that do not have the status deleted or canceled
|
||||||
let hasFiles = filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0;
|
let hasFiles = filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0;
|
||||||
@ -185,8 +185,8 @@ let FileDragAndDrop = React.createClass({
|
|||||||
hasFiles={hasFiles}
|
hasFiles={hasFiles}
|
||||||
onClick={this.handleOnClick}
|
onClick={this.handleOnClick}
|
||||||
enableLocalHashing={enableLocalHashing}
|
enableLocalHashing={enableLocalHashing}
|
||||||
fileClassToUpload={fileClassToUpload}
|
uploadMethod={uploadMethod}
|
||||||
location={location}/>
|
fileClassToUpload={fileClassToUpload} />
|
||||||
<FileDragAndDropPreviewIterator
|
<FileDragAndDropPreviewIterator
|
||||||
files={filesToUpload}
|
files={filesToUpload}
|
||||||
handleDeleteFile={this.handleDeleteFile}
|
handleDeleteFile={this.handleDeleteFile}
|
||||||
|
@ -3,30 +3,28 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
|
|
||||||
import { getLangText } from '../../../utils/lang_utils';
|
|
||||||
import { dragAndDropAvailable } from '../../../utils/feature_detection_utils';
|
import { dragAndDropAvailable } from '../../../utils/feature_detection_utils';
|
||||||
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
import { getCurrentQueryParams } from '../../../utils/url_utils';
|
||||||
|
|
||||||
let FileDragAndDropDialog = React.createClass({
|
let FileDragAndDropDialog = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
hasFiles: React.PropTypes.bool,
|
hasFiles: React.PropTypes.bool,
|
||||||
multipleFiles: React.PropTypes.bool,
|
multipleFiles: React.PropTypes.bool,
|
||||||
onClick: React.PropTypes.func,
|
|
||||||
enableLocalHashing: React.PropTypes.bool,
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
|
uploadMethod: React.PropTypes.string,
|
||||||
|
onClick: React.PropTypes.func,
|
||||||
|
|
||||||
// A class of a file the user has to upload
|
// A class of a file the user has to upload
|
||||||
// Needs to be defined both in singular as well as in plural
|
// Needs to be defined both in singular as well as in plural
|
||||||
fileClassToUpload: React.PropTypes.shape({
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
singular: React.PropTypes.string,
|
singular: React.PropTypes.string,
|
||||||
plural: React.PropTypes.string
|
plural: React.PropTypes.string
|
||||||
}),
|
})
|
||||||
|
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDragDialog(fileClass) {
|
getDragDialog(fileClass) {
|
||||||
if(dragAndDropAvailable) {
|
if (dragAndDropAvailable) {
|
||||||
return [
|
return [
|
||||||
<p>{getLangText('Drag %s here', fileClass)}</p>,
|
<p>{getLangText('Drag %s here', fileClass)}</p>,
|
||||||
<p>{getLangText('or')}</p>
|
<p>{getLangText('or')}</p>
|
||||||
@ -37,26 +35,31 @@ let FileDragAndDropDialog = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const queryParams = this.props.location.query;
|
const {
|
||||||
|
hasFiles,
|
||||||
|
multipleFiles,
|
||||||
|
enableLocalHashing,
|
||||||
|
uploadMethod,
|
||||||
|
fileClassToUpload,
|
||||||
|
onClick } = this.props;
|
||||||
|
|
||||||
if(this.props.hasFiles) {
|
if (hasFiles) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
if(this.props.enableLocalHashing && !queryParams.method) {
|
if (enableLocalHashing && !uploadMethod) {
|
||||||
|
const currentQueryParams = getCurrentQueryParams();
|
||||||
|
|
||||||
let queryParamsHash = Object.assign({}, queryParams);
|
const queryParamsHash = Object.assign({}, currentQueryParams);
|
||||||
queryParamsHash.method = 'hash';
|
queryParamsHash.method = 'hash';
|
||||||
|
|
||||||
let queryParamsUpload = Object.assign({}, queryParams);
|
const queryParamsUpload = Object.assign({}, currentQueryParams);
|
||||||
queryParamsUpload.method = 'upload';
|
queryParamsUpload.method = 'upload';
|
||||||
|
|
||||||
let { location } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="file-drag-and-drop-dialog present-options">
|
<div className="file-drag-and-drop-dialog present-options">
|
||||||
<p>{getLangText('Would you rather')}</p>
|
<p>{getLangText('Would you rather')}</p>
|
||||||
<Link
|
<Link
|
||||||
to={location.pathname}
|
to={window.location.pathname}
|
||||||
query={queryParamsHash}>
|
query={queryParamsHash}>
|
||||||
<span className="btn btn-default btn-sm">
|
<span className="btn btn-default btn-sm">
|
||||||
{getLangText('Hash your work')}
|
{getLangText('Hash your work')}
|
||||||
@ -64,9 +67,9 @@ let FileDragAndDropDialog = React.createClass({
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<span> or </span>
|
<span> or </span>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
to={location.pathname}
|
to={window.location.pathname}
|
||||||
query={queryParamsUpload}>
|
query={queryParamsUpload}>
|
||||||
<span className="btn btn-default btn-sm">
|
<span className="btn btn-default btn-sm">
|
||||||
{getLangText('Upload and hash your work')}
|
{getLangText('Upload and hash your work')}
|
||||||
@ -75,26 +78,27 @@ let FileDragAndDropDialog = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if(this.props.multipleFiles) {
|
if (multipleFiles) {
|
||||||
return (
|
return (
|
||||||
<span className="file-drag-and-drop-dialog">
|
<span className="file-drag-and-drop-dialog">
|
||||||
{this.getDragDialog(this.props.fileClassToUpload.plural)}
|
{this.getDragDialog(fileClassToUpload.plural)}
|
||||||
<span
|
<span
|
||||||
className="btn btn-default"
|
className="btn btn-default"
|
||||||
onClick={this.props.onClick}>
|
onClick={onClick}>
|
||||||
{getLangText('choose %s to upload', this.props.fileClassToUpload.plural)}
|
{getLangText('choose %s to upload', fileClassToUpload.plural)}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let dialog = queryParams.method === 'hash' ? getLangText('choose a %s to hash', this.props.fileClassToUpload.singular) : getLangText('choose a %s to upload', this.props.fileClassToUpload.singular);
|
const dialog = uploadMethod === 'hash' ? getLangText('choose a %s to hash', fileClassToUpload.singular)
|
||||||
|
: getLangText('choose a %s to upload', fileClassToUpload.singular);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="file-drag-and-drop-dialog">
|
<span className="file-drag-and-drop-dialog">
|
||||||
{this.getDragDialog(this.props.fileClassToUpload.singular)}
|
{this.getDragDialog(fileClassToUpload.singular)}
|
||||||
<span
|
<span
|
||||||
className="btn btn-default"
|
className="btn btn-default"
|
||||||
onClick={this.props.onClick}>
|
onClick={onClick}>
|
||||||
{dialog}
|
{dialog}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@ -105,4 +109,4 @@ let FileDragAndDropDialog = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default FileDragAndDropDialog;
|
export default FileDragAndDropDialog;
|
||||||
|
@ -18,7 +18,6 @@ import { displayValidFilesFilter, transformAllowedExtensionsToInputAcceptProp }
|
|||||||
import { getCookie } from '../../utils/fetch_api_utils';
|
import { getCookie } from '../../utils/fetch_api_utils';
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
let ReactS3FineUploader = React.createClass({
|
let ReactS3FineUploader = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
keyRoutine: React.PropTypes.shape({
|
keyRoutine: React.PropTypes.shape({
|
||||||
@ -107,11 +106,14 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
// One solution we found in the process of tackling this problem was to hash
|
// One solution we found in the process of tackling this problem was to hash
|
||||||
// the file in the browser using md5 and then uploading the resulting text document instead
|
// the file in the browser using md5 and then uploading the resulting text document instead
|
||||||
// of the actual file.
|
// of the actual file.
|
||||||
// This boolean essentially enables that behavior
|
//
|
||||||
|
// This boolean and string essentially enable that behavior.
|
||||||
|
// Right now, we determine which upload method to use by appending a query parameter,
|
||||||
|
// which should be passed into 'uploadMethod':
|
||||||
|
// 'hash': upload using the hash
|
||||||
|
// 'upload': upload full file (default if not specified)
|
||||||
enableLocalHashing: React.PropTypes.bool,
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
|
uploadMethod: React.PropTypes.string,
|
||||||
// automatically injected by React-Router
|
|
||||||
query: React.PropTypes.object,
|
|
||||||
|
|
||||||
// A class of a file the user has to upload
|
// A class of a file the user has to upload
|
||||||
// Needs to be defined both in singular as well as in plural
|
// Needs to be defined both in singular as well as in plural
|
||||||
@ -126,9 +128,7 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
fileInputElement: React.PropTypes.oneOfType([
|
fileInputElement: React.PropTypes.oneOfType([
|
||||||
React.PropTypes.func,
|
React.PropTypes.func,
|
||||||
React.PropTypes.element
|
React.PropTypes.element
|
||||||
]),
|
])
|
||||||
|
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -192,11 +192,11 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
filesToUpload: [],
|
filesToUpload: [],
|
||||||
uploader: new fineUploader.s3.FineUploaderBasic(this.propsToConfig()),
|
uploader: new fineUploader.s3.FineUploaderBasic(this.propsToConfig()),
|
||||||
csrfToken: getCookie(AppConstants.csrftoken),
|
csrfToken: getCookie(AppConstants.csrftoken),
|
||||||
|
|
||||||
// -1: aborted
|
// -1: aborted
|
||||||
// -2: uninitialized
|
// -2: uninitialized
|
||||||
hashingProgress: -2,
|
hashingProgress: -2,
|
||||||
|
|
||||||
// this is for logging
|
// this is for logging
|
||||||
chunks: {}
|
chunks: {}
|
||||||
};
|
};
|
||||||
@ -354,7 +354,6 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
/* FineUploader specific callback function handlers */
|
/* FineUploader specific callback function handlers */
|
||||||
|
|
||||||
onUploadChunk(id, name, chunkData) {
|
onUploadChunk(id, name, chunkData) {
|
||||||
|
|
||||||
let chunks = this.state.chunks;
|
let chunks = this.state.chunks;
|
||||||
|
|
||||||
chunks[id + '-' + chunkData.startByte + '-' + chunkData.endByte] = {
|
chunks[id + '-' + chunkData.startByte + '-' + chunkData.endByte] = {
|
||||||
@ -370,10 +369,9 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onUploadChunkSuccess(id, chunkData, responseJson, xhr) {
|
onUploadChunkSuccess(id, chunkData, responseJson, xhr) {
|
||||||
|
|
||||||
let chunks = this.state.chunks;
|
let chunks = this.state.chunks;
|
||||||
let chunkKey = id + '-' + chunkData.startByte + '-' + chunkData.endByte;
|
let chunkKey = id + '-' + chunkData.startByte + '-' + chunkData.endByte;
|
||||||
|
|
||||||
if(chunks[chunkKey]) {
|
if(chunks[chunkKey]) {
|
||||||
chunks[chunkKey].completed = true;
|
chunks[chunkKey].completed = true;
|
||||||
chunks[chunkKey].responseJson = responseJson;
|
chunks[chunkKey].responseJson = responseJson;
|
||||||
@ -414,7 +412,7 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
} else {
|
} else {
|
||||||
console.warn('You didn\'t define submitFile in as a prop in react-s3-fine-uploader');
|
console.warn('You didn\'t define submitFile in as a prop in react-s3-fine-uploader');
|
||||||
}
|
}
|
||||||
|
|
||||||
// for explanation, check comment of if statement above
|
// for explanation, check comment of if statement above
|
||||||
if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
|
if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
|
||||||
// also, lets check if after the completion of this upload,
|
// also, lets check if after the completion of this upload,
|
||||||
@ -597,7 +595,6 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
} else {
|
} else {
|
||||||
throw new Error(getLangText('File upload could not be paused.'));
|
throw new Error(getLangText('File upload could not be paused.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleResumeFile(fileId) {
|
handleResumeFile(fileId) {
|
||||||
@ -647,16 +644,14 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
// md5 hash of a file locally and just upload a txt file containing that hash.
|
// md5 hash of a file locally and just upload a txt file containing that hash.
|
||||||
//
|
//
|
||||||
// In the view this only happens when the user is allowed to do local hashing as well
|
// In the view this only happens when the user is allowed to do local hashing as well
|
||||||
// as when the correct query parameter is present in the url ('hash' and not 'upload')
|
// as when the correct method prop is present ('hash' and not 'upload')
|
||||||
let queryParams = this.props.location.query;
|
if (this.props.enableLocalHashing && this.props.uploadMethod === 'hash') {
|
||||||
if(this.props.enableLocalHashing && queryParams && queryParams.method === 'hash') {
|
const convertedFilePromises = [];
|
||||||
|
|
||||||
let convertedFilePromises = [];
|
|
||||||
let overallFileSize = 0;
|
let overallFileSize = 0;
|
||||||
|
|
||||||
// "files" is not a classical Javascript array but a Javascript FileList, therefore
|
// "files" is not a classical Javascript array but a Javascript FileList, therefore
|
||||||
// we can not use map to convert values
|
// we can not use map to convert values
|
||||||
for(let i = 0; i < files.length; i++) {
|
for(let i = 0; i < files.length; i++) {
|
||||||
|
|
||||||
// for calculating the overall progress of all submitted files
|
// for calculating the overall progress of all submitted files
|
||||||
// we'll need to calculate the overall sum of all files' sizes
|
// we'll need to calculate the overall sum of all files' sizes
|
||||||
overallFileSize += files[i].size;
|
overallFileSize += files[i].size;
|
||||||
@ -668,7 +663,6 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
// we're using promises to handle that
|
// we're using promises to handle that
|
||||||
let hashedFilePromise = computeHashOfFile(files[i]);
|
let hashedFilePromise = computeHashOfFile(files[i]);
|
||||||
convertedFilePromises.push(hashedFilePromise);
|
convertedFilePromises.push(hashedFilePromise);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// To react after the computation of all files, we define the resolvement
|
// To react after the computation of all files, we define the resolvement
|
||||||
@ -676,7 +670,6 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
// with their txt representative
|
// with their txt representative
|
||||||
Q.all(convertedFilePromises)
|
Q.all(convertedFilePromises)
|
||||||
.progress(({index, value: {progress, reject}}) => {
|
.progress(({index, value: {progress, reject}}) => {
|
||||||
|
|
||||||
// hashing progress has been aborted from outside
|
// hashing progress has been aborted from outside
|
||||||
// To get out of the executing, we need to call reject from the
|
// To get out of the executing, we need to call reject from the
|
||||||
// inside of the promise's execution.
|
// inside of the promise's execution.
|
||||||
@ -696,18 +689,14 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
// currently hashing files
|
// currently hashing files
|
||||||
let overallHashingProgress = 0;
|
let overallHashingProgress = 0;
|
||||||
for(let i = 0; i < files.length; i++) {
|
for(let i = 0; i < files.length; i++) {
|
||||||
|
|
||||||
let filesSliceOfOverall = files[i].size / overallFileSize;
|
let filesSliceOfOverall = files[i].size / overallFileSize;
|
||||||
overallHashingProgress += filesSliceOfOverall * files[i].progress;
|
overallHashingProgress += filesSliceOfOverall * files[i].progress;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiply by 100, since react-progressbar expects decimal numbers
|
// Multiply by 100, since react-progressbar expects decimal numbers
|
||||||
this.setState({ hashingProgress: overallHashingProgress * 100});
|
this.setState({ hashingProgress: overallHashingProgress * 100});
|
||||||
|
|
||||||
})
|
})
|
||||||
.then((convertedFiles) => {
|
.then((convertedFiles) => {
|
||||||
|
|
||||||
// clear hashing progress, since its done
|
// clear hashing progress, since its done
|
||||||
this.setState({ hashingProgress: -2});
|
this.setState({ hashingProgress: -2});
|
||||||
|
|
||||||
@ -823,20 +812,18 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
changeSet.status = { $set: status };
|
changeSet.status = { $set: status };
|
||||||
|
|
||||||
let filesToUpload = React.addons.update(this.state.filesToUpload, { [fileId]: changeSet });
|
let filesToUpload = React.addons.update(this.state.filesToUpload, { [fileId]: changeSet });
|
||||||
|
|
||||||
this.setState({ filesToUpload });
|
this.setState({ filesToUpload });
|
||||||
},
|
},
|
||||||
|
|
||||||
isDropzoneInactive() {
|
isDropzoneInactive() {
|
||||||
let filesToDisplay = this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1);
|
const filesToDisplay = this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1);
|
||||||
let queryParams = this.props.location.query;
|
|
||||||
|
|
||||||
if((this.props.enableLocalHashing && !queryParams.method) || !this.props.areAssetsEditable || !this.props.multiple && filesToDisplay.length > 0) {
|
if ((this.props.enableLocalHashing && !this.props.uploadMethod) || !this.props.areAssetsEditable || !this.props.multiple && filesToDisplay.length > 0) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getAllowedExtensions() {
|
getAllowedExtensions() {
|
||||||
@ -850,17 +837,16 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {
|
const {
|
||||||
multiple,
|
multiple,
|
||||||
areAssetsDownloadable,
|
areAssetsDownloadable,
|
||||||
areAssetsEditable,
|
areAssetsEditable,
|
||||||
onInactive,
|
onInactive,
|
||||||
enableLocalHashing,
|
enableLocalHashing,
|
||||||
fileClassToUpload,
|
uploadMethod,
|
||||||
validation,
|
fileClassToUpload,
|
||||||
fileInputElement,
|
validation,
|
||||||
location
|
fileInputElement } = this.props;
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
// Here we initialize the template that has been either provided from the outside
|
// Here we initialize the template that has been either provided from the outside
|
||||||
// or the default input that is FileDragAndDrop.
|
// or the default input that is FileDragAndDrop.
|
||||||
@ -870,8 +856,8 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
areAssetsEditable,
|
areAssetsEditable,
|
||||||
onInactive,
|
onInactive,
|
||||||
enableLocalHashing,
|
enableLocalHashing,
|
||||||
|
uploadMethod,
|
||||||
fileClassToUpload,
|
fileClassToUpload,
|
||||||
location,
|
|
||||||
onDrop: this.handleUploadFile,
|
onDrop: this.handleUploadFile,
|
||||||
filesToUpload: this.state.filesToUpload,
|
filesToUpload: this.state.filesToUpload,
|
||||||
handleDeleteFile: this.handleDeleteFile,
|
handleDeleteFile: this.handleDeleteFile,
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import requests from '../utils/requests';
|
import requests from '../utils/requests';
|
||||||
|
|
||||||
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
|
|
||||||
import { mergeOptions } from '../utils/general_utils';
|
import { mergeOptions } from '../utils/general_utils';
|
||||||
|
import { generateOrderingQueryParams } from '../utils/url_utils';
|
||||||
|
|
||||||
let EditionListFetcher = {
|
let EditionListFetcher = {
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import requests from '../utils/requests';
|
import requests from '../utils/requests';
|
||||||
|
|
||||||
import { mergeOptions } from '../utils/general_utils';
|
import { mergeOptions } from '../utils/general_utils';
|
||||||
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
|
import { generateOrderingQueryParams } from '../utils/url_utils';
|
||||||
|
|
||||||
let PieceListFetcher = {
|
let PieceListFetcher = {
|
||||||
/**
|
/**
|
||||||
|
@ -2,63 +2,10 @@
|
|||||||
|
|
||||||
import Q from 'q';
|
import Q from 'q';
|
||||||
|
|
||||||
import { sanitize } from './general_utils';
|
|
||||||
import AppConstants from '../constants/application_constants';
|
import AppConstants from '../constants/application_constants';
|
||||||
|
|
||||||
// TODO: Create Unittests that test all functions
|
// TODO: Create Unittests that test all functions
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a key-value object of this form:
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* 'page': 1,
|
|
||||||
* 'pageSize': 10
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* and converts it to a query-parameter, which you can append to your URL.
|
|
||||||
* The return looks like this:
|
|
||||||
*
|
|
||||||
* ?page=1&page_size=10
|
|
||||||
*
|
|
||||||
* CamelCase gets converted to snake_case!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
export function argsToQueryParams(obj) {
|
|
||||||
|
|
||||||
obj = sanitize(obj);
|
|
||||||
|
|
||||||
return Object
|
|
||||||
.keys(obj)
|
|
||||||
.map((key, i) => {
|
|
||||||
let s = '';
|
|
||||||
|
|
||||||
if(i === 0) {
|
|
||||||
s += '?';
|
|
||||||
} else {
|
|
||||||
s += '&';
|
|
||||||
}
|
|
||||||
|
|
||||||
let snakeCaseKey = key.replace(/[A-Z]/, (match) => '_' + match.toLowerCase());
|
|
||||||
|
|
||||||
return s + snakeCaseKey + '=' + encodeURIComponent(obj[key]);
|
|
||||||
})
|
|
||||||
.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a string and a boolean and generates a string query parameter for
|
|
||||||
* an API call.
|
|
||||||
*/
|
|
||||||
export function generateOrderingQueryParams(orderBy, orderAsc) {
|
|
||||||
let interpolation = '';
|
|
||||||
|
|
||||||
if(!orderAsc) {
|
|
||||||
interpolation += '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
return interpolation + orderBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function status(response) {
|
export function status(response) {
|
||||||
if (response.status >= 200 && response.status < 300) {
|
if (response.status >= 200 && response.status < 300) {
|
||||||
return response;
|
return response;
|
||||||
@ -68,7 +15,7 @@ export function status(response) {
|
|||||||
|
|
||||||
export function getCookie(name) {
|
export function getCookie(name) {
|
||||||
let parts = document.cookie.split(';');
|
let parts = document.cookie.split(';');
|
||||||
|
|
||||||
for(let i = 0; i < parts.length; i++) {
|
for(let i = 0; i < parts.length; i++) {
|
||||||
if(parts[i].indexOf(AppConstants.csrftoken + '=') > -1) {
|
if(parts[i].indexOf(AppConstants.csrftoken + '=') > -1) {
|
||||||
return parts[i].split('=').pop();
|
return parts[i].split('=').pop();
|
||||||
@ -111,4 +58,4 @@ export function fetchImageAsBlob(url) {
|
|||||||
|
|
||||||
xhr.send();
|
xhr.send();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
import Q from 'q';
|
import Q from 'q';
|
||||||
|
|
||||||
import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils';
|
|
||||||
|
|
||||||
import AppConstants from '../constants/application_constants';
|
import AppConstants from '../constants/application_constants';
|
||||||
|
|
||||||
import {excludePropFromObject} from '../utils/general_utils';
|
import { getCookie } from '../utils/fetch_api_utils';
|
||||||
|
import { excludePropFromObject } from '../utils/general_utils';
|
||||||
|
import { argsToQueryParams } from '../utils/url_utils';
|
||||||
|
|
||||||
class Requests {
|
class Requests {
|
||||||
_merge(defaults, options) {
|
_merge(defaults, options) {
|
||||||
|
83
js/utils/url_utils.js
Normal file
83
js/utils/url_utils.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
import camelCase from 'camelcase';
|
||||||
|
import snakeCase from 'snake-case';
|
||||||
|
import qs from 'qs';
|
||||||
|
|
||||||
|
import { sanitize } from './general_utils';
|
||||||
|
|
||||||
|
// TODO: Create Unittests that test all functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a key-value dictionary of this form:
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* 'page': 1,
|
||||||
|
* 'pageSize': 10
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* and converts it to a query-parameter, which you can append to your URL.
|
||||||
|
* The return looks like this:
|
||||||
|
*
|
||||||
|
* ?page=1&page_size=10
|
||||||
|
*
|
||||||
|
* CamelCase gets converted to snake_case!
|
||||||
|
*
|
||||||
|
* @param {object} obj Query params dictionary
|
||||||
|
* @return {string} Query params string
|
||||||
|
*/
|
||||||
|
export function argsToQueryParams(obj) {
|
||||||
|
const sanitizedObj = sanitize(obj);
|
||||||
|
const queryParamObj = {};
|
||||||
|
|
||||||
|
Object
|
||||||
|
.keys(sanitizedObj)
|
||||||
|
.forEach((key) => {
|
||||||
|
queryParamObj[snakeCase(key)] = sanitizedObj[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use bracket arrayFormat as history.js and react-router use it
|
||||||
|
return '?' + qs.stringify(queryParamObj, { arrayFormat: 'brackets' });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current url's query params as an key-val dictionary.
|
||||||
|
* snake_case gets converted to CamelCase!
|
||||||
|
* @return {object} Query params dictionary
|
||||||
|
*/
|
||||||
|
export function getCurrentQueryParams() {
|
||||||
|
return queryParamsToArgs(window.location.search.substring(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given query param string into a key-val dictionary.
|
||||||
|
* snake_case gets converted to CamelCase!
|
||||||
|
* @param {string} queryParamString Query params string
|
||||||
|
* @return {object} Query params dictionary
|
||||||
|
*/
|
||||||
|
export function queryParamsToArgs(queryParamString) {
|
||||||
|
const qsQueryParamObj = qs.parse(queryParamString);
|
||||||
|
const camelCaseParamObj = {};
|
||||||
|
|
||||||
|
Object
|
||||||
|
.keys(qsQueryParamObj)
|
||||||
|
.forEach((key) => {
|
||||||
|
camelCaseParamObj[camelCase(key)] = qsQueryParamObj[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return camelCaseParamObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a string and a boolean and generates a string query parameter for
|
||||||
|
* an API call.
|
||||||
|
*/
|
||||||
|
export function generateOrderingQueryParams(orderBy, orderAsc) {
|
||||||
|
let interpolation = '';
|
||||||
|
|
||||||
|
if(!orderAsc) {
|
||||||
|
interpolation += '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
return interpolation + orderBy;
|
||||||
|
}
|
@ -46,6 +46,7 @@
|
|||||||
"browser-sync": "^2.7.5",
|
"browser-sync": "^2.7.5",
|
||||||
"browserify": "^9.0.8",
|
"browserify": "^9.0.8",
|
||||||
"browserify-shim": "^3.8.10",
|
"browserify-shim": "^3.8.10",
|
||||||
|
"camelcase": "^1.2.1",
|
||||||
"classnames": "^1.2.2",
|
"classnames": "^1.2.2",
|
||||||
"compression": "^1.4.4",
|
"compression": "^1.4.4",
|
||||||
"envify": "^3.4.0",
|
"envify": "^3.4.0",
|
||||||
@ -73,6 +74,7 @@
|
|||||||
"object-assign": "^2.0.0",
|
"object-assign": "^2.0.0",
|
||||||
"opn": "^3.0.2",
|
"opn": "^3.0.2",
|
||||||
"q": "^1.4.1",
|
"q": "^1.4.1",
|
||||||
|
"qs": "^5.2.0",
|
||||||
"raven-js": "^1.1.19",
|
"raven-js": "^1.1.19",
|
||||||
"react": "0.13.2",
|
"react": "0.13.2",
|
||||||
"react-bootstrap": "0.25.1",
|
"react-bootstrap": "0.25.1",
|
||||||
@ -83,6 +85,7 @@
|
|||||||
"react-textarea-autosize": "^2.5.2",
|
"react-textarea-autosize": "^2.5.2",
|
||||||
"reactify": "^1.1.0",
|
"reactify": "^1.1.0",
|
||||||
"shmui": "^0.1.0",
|
"shmui": "^0.1.0",
|
||||||
|
"snake-case": "^1.1.1",
|
||||||
"spark-md5": "~1.0.0",
|
"spark-md5": "~1.0.0",
|
||||||
"uglifyjs": "^2.4.10",
|
"uglifyjs": "^2.4.10",
|
||||||
"vinyl-buffer": "^1.0.0",
|
"vinyl-buffer": "^1.0.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user