mirror of
https://github.com/ascribe/onion.git
synced 2025-01-03 18:35:09 +01:00
Merge with AD-1264
This commit is contained in:
commit
cd6673f255
@ -21,8 +21,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() {
|
||||||
@ -46,6 +45,7 @@ let FurtherDetailsFileuploader = React.createClass({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Property
|
<Property
|
||||||
|
name="other_data_key"
|
||||||
label={this.props.label}>
|
label={this.props.label}>
|
||||||
<ReactS3FineUploader
|
<ReactS3FineUploader
|
||||||
uploadStarted={this.props.uploadStarted}
|
uploadStarted={this.props.uploadStarted}
|
||||||
@ -91,8 +91,7 @@ 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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@ import GlobalNotificationActions from '../../actions/global_notification_actions
|
|||||||
import requests from '../../utils/requests';
|
import requests from '../../utils/requests';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
import { mergeOptionsWithDuplicates } from '../../utils/general_utils';
|
|
||||||
|
|
||||||
|
|
||||||
let Form = React.createClass({
|
let Form = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
@ -124,12 +122,12 @@ let Form = React.createClass({
|
|||||||
getFormData() {
|
getFormData() {
|
||||||
let data = {};
|
let data = {};
|
||||||
|
|
||||||
for(let ref in this.refs) {
|
for (let ref in this.refs) {
|
||||||
data[this.refs[ref].props.name] = this.refs[ref].state.value;
|
data[this.refs[ref].props.name] = this.refs[ref].state.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(typeof this.props.getFormData === 'function') {
|
if (typeof this.props.getFormData === 'function') {
|
||||||
data = mergeOptionsWithDuplicates(data, this.props.getFormData());
|
data = Object.assign(data, this.props.getFormData());
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@ -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'
|
||||||
|
@ -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,8 +107,8 @@ 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} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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,8 +89,7 @@ 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}/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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')}
|
||||||
@ -66,7 +69,7 @@ let FileDragAndDropDialog = React.createClass({
|
|||||||
<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>
|
||||||
|
@ -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() {
|
||||||
@ -202,7 +202,7 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUpdate() {
|
componentWillReceiveProps() {
|
||||||
// since the csrf header is defined in this component's props,
|
// since the csrf header is defined in this component's props,
|
||||||
// everytime the csrf cookie is changed we'll need to reinitalize
|
// everytime the csrf cookie is changed we'll need to reinitalize
|
||||||
// fineuploader and update the actual csrf token
|
// fineuploader and update the actual csrf token
|
||||||
@ -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,7 +369,6 @@ 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;
|
||||||
|
|
||||||
@ -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});
|
||||||
|
|
||||||
@ -828,15 +817,13 @@ let ReactS3FineUploader = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
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,
|
||||||
|
@ -33,7 +33,6 @@ import { mergeOptions } from '../../../../../../utils/general_utils';
|
|||||||
|
|
||||||
let CylandPieceContainer = React.createClass({
|
let CylandPieceContainer = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
location: React.PropTypes.object,
|
|
||||||
params: React.PropTypes.object
|
params: React.PropTypes.object
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -107,8 +106,7 @@ let CylandPieceContainer = React.createClass({
|
|||||||
<CylandAdditionalDataForm
|
<CylandAdditionalDataForm
|
||||||
piece={this.state.piece}
|
piece={this.state.piece}
|
||||||
disabled={!this.state.piece.acl.acl_edit}
|
disabled={!this.state.piece.acl.acl_edit}
|
||||||
isInline={true}
|
isInline={true} />
|
||||||
location={this.props.location}/>
|
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
</WalletPieceContainer>
|
</WalletPieceContainer>
|
||||||
);
|
);
|
||||||
|
@ -26,8 +26,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
handleSuccess: React.PropTypes.func,
|
handleSuccess: React.PropTypes.func,
|
||||||
piece: React.PropTypes.object.isRequired,
|
piece: React.PropTypes.object.isRequired,
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
isInline: React.PropTypes.bool,
|
isInline: React.PropTypes.bool
|
||||||
location: React.PropTypes.object
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -143,8 +142,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
isReadyForFormSubmission={formSubmissionValidation.fileOptional}
|
isReadyForFormSubmission={formSubmissionValidation.fileOptional}
|
||||||
pieceId={piece.id}
|
pieceId={piece.id}
|
||||||
otherData={piece.other_data}
|
otherData={piece.other_data}
|
||||||
multiple={true}
|
multiple={true} />
|
||||||
location={this.props.location}/>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -210,8 +210,7 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
<CylandAdditionalDataForm
|
<CylandAdditionalDataForm
|
||||||
disabled={this.state.step > 1}
|
disabled={this.state.step > 1}
|
||||||
handleSuccess={this.handleAdditionalDataSuccess}
|
handleSuccess={this.handleAdditionalDataSuccess}
|
||||||
piece={this.state.piece}
|
piece={this.state.piece} />
|
||||||
location={this.props.location}/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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;
|
||||||
|
@ -1,29 +1,21 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes an object and deletes all keys that are
|
* Takes an object and returns a shallow copy without any keys
|
||||||
*
|
* that fail the passed in filter function.
|
||||||
* tagged as false by the passed in filter function
|
* Does not modify the passed in object.
|
||||||
*
|
*
|
||||||
* @param {object} obj regular javascript object
|
* @param {object} obj regular javascript object
|
||||||
* @return {object} regular javascript object without null values or empty strings
|
* @return {object} regular javascript object without null values or empty strings
|
||||||
*/
|
*/
|
||||||
export function sanitize(obj, filterFn) {
|
export function sanitize(obj, filterFn) {
|
||||||
if(!filterFn) {
|
if (!filterFn) {
|
||||||
// By matching null with a double equal, we can match undefined and null
|
// By matching null with a double equal, we can match undefined and null
|
||||||
// http://stackoverflow.com/a/15992131
|
// http://stackoverflow.com/a/15992131
|
||||||
filterFn = (val) => val == null || val === '';
|
filterFn = (val) => val == null || val === '';
|
||||||
}
|
}
|
||||||
|
|
||||||
Object
|
return omitFromObject(obj, filterFn);
|
||||||
.keys(obj)
|
|
||||||
.map((key) => {
|
|
||||||
if(filterFn(obj[key])) {
|
|
||||||
delete obj[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,8 +74,8 @@ export function formatText() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Checks a list of objects for key duplicates and returns a boolean
|
* Checks a list of objects for key duplicates and returns a boolean
|
||||||
*/
|
*/
|
||||||
function _doesObjectListHaveDuplicates(l) {
|
function _doesObjectListHaveDuplicates(l) {
|
||||||
let mergedList = [];
|
let mergedList = [];
|
||||||
@ -117,38 +109,11 @@ function _doesObjectListHaveDuplicates(l) {
|
|||||||
export function mergeOptions(...l) {
|
export function mergeOptions(...l) {
|
||||||
// If the objects submitted in the list have duplicates,in their key names,
|
// If the objects submitted in the list have duplicates,in their key names,
|
||||||
// abort the merge and tell the function's user to check his objects.
|
// abort the merge and tell the function's user to check his objects.
|
||||||
if(_doesObjectListHaveDuplicates(l)) {
|
if (_doesObjectListHaveDuplicates(l)) {
|
||||||
throw new Error('The objects you submitted for merging have duplicates. Merge aborted.');
|
throw new Error('The objects you submitted for merging have duplicates. Merge aborted.');
|
||||||
}
|
}
|
||||||
|
|
||||||
let newObj = {};
|
return Object.assign({}, ...l);
|
||||||
|
|
||||||
for(let i = 1; i < l.length; i++) {
|
|
||||||
newObj = _mergeOptions(newObj, _mergeOptions(l[i - 1], l[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return newObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merges a number of objects even if there're having duplicates,
|
|
||||||
* taking the last given value for the key.
|
|
||||||
*
|
|
||||||
* DOES NOT RETURN AN ERROR!
|
|
||||||
*
|
|
||||||
* Takes a list of object and merges their keys to one object.
|
|
||||||
* Uses mergeOptions for two objects.
|
|
||||||
* @param {[type]} l [description]
|
|
||||||
* @return {[type]} [description]
|
|
||||||
*/
|
|
||||||
export function mergeOptionsWithDuplicates(...l) {
|
|
||||||
let newObj = {};
|
|
||||||
|
|
||||||
for(let i = 1; i < l.length; i++) {
|
|
||||||
newObj = _mergeOptions(newObj, _mergeOptions(l[i - 1], l[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return newObj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,25 +129,6 @@ export function update(a, ...l) {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
|
|
||||||
* @param obj1
|
|
||||||
* @param obj2
|
|
||||||
* @returns obj3 a new object based on obj1 and obj2
|
|
||||||
* Taken from: http://stackoverflow.com/a/171256/1263876
|
|
||||||
*/
|
|
||||||
function _mergeOptions(obj1, obj2) {
|
|
||||||
let obj3 = {};
|
|
||||||
|
|
||||||
for (let attrname in obj1) {
|
|
||||||
obj3[attrname] = obj1[attrname];
|
|
||||||
}
|
|
||||||
for (let attrname in obj2) {
|
|
||||||
obj3[attrname] = obj2[attrname];
|
|
||||||
}
|
|
||||||
return obj3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escape HTML in a string so it can be injected safely using
|
* Escape HTML in a string so it can be injected safely using
|
||||||
* React's `dangerouslySetInnerHTML`
|
* React's `dangerouslySetInnerHTML`
|
||||||
|
@ -2,24 +2,13 @@
|
|||||||
|
|
||||||
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 { getCookie } from '../utils/fetch_api_utils';
|
||||||
import { omitFromObject } from '../utils/general_utils';
|
import { omitFromObject } from '../utils/general_utils';
|
||||||
|
import { argsToQueryParams } from '../utils/url_utils';
|
||||||
|
|
||||||
class Requests {
|
class Requests {
|
||||||
_merge(defaults, options) {
|
|
||||||
let merged = {};
|
|
||||||
for (let key in defaults) {
|
|
||||||
merged[key] = defaults[key];
|
|
||||||
}
|
|
||||||
for (let key in options) {
|
|
||||||
merged[key] = options[key];
|
|
||||||
}
|
|
||||||
return merged;
|
|
||||||
}
|
|
||||||
|
|
||||||
unpackResponse(response) {
|
unpackResponse(response) {
|
||||||
if (response.status >= 500) {
|
if (response.status >= 500) {
|
||||||
throw new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url);
|
throw new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url);
|
||||||
@ -112,7 +101,7 @@ class Requests {
|
|||||||
|
|
||||||
request(verb, url, options) {
|
request(verb, url, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
let merged = this._merge(this.httpOptions, options);
|
let merged = Object.assign({}, this.httpOptions, options);
|
||||||
let csrftoken = getCookie(AppConstants.csrftoken);
|
let csrftoken = getCookie(AppConstants.csrftoken);
|
||||||
if (csrftoken) {
|
if (csrftoken) {
|
||||||
merged.headers['X-CSRFToken'] = csrftoken;
|
merged.headers['X-CSRFToken'] = csrftoken;
|
||||||
@ -124,16 +113,16 @@ class Requests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(url, params) {
|
get(url, params) {
|
||||||
if (url === undefined){
|
if (url === undefined) {
|
||||||
throw new Error('Url undefined');
|
throw new Error('Url undefined');
|
||||||
}
|
}
|
||||||
let paramsCopy = this._merge(params);
|
let paramsCopy = Object.assign({}, params);
|
||||||
let newUrl = this.prepareUrl(url, paramsCopy, true);
|
let newUrl = this.prepareUrl(url, paramsCopy, true);
|
||||||
return this.request('get', newUrl);
|
return this.request('get', newUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(url, params) {
|
delete(url, params) {
|
||||||
let paramsCopy = this._merge(params);
|
let paramsCopy = Object.assign({}, params);
|
||||||
let newUrl = this.prepareUrl(url, paramsCopy, true);
|
let newUrl = this.prepareUrl(url, paramsCopy, true);
|
||||||
return this.request('delete', newUrl);
|
return this.request('delete', newUrl);
|
||||||
}
|
}
|
||||||
@ -153,11 +142,11 @@ class Requests {
|
|||||||
return this._putOrPost(url, params, 'post');
|
return this._putOrPost(url, params, 'post');
|
||||||
}
|
}
|
||||||
|
|
||||||
put(url, params){
|
put(url, params) {
|
||||||
return this._putOrPost(url, params, 'put');
|
return this._putOrPost(url, params, 'put');
|
||||||
}
|
}
|
||||||
|
|
||||||
patch(url, params){
|
patch(url, params) {
|
||||||
return this._putOrPost(url, params, 'patch');
|
return this._putOrPost(url, params, 'patch');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 decamelize from 'decamelize';
|
||||||
|
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[decamelize(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,8 +46,10 @@
|
|||||||
"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",
|
||||||
|
"decamelize": "^1.1.1",
|
||||||
"envify": "^3.4.0",
|
"envify": "^3.4.0",
|
||||||
"eslint": "^0.22.1",
|
"eslint": "^0.22.1",
|
||||||
"eslint-plugin-react": "^2.5.0",
|
"eslint-plugin-react": "^2.5.0",
|
||||||
@ -73,6 +75,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": "^4.0.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",
|
||||||
|
Loading…
Reference in New Issue
Block a user