mirror of
https://github.com/ascribe/onion.git
synced 2024-06-30 13:41:57 +02:00
Merge remote-tracking branch 'remotes/origin/AD-456-ikonotv-branded-page-for-registra' into AD-943-add-custom-additional-fields
This commit is contained in:
commit
b24d4608dd
|
@ -30,7 +30,7 @@ class ContractListActions {
|
||||||
|
|
||||||
changeContract(contract){
|
changeContract(contract){
|
||||||
return Q.Promise((resolve, reject) => {
|
return Q.Promise((resolve, reject) => {
|
||||||
OwnershipFetcher.makeContractPublic(contract)
|
OwnershipFetcher.changeContract(contract)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
resolve(res);
|
resolve(res);
|
||||||
})
|
})
|
||||||
|
|
|
@ -38,9 +38,9 @@ let FurtherDetails = React.createClass({
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
submitKey(key){
|
submitFile(file){
|
||||||
this.setState({
|
this.setState({
|
||||||
otherDataKey: key
|
otherDataKey: file.key
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ let FurtherDetails = React.createClass({
|
||||||
extraData={this.props.extraData} />
|
extraData={this.props.extraData} />
|
||||||
<Form>
|
<Form>
|
||||||
<FurtherDetailsFileuploader
|
<FurtherDetailsFileuploader
|
||||||
submitKey={this.submitKey}
|
submitFile={this.submitFile}
|
||||||
setIsUploadReady={this.setIsUploadReady}
|
setIsUploadReady={this.setIsUploadReady}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
editable={this.props.editable}
|
editable={this.props.editable}
|
||||||
|
|
|
@ -17,7 +17,7 @@ let FurtherDetailsFileuploader = React.createClass({
|
||||||
pieceId: React.PropTypes.number,
|
pieceId: React.PropTypes.number,
|
||||||
otherData: React.PropTypes.arrayOf(React.PropTypes.object),
|
otherData: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||||
setIsUploadReady: React.PropTypes.func,
|
setIsUploadReady: React.PropTypes.func,
|
||||||
submitKey: 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
|
||||||
|
@ -55,11 +55,8 @@ let FurtherDetailsFileuploader = React.createClass({
|
||||||
url: ApiUrls.blob_otherdatas,
|
url: ApiUrls.blob_otherdatas,
|
||||||
pieceId: this.props.pieceId
|
pieceId: this.props.pieceId
|
||||||
}}
|
}}
|
||||||
validation={{
|
validation={AppConstants.fineUploader.validation.additionalData}
|
||||||
itemLimit: 100000,
|
submitFile={this.props.submitFile}
|
||||||
sizeLimit: '50000000'
|
|
||||||
}}
|
|
||||||
submitKey={this.props.submitKey}
|
|
||||||
setIsUploadReady={this.props.setIsUploadReady}
|
setIsUploadReady={this.props.setIsUploadReady}
|
||||||
isReadyForFormSubmission={this.props.isReadyForFormSubmission}
|
isReadyForFormSubmission={this.props.isReadyForFormSubmission}
|
||||||
session={{
|
session={{
|
||||||
|
|
|
@ -4,45 +4,40 @@ import React from 'react';
|
||||||
|
|
||||||
import Form from '../ascribe_forms/form';
|
import Form from '../ascribe_forms/form';
|
||||||
import Property from '../ascribe_forms/property';
|
import Property from '../ascribe_forms/property';
|
||||||
import InputCheckbox from '../ascribe_forms/input_checkbox';
|
|
||||||
|
|
||||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||||
|
|
||||||
import ContractListActions from '../../actions/contract_list_actions';
|
import ContractListActions from '../../actions/contract_list_actions';
|
||||||
|
|
||||||
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
|
|
||||||
|
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../constants/application_constants';
|
||||||
import ApiUrls from '../../constants/api_urls';
|
import ApiUrls from '../../constants/api_urls';
|
||||||
|
|
||||||
|
import InputFineUploader from './input_fineuploader';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
import { getCookie } from '../../utils/fetch_api_utils';
|
|
||||||
import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||||
|
|
||||||
|
|
||||||
let CreateContractForm = React.createClass({
|
let CreateContractForm = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
isPublic: React.PropTypes.bool,
|
||||||
|
|
||||||
|
// A class of a file the user has to upload
|
||||||
|
// Needs to be defined both in singular as well as in plural
|
||||||
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
|
singular: React.PropTypes.string,
|
||||||
|
plural: React.PropTypes.string
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return {
|
return {
|
||||||
contractKey: null,
|
isUploadReady: false,
|
||||||
isUploadReady: false
|
contractName: ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormData(){
|
|
||||||
return {
|
|
||||||
blob: this.state.contractKey
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
submitKey(key) {
|
|
||||||
this.setState({
|
|
||||||
contractKey: key
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setIsUploadReady(isReady) {
|
setIsUploadReady(isReady) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isUploadReady: isReady
|
isUploadReady: isReady
|
||||||
|
@ -56,31 +51,25 @@ let CreateContractForm = React.createClass({
|
||||||
this.refs.form.reset();
|
this.refs.form.reset();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
submitFileName(fileName) {
|
||||||
|
this.setState({
|
||||||
|
contractName: fileName
|
||||||
|
});
|
||||||
|
|
||||||
|
this.refs.form.submit();
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
ref='form'
|
ref='form'
|
||||||
url={ApiUrls.ownership_contract_list}
|
url={ApiUrls.ownership_contract_list}
|
||||||
getFormData={this.getFormData}
|
handleSuccess={this.handleCreateSuccess}>
|
||||||
handleSuccess={this.handleCreateSuccess}
|
|
||||||
buttons={
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="btn ascribe-btn ascribe-btn-login"
|
|
||||||
disabled={!this.state.isUploadReady}>
|
|
||||||
{getLangText('Create new contract')}
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
spinner={
|
|
||||||
<span className="btn ascribe-btn ascribe-btn-login ascribe-btn-login-spinner">
|
|
||||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
|
||||||
</span>
|
|
||||||
}>
|
|
||||||
<Property
|
<Property
|
||||||
label="Contract file">
|
name="blob"
|
||||||
<ReactS3FineUploader
|
label={getLangText('Contract file (*.pdf only, max. 50MB per contract)')}>
|
||||||
ref='uploader'
|
<InputFineUploader
|
||||||
|
submitFileName={this.submitFileName}
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
fileClass: 'contract'
|
fileClass: 'contract'
|
||||||
|
@ -89,46 +78,30 @@ let CreateContractForm = React.createClass({
|
||||||
url: ApiUrls.blob_contracts
|
url: ApiUrls.blob_contracts
|
||||||
}}
|
}}
|
||||||
validation={{
|
validation={{
|
||||||
itemLimit: 100000,
|
itemLimit: AppConstants.fineUploader.validation.additionalData.itemLimit,
|
||||||
sizeLimit: '50000000'
|
sizeLimit: AppConstants.fineUploader.validation.additionalData.sizeLimit,
|
||||||
}}
|
allowedExtensions: ['pdf']
|
||||||
signature={{
|
|
||||||
endpoint: AppConstants.serverUrl + 's3/signature/',
|
|
||||||
customHeaders: {
|
|
||||||
'X-CSRFToken': getCookie(AppConstants.csrftoken)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
deleteFile={{
|
|
||||||
enabled: true,
|
|
||||||
method: 'DELETE',
|
|
||||||
endpoint: AppConstants.serverUrl + 's3/delete',
|
|
||||||
customHeaders: {
|
|
||||||
'X-CSRFToken': getCookie(AppConstants.csrftoken)
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
areAssetsDownloadable={true}
|
areAssetsDownloadable={true}
|
||||||
areAssetsEditable={true}
|
areAssetsEditable={true}
|
||||||
submitKey={this.submitKey}
|
|
||||||
setIsUploadReady={this.setIsUploadReady}
|
setIsUploadReady={this.setIsUploadReady}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}/>
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
|
fileClassToUpload={this.props.fileClassToUpload}/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='name'
|
name='name'
|
||||||
label={getLangText('Contract name')}>
|
label={getLangText('Contract name')}
|
||||||
|
hidden={true}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="(e.g. Contract - Loan agreement #1)"
|
value={this.state.contractName}/>
|
||||||
required/>
|
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name="is_public"
|
name="is_public"
|
||||||
className="ascribe-settings-property-collapsible-toggle"
|
hidden={true}>
|
||||||
style={{paddingBottom: 0}}>
|
<input
|
||||||
<InputCheckbox>
|
type="checkbox"
|
||||||
<span>
|
value={this.props.isPublic} />
|
||||||
Make contract public (this will replace the current public contract)
|
|
||||||
</span>
|
|
||||||
</InputCheckbox>
|
|
||||||
</Property>
|
</Property>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Property from './property';
|
||||||
import InputFineUploader from './input_fineuploader';
|
import InputFineUploader from './input_fineuploader';
|
||||||
|
|
||||||
import ApiUrls from '../../constants/api_urls';
|
import ApiUrls from '../../constants/api_urls';
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
import { mergeOptions } from '../../utils/general_utils';
|
import { mergeOptions } from '../../utils/general_utils';
|
||||||
|
@ -99,6 +100,14 @@ let RegisterPieceForm = React.createClass({
|
||||||
name="digital_work_key"
|
name="digital_work_key"
|
||||||
ignoreFocus={true}>
|
ignoreFocus={true}>
|
||||||
<InputFineUploader
|
<InputFineUploader
|
||||||
|
keyRoutine={{
|
||||||
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
|
fileClass: 'digitalwork'
|
||||||
|
}}
|
||||||
|
createBlobRoutine={{
|
||||||
|
url: ApiUrls.blob_digitalworks
|
||||||
|
}}
|
||||||
|
validation={AppConstants.fineUploader.validation.registerWork}
|
||||||
setIsUploadReady={this.setIsUploadReady}
|
setIsUploadReady={this.setIsUploadReady}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
isFineUploaderActive={this.props.isFineUploaderActive}
|
isFineUploaderActive={this.props.isFineUploaderActive}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import React from 'react';
|
||||||
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
|
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
|
||||||
|
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../constants/application_constants';
|
||||||
import ApiUrls from '../../constants/api_urls';
|
|
||||||
|
|
||||||
import { getCookie } from '../../utils/fetch_api_utils';
|
import { getCookie } from '../../utils/fetch_api_utils';
|
||||||
|
|
||||||
|
@ -13,7 +12,21 @@ let InputFileUploader = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
setIsUploadReady: React.PropTypes.func,
|
setIsUploadReady: React.PropTypes.func,
|
||||||
isReadyForFormSubmission: React.PropTypes.func,
|
isReadyForFormSubmission: React.PropTypes.func,
|
||||||
|
submitFileName: React.PropTypes.func,
|
||||||
|
|
||||||
onClick: React.PropTypes.func,
|
onClick: React.PropTypes.func,
|
||||||
|
keyRoutine: React.PropTypes.shape({
|
||||||
|
url: React.PropTypes.string,
|
||||||
|
fileClass: React.PropTypes.string
|
||||||
|
}),
|
||||||
|
createBlobRoutine: React.PropTypes.shape({
|
||||||
|
url: React.PropTypes.string
|
||||||
|
}),
|
||||||
|
validation: React.PropTypes.shape({
|
||||||
|
itemLimit: React.PropTypes.number,
|
||||||
|
sizeLimit: React.PropTypes.string,
|
||||||
|
allowedExtensions: React.PropTypes.arrayOf(React.PropTypes.string)
|
||||||
|
}),
|
||||||
|
|
||||||
// isFineUploaderActive is used to lock react fine uploader in case
|
// isFineUploaderActive is used to lock react fine uploader in case
|
||||||
// a user is actually not logged in already to prevent him from droping files
|
// a user is actually not logged in already to prevent him from droping files
|
||||||
|
@ -24,7 +37,14 @@ let InputFileUploader = React.createClass({
|
||||||
enableLocalHashing: React.PropTypes.bool,
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
|
|
||||||
// provided by Property
|
// provided by Property
|
||||||
disabled: React.PropTypes.bool
|
disabled: React.PropTypes.bool,
|
||||||
|
|
||||||
|
// A class of a file the user has to upload
|
||||||
|
// Needs to be defined both in singular as well as in plural
|
||||||
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
|
singular: React.PropTypes.string,
|
||||||
|
plural: React.PropTypes.string
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
|
@ -33,10 +53,14 @@ let InputFileUploader = React.createClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
submitKey(key){
|
submitFile(file){
|
||||||
this.setState({
|
this.setState({
|
||||||
value: key
|
value: file.key
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(typeof this.props.submitFileName === 'function') {
|
||||||
|
this.props.submitFileName(file.originalName);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
|
@ -56,18 +80,10 @@ let InputFileUploader = React.createClass({
|
||||||
<ReactS3FineUploader
|
<ReactS3FineUploader
|
||||||
ref="fineuploader"
|
ref="fineuploader"
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
keyRoutine={{
|
keyRoutine={this.props.keyRoutine}
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
createBlobRoutine={this.props.createBlobRoutine}
|
||||||
fileClass: 'digitalwork'
|
validation={this.props.validation}
|
||||||
}}
|
submitFile={this.submitFile}
|
||||||
createBlobRoutine={{
|
|
||||||
url: ApiUrls.blob_digitalworks
|
|
||||||
}}
|
|
||||||
submitKey={this.submitKey}
|
|
||||||
validation={{
|
|
||||||
itemLimit: 100000,
|
|
||||||
sizeLimit: '25000000000'
|
|
||||||
}}
|
|
||||||
setIsUploadReady={this.props.setIsUploadReady}
|
setIsUploadReady={this.props.setIsUploadReady}
|
||||||
isReadyForFormSubmission={this.props.isReadyForFormSubmission}
|
isReadyForFormSubmission={this.props.isReadyForFormSubmission}
|
||||||
areAssetsDownloadable={false}
|
areAssetsDownloadable={false}
|
||||||
|
@ -87,7 +103,8 @@ let InputFileUploader = React.createClass({
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onInactive={this.props.onLoggedOut}
|
onInactive={this.props.onLoggedOut}
|
||||||
enableLocalHashing={this.props.enableLocalHashing} />
|
enableLocalHashing={this.props.enableLocalHashing}
|
||||||
|
fileClassToUpload={this.props.fileClassToUpload}/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -70,7 +70,7 @@ let Property = React.createClass({
|
||||||
// In order to set this.state.value from another component
|
// In order to set this.state.value from another component
|
||||||
// the state of value should only be set if its not undefined and
|
// the state of value should only be set if its not undefined and
|
||||||
// actually references something
|
// actually references something
|
||||||
if(typeof childInput.getDOMNode().value !== 'undefined') {
|
if(childInput && typeof childInput.getDOMNode().value !== 'undefined') {
|
||||||
this.setState({
|
this.setState({
|
||||||
value: childInput.getDOMNode().value
|
value: childInput.getDOMNode().value
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,12 +9,14 @@ import ContractListStore from '../../stores/contract_list_store';
|
||||||
import ContractListActions from '../../actions/contract_list_actions';
|
import ContractListActions from '../../actions/contract_list_actions';
|
||||||
|
|
||||||
import ActionPanel from '../ascribe_panel/action_panel';
|
import ActionPanel from '../ascribe_panel/action_panel';
|
||||||
|
import ContractSettingsUpdateButton from './contract_settings_update_button';
|
||||||
|
|
||||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
let ContractSettings = React.createClass({
|
let ContractSettings = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
defaultExpanded: React.PropTypes.bool
|
defaultExpanded: React.PropTypes.bool
|
||||||
|
@ -37,23 +39,6 @@ let ContractSettings = React.createClass({
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
},
|
},
|
||||||
|
|
||||||
makeContractPublic(contract) {
|
|
||||||
return () => {
|
|
||||||
contract.is_public = true;
|
|
||||||
ContractListActions.changeContract(contract)
|
|
||||||
.then(() => {
|
|
||||||
ContractListActions.fetchContractList(true);
|
|
||||||
let notification = getLangText('Contract %s is now public', contract.name);
|
|
||||||
notification = new GlobalNotificationModel(notification, 'success', 4000);
|
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
let notification = new GlobalNotificationModel(err, 'danger', 10000);
|
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
removeContract(contract) {
|
removeContract(contract) {
|
||||||
return () => {
|
return () => {
|
||||||
ContractListActions.removeContract(contract.id)
|
ContractListActions.removeContract(contract.id)
|
||||||
|
@ -80,81 +65,92 @@ let ContractSettings = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
let publicContracts = this.getPublicContracts();
|
let publicContracts = this.getPublicContracts();
|
||||||
let privateContracts = this.getPrivateContracts();
|
let privateContracts = this.getPrivateContracts();
|
||||||
|
let createPublicContractForm = null;
|
||||||
|
|
||||||
|
if(publicContracts.length === 0) {
|
||||||
|
createPublicContractForm = (
|
||||||
|
<CreateContractForm
|
||||||
|
isPublic={true}
|
||||||
|
fileClassToUpload={{
|
||||||
|
singular: 'new public contract',
|
||||||
|
plural: 'new public contracts'
|
||||||
|
}}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('Contract Settings')}
|
title={getLangText('Contracts')}
|
||||||
show={true}
|
show={true}
|
||||||
defaultExpanded={true}>
|
defaultExpanded={true}>
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('List Contracts')}
|
title={getLangText('Public Contracts')}
|
||||||
show={true}
|
show={true}
|
||||||
defaultExpanded={true}>
|
defaultExpanded={true}>
|
||||||
<CollapsibleParagraph
|
{createPublicContractForm}
|
||||||
title={getLangText('Public Contracts')}
|
{publicContracts.map((contract, i) => {
|
||||||
show={true}
|
return (
|
||||||
defaultExpanded={true}>
|
<ActionPanel
|
||||||
{publicContracts.map((contract, i) => {
|
key={i}
|
||||||
return (
|
title={contract.name}
|
||||||
<ActionPanel
|
content={contract.name}
|
||||||
key={i}
|
buttons={
|
||||||
title={contract.name}
|
<div className="pull-right">
|
||||||
content={contract.name}
|
<ContractSettingsUpdateButton contract={contract}/>
|
||||||
buttons={
|
<a
|
||||||
<div className="pull-right">
|
className="btn btn-default btn-sm margin-left-2px"
|
||||||
<button className="btn btn-default btn-sm margin-left-2px">
|
href={contract.blob.url_safe}
|
||||||
UPDATE
|
target="_blank">
|
||||||
</button>
|
{getLangText('PREVIEW')}
|
||||||
<button
|
</a>
|
||||||
className="btn btn-default btn-sm margin-left-2px"
|
<button
|
||||||
onClick={this.removeContract(contract)}>
|
className="btn btn-default btn-sm margin-left-2px"
|
||||||
REMOVE
|
onClick={this.removeContract(contract)}>
|
||||||
</button>
|
{getLangText('REMOVE')}
|
||||||
</div>
|
</button>
|
||||||
}
|
</div>
|
||||||
leftColumnWidth="40%"
|
}
|
||||||
rightColumnWidth="60%"/>
|
leftColumnWidth="40%"
|
||||||
);
|
rightColumnWidth="60%"/>
|
||||||
})}
|
);
|
||||||
</CollapsibleParagraph>
|
})}
|
||||||
<CollapsibleParagraph
|
|
||||||
title={getLangText('Private Contracts')}
|
|
||||||
show={true}
|
|
||||||
defaultExpanded={true}>
|
|
||||||
{privateContracts.map((contract, i) => {
|
|
||||||
return (
|
|
||||||
<ActionPanel
|
|
||||||
key={i}
|
|
||||||
title={contract.name}
|
|
||||||
content={contract.name}
|
|
||||||
buttons={
|
|
||||||
<div className="pull-right">
|
|
||||||
<button className="btn btn-default btn-sm margin-left-2px">
|
|
||||||
UPDATE
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="btn btn-default btn-sm margin-left-2px"
|
|
||||||
onClick={this.removeContract(contract)}>
|
|
||||||
REMOVE
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="btn btn-default btn-sm margin-left-2px"
|
|
||||||
onClick={this.makeContractPublic(contract)}>
|
|
||||||
MAKE PUBLIC
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
leftColumnWidth="40%"
|
|
||||||
rightColumnWidth="60%"/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</CollapsibleParagraph>
|
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('Create Contract')}
|
title={getLangText('Private Contracts')}
|
||||||
show={true}
|
show={true}
|
||||||
defaultExpanded={true}>
|
defaultExpanded={true}>
|
||||||
<CreateContractForm />
|
<CreateContractForm
|
||||||
|
isPublic={false}
|
||||||
|
fileClassToUpload={{
|
||||||
|
singular: getLangText('new private contract'),
|
||||||
|
plural: getLangText('new private contracts')
|
||||||
|
}}/>
|
||||||
|
{privateContracts.map((contract, i) => {
|
||||||
|
return (
|
||||||
|
<ActionPanel
|
||||||
|
key={i}
|
||||||
|
title={contract.name}
|
||||||
|
content={contract.name}
|
||||||
|
buttons={
|
||||||
|
<div className="pull-right">
|
||||||
|
<ContractSettingsUpdateButton contract={contract} />
|
||||||
|
<a
|
||||||
|
className="btn btn-default btn-sm margin-left-2px"
|
||||||
|
href={contract.blob.url_safe}
|
||||||
|
target="_blank">
|
||||||
|
{getLangText('PREVIEW')}
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
className="btn btn-default btn-sm margin-left-2px"
|
||||||
|
onClick={this.removeContract(contract)}>
|
||||||
|
{getLangText('REMOVE')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
leftColumnWidth="40%"
|
||||||
|
rightColumnWidth="60%"/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
|
||||||
|
import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button';
|
||||||
|
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
import ApiUrls from '../../constants/api_urls';
|
||||||
|
|
||||||
|
import ContractListActions from '../../actions/contract_list_actions';
|
||||||
|
|
||||||
|
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||||
|
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||||
|
|
||||||
|
import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||||
|
import { getCookie } from '../../utils/fetch_api_utils';
|
||||||
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
|
let ContractSettingsUpdateButton = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
contract: React.PropTypes.object
|
||||||
|
},
|
||||||
|
|
||||||
|
submitFile(file) {
|
||||||
|
let contract = this.props.contract;
|
||||||
|
|
||||||
|
// override the blob with the key's value
|
||||||
|
contract.blob = file.key;
|
||||||
|
|
||||||
|
// send it to the server
|
||||||
|
ContractListActions
|
||||||
|
.changeContract(contract)
|
||||||
|
.then((res) => {
|
||||||
|
|
||||||
|
// Display feedback to the user
|
||||||
|
let notification = new GlobalNotificationModel(getLangText('Contract %s successfully updated', res.name), 'success', 5000);
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
|
// and refresh the contract list to get the updated contracs
|
||||||
|
return ContractListActions.fetchContractList(true);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Also, reset the fineuploader component so that the user can again 'update' his contract
|
||||||
|
this.refs.fineuploader.reset();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.logGlobal(err);
|
||||||
|
let notification = new GlobalNotificationModel(getLangText('Contract could not be updated'), 'success', 5000);
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<ReactS3FineUploader
|
||||||
|
ref="fineuploader"
|
||||||
|
fileInputElement={UploadButton}
|
||||||
|
keyRoutine={{
|
||||||
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
|
fileClass: 'contract'
|
||||||
|
}}
|
||||||
|
createBlobRoutine={{
|
||||||
|
url: ApiUrls.blob_contracts
|
||||||
|
}}
|
||||||
|
validation={{
|
||||||
|
itemLimit: AppConstants.fineUploader.validation.registerWork.itemLimit,
|
||||||
|
sizeLimit: AppConstants.fineUploader.validation.additionalData.sizeLimit,
|
||||||
|
allowedExtensions: ['pdf']
|
||||||
|
}}
|
||||||
|
setIsUploadReady={() =>{/* So that ReactS3FineUploader is not complaining */}}
|
||||||
|
signature={{
|
||||||
|
endpoint: AppConstants.serverUrl + 's3/signature/',
|
||||||
|
customHeaders: {
|
||||||
|
'X-CSRFToken': getCookie(AppConstants.csrftoken)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
deleteFile={{
|
||||||
|
enabled: true,
|
||||||
|
method: 'DELETE',
|
||||||
|
endpoint: AppConstants.serverUrl + 's3/delete',
|
||||||
|
customHeaders: {
|
||||||
|
'X-CSRFToken': getCookie(AppConstants.csrftoken)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
fileClassToUpload={{
|
||||||
|
singular: getLangText('UPDATE'),
|
||||||
|
plural: getLangText('UPDATE')
|
||||||
|
}}
|
||||||
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
|
submitFile={this.submitFile}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ContractSettingsUpdateButton;
|
|
@ -26,8 +26,6 @@ let SettingsContainer = React.createClass({
|
||||||
<APISettings />
|
<APISettings />
|
||||||
<BitcoinWalletSettings />
|
<BitcoinWalletSettings />
|
||||||
<ContractSettings />
|
<ContractSettings />
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,14 @@ import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||||
import FileDragAndDropDialog from './file_drag_and_drop_dialog';
|
import FileDragAndDropDialog from './file_drag_and_drop_dialog';
|
||||||
import FileDragAndDropPreviewIterator from './file_drag_and_drop_preview_iterator';
|
import FileDragAndDropPreviewIterator from './file_drag_and_drop_preview_iterator';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
// Taken from: https://github.com/fedosejev/react-file-drag-and-drop
|
// Taken from: https://github.com/fedosejev/react-file-drag-and-drop
|
||||||
let FileDragAndDrop = React.createClass({
|
let FileDragAndDrop = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
className: React.PropTypes.string,
|
|
||||||
onDragStart: React.PropTypes.func,
|
|
||||||
onDrop: React.PropTypes.func.isRequired,
|
onDrop: React.PropTypes.func.isRequired,
|
||||||
onDrag: React.PropTypes.func,
|
|
||||||
onDragEnter: React.PropTypes.func,
|
|
||||||
onLeave: React.PropTypes.func,
|
|
||||||
onDragLeave: React.PropTypes.func,
|
|
||||||
onDragOver: React.PropTypes.func,
|
onDragOver: React.PropTypes.func,
|
||||||
onDragEnd: React.PropTypes.func,
|
|
||||||
onInactive: React.PropTypes.func,
|
onInactive: React.PropTypes.func,
|
||||||
filesToUpload: React.PropTypes.array,
|
filesToUpload: React.PropTypes.array,
|
||||||
handleDeleteFile: React.PropTypes.func,
|
handleDeleteFile: React.PropTypes.func,
|
||||||
|
@ -37,37 +31,16 @@ let FileDragAndDrop = React.createClass({
|
||||||
hashingProgress: React.PropTypes.number,
|
hashingProgress: React.PropTypes.number,
|
||||||
// sets the value of this.state.hashingProgress in reactfineuploader
|
// sets the value of this.state.hashingProgress in reactfineuploader
|
||||||
// to -1 which is code for: aborted
|
// to -1 which is code for: aborted
|
||||||
handleCancelHashing: React.PropTypes.func
|
handleCancelHashing: React.PropTypes.func,
|
||||||
},
|
|
||||||
|
|
||||||
handleDragStart(event) {
|
// A class of a file the user has to upload
|
||||||
if (typeof this.props.onDragStart === 'function') {
|
// Needs to be defined both in singular as well as in plural
|
||||||
this.props.onDragStart(event);
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
}
|
singular: React.PropTypes.string,
|
||||||
},
|
plural: React.PropTypes.string
|
||||||
|
}),
|
||||||
|
|
||||||
handleDrag(event) {
|
allowedExtensions: React.PropTypes.string
|
||||||
if (typeof this.props.onDrag === 'function') {
|
|
||||||
this.props.onDrag(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleDragEnd(event) {
|
|
||||||
if (typeof this.props.onDragEnd === 'function') {
|
|
||||||
this.props.onDragEnd(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleDragEnter(event) {
|
|
||||||
if (typeof this.props.onDragEnter === 'function') {
|
|
||||||
this.props.onDragEnter(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleDragLeave(event) {
|
|
||||||
if (typeof this.props.onDragLeave === 'function') {
|
|
||||||
this.props.onDragLeave(event);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDragOver(event) {
|
handleDragOver(event) {
|
||||||
|
@ -159,14 +132,27 @@ let FileDragAndDrop = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
|
let { filesToUpload,
|
||||||
|
dropzoneInactive,
|
||||||
|
className,
|
||||||
|
hashingProgress,
|
||||||
|
handleCancelHashing,
|
||||||
|
multiple,
|
||||||
|
enableLocalHashing,
|
||||||
|
fileClassToUpload,
|
||||||
|
areAssetsDownloadable,
|
||||||
|
areAssetsEditable,
|
||||||
|
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 = this.props.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;
|
||||||
let className = hasFiles ? 'has-files ' : '';
|
let updatedClassName = hasFiles ? 'has-files ' : '';
|
||||||
className += this.props.dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone';
|
updatedClassName += dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone';
|
||||||
className += this.props.className ? ' ' + this.props.className : '';
|
updatedClassName += ' file-drag-and-drop';
|
||||||
|
|
||||||
// if !== -2: triggers a FileDragAndDrop-global spinner
|
// if !== -2: triggers a FileDragAndDrop-global spinner
|
||||||
if(this.props.hashingProgress !== -2) {
|
if(hashingProgress !== -2) {
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<div className="file-drag-and-drop-hashing-dialog">
|
<div className="file-drag-and-drop-hashing-dialog">
|
||||||
|
@ -184,29 +170,26 @@ let FileDragAndDrop = React.createClass({
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={className}
|
className={updatedClassName}
|
||||||
onDragStart={this.handleDragStart}
|
|
||||||
onDrag={this.handleDrop}
|
onDrag={this.handleDrop}
|
||||||
onDragEnter={this.handleDragEnter}
|
|
||||||
onDragLeave={this.handleDragLeave}
|
|
||||||
onDragOver={this.handleDragOver}
|
onDragOver={this.handleDragOver}
|
||||||
onDrop={this.handleDrop}
|
onDrop={this.handleDrop}>
|
||||||
onDragEnd={this.handleDragEnd}>
|
|
||||||
<FileDragAndDropDialog
|
<FileDragAndDropDialog
|
||||||
multipleFiles={this.props.multiple}
|
multipleFiles={multiple}
|
||||||
hasFiles={hasFiles}
|
hasFiles={hasFiles}
|
||||||
onClick={this.handleOnClick}
|
onClick={this.handleOnClick}
|
||||||
enableLocalHashing={this.props.enableLocalHashing}/>
|
enableLocalHashing={enableLocalHashing}
|
||||||
|
fileClassToUpload={fileClassToUpload}/>
|
||||||
<FileDragAndDropPreviewIterator
|
<FileDragAndDropPreviewIterator
|
||||||
files={this.props.filesToUpload}
|
files={filesToUpload}
|
||||||
handleDeleteFile={this.handleDeleteFile}
|
handleDeleteFile={this.handleDeleteFile}
|
||||||
handleCancelFile={this.handleCancelFile}
|
handleCancelFile={this.handleCancelFile}
|
||||||
handlePauseFile={this.handlePauseFile}
|
handlePauseFile={this.handlePauseFile}
|
||||||
handleResumeFile={this.handleResumeFile}
|
handleResumeFile={this.handleResumeFile}
|
||||||
areAssetsDownloadable={this.props.areAssetsDownloadable}
|
areAssetsDownloadable={areAssetsDownloadable}
|
||||||
areAssetsEditable={this.props.areAssetsEditable}/>
|
areAssetsEditable={areAssetsEditable}/>
|
||||||
<input
|
<input
|
||||||
multiple={this.props.multiple}
|
multiple={multiple}
|
||||||
ref="fileinput"
|
ref="fileinput"
|
||||||
type="file"
|
type="file"
|
||||||
style={{
|
style={{
|
||||||
|
@ -214,7 +197,8 @@ let FileDragAndDrop = React.createClass({
|
||||||
height: 0,
|
height: 0,
|
||||||
width: 0
|
width: 0
|
||||||
}}
|
}}
|
||||||
onChange={this.handleDrop} />
|
onChange={this.handleDrop}
|
||||||
|
accept={allowedExtensions}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Router from 'react-router';
|
import Router from 'react-router';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
|
||||||
let Link = Router.Link;
|
let Link = Router.Link;
|
||||||
|
|
||||||
|
@ -12,7 +12,14 @@ let FileDragAndDropDialog = React.createClass({
|
||||||
hasFiles: React.PropTypes.bool,
|
hasFiles: React.PropTypes.bool,
|
||||||
multipleFiles: React.PropTypes.bool,
|
multipleFiles: React.PropTypes.bool,
|
||||||
onClick: React.PropTypes.func,
|
onClick: React.PropTypes.func,
|
||||||
enableLocalHashing: React.PropTypes.bool
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
|
|
||||||
|
// A class of a file the user has to upload
|
||||||
|
// Needs to be defined both in singular as well as in plural
|
||||||
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
|
singular: React.PropTypes.string,
|
||||||
|
plural: React.PropTypes.string
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [Router.State],
|
mixins: [Router.State],
|
||||||
|
@ -56,29 +63,29 @@ let FileDragAndDropDialog = React.createClass({
|
||||||
} else {
|
} else {
|
||||||
if(this.props.multipleFiles) {
|
if(this.props.multipleFiles) {
|
||||||
return (
|
return (
|
||||||
<div className="file-drag-and-drop-dialog">
|
<span className="file-drag-and-drop-dialog">
|
||||||
<p>{getLangText('Drag files here')}</p>
|
<p>{getLangText('Drag %s here', this.props.fileClassToUpload.plural)}</p>
|
||||||
<p>{getLangText('or')}</p>
|
<p>{getLangText('or')}</p>
|
||||||
<span
|
<span
|
||||||
className="btn btn-default"
|
className="btn btn-default"
|
||||||
onClick={this.props.onClick}>
|
onClick={this.props.onClick}>
|
||||||
{getLangText('choose files to upload')}
|
{getLangText('choose %s to upload', this.props.fileClassToUpload.plural)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</span>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let dialog = queryParams.method === 'hash' ? getLangText('choose a file to hash') : getLangText('choose a file to upload');
|
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);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="file-drag-and-drop-dialog">
|
<span className="file-drag-and-drop-dialog">
|
||||||
<p>{getLangText('Drag a file here')}</p>
|
<p>{getLangText('Drag a %s here', this.props.fileClassToUpload.singular)}</p>
|
||||||
<p>{getLangText('or')}</p>
|
<p>{getLangText('or')}</p>
|
||||||
<span
|
<span
|
||||||
className="btn btn-default"
|
className="btn btn-default"
|
||||||
onClick={this.props.onClick}>
|
onClick={this.props.onClick}>
|
||||||
{dialog}
|
{dialog}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,9 @@ import React from 'react';
|
||||||
|
|
||||||
import FileDragAndDropPreviewImage from './file_drag_and_drop_preview_image';
|
import FileDragAndDropPreviewImage from './file_drag_and_drop_preview_image';
|
||||||
import FileDragAndDropPreviewOther from './file_drag_and_drop_preview_other';
|
import FileDragAndDropPreviewOther from './file_drag_and_drop_preview_other';
|
||||||
import { getLangText } from '../../utils/lang_utils.js';
|
|
||||||
|
|
||||||
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
|
||||||
let FileDragAndDropPreview = React.createClass({
|
let FileDragAndDropPreview = React.createClass({
|
||||||
|
|
||||||
|
@ -43,6 +45,7 @@ let FileDragAndDropPreview = React.createClass({
|
||||||
|
|
||||||
handleDownloadFile() {
|
handleDownloadFile() {
|
||||||
if(this.props.file.s3Url) {
|
if(this.props.file.s3Url) {
|
||||||
|
// This simply opens a new browser tab with the url provided
|
||||||
open(this.props.file.s3Url);
|
open(this.props.file.s3Url);
|
||||||
}
|
}
|
||||||
},
|
},
|
|
@ -3,8 +3,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||||
|
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../../constants/application_constants';
|
||||||
import { getLangText } from '../../utils/lang_utils.js';
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
|
||||||
let FileDragAndDropPreviewImage = React.createClass({
|
let FileDragAndDropPreviewImage = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
|
@ -5,7 +5,7 @@ import React from 'react';
|
||||||
import FileDragAndDropPreview from './file_drag_and_drop_preview';
|
import FileDragAndDropPreview from './file_drag_and_drop_preview';
|
||||||
import FileDragAndDropPreviewProgress from './file_drag_and_drop_preview_progress';
|
import FileDragAndDropPreviewProgress from './file_drag_and_drop_preview_progress';
|
||||||
|
|
||||||
import { displayValidFilesFilter } from './react_s3_fine_uploader_utils';
|
import { displayValidFilesFilter } from '../react_s3_fine_uploader_utils';
|
||||||
|
|
||||||
|
|
||||||
let FileDragAndDropPreviewIterator = React.createClass({
|
let FileDragAndDropPreviewIterator = React.createClass({
|
|
@ -3,8 +3,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||||
|
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../../constants/application_constants';
|
||||||
import { getLangText } from '../../utils/lang_utils.js';
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
|
||||||
let FileDragAndDropPreviewOther = React.createClass({
|
let FileDragAndDropPreviewOther = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
@ -61,7 +61,7 @@ let FileDragAndDropPreviewOther = React.createClass({
|
||||||
<div className="file-drag-and-drop-preview-table-wrapper">
|
<div className="file-drag-and-drop-preview-table-wrapper">
|
||||||
<div className="file-drag-and-drop-preview-other">
|
<div className="file-drag-and-drop-preview-other">
|
||||||
{actionSymbol}
|
{actionSymbol}
|
||||||
<span>{'.' + this.props.type}</span>
|
<p>{'.' + this.props.type}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -4,7 +4,8 @@ import React from 'react';
|
||||||
|
|
||||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||||
|
|
||||||
import { displayValidProgressFilesFilter } from './react_s3_fine_uploader_utils';
|
import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils';
|
||||||
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
let FileDragAndDropPreviewProgress = React.createClass({
|
let FileDragAndDropPreviewProgress = React.createClass({
|
||||||
|
@ -54,7 +55,7 @@ let FileDragAndDropPreviewProgress = React.createClass({
|
||||||
return (
|
return (
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
now={Math.ceil(overallProgress)}
|
now={Math.ceil(overallProgress)}
|
||||||
label="Overall progress: %(percent)s%"
|
label={getLangText('Overall progress%s', ': %(percent)s%')}
|
||||||
className="ascribe-progress-bar"
|
className="ascribe-progress-bar"
|
||||||
style={style} />
|
style={style} />
|
||||||
);
|
);
|
|
@ -0,0 +1,103 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils';
|
||||||
|
import { getLangText } from '../../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
|
let UploadButton = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
onDrop: React.PropTypes.func.isRequired,
|
||||||
|
filesToUpload: React.PropTypes.array,
|
||||||
|
multiple: React.PropTypes.bool,
|
||||||
|
|
||||||
|
// For simplification purposes we're just going to use this prop as a
|
||||||
|
// label for the upload button
|
||||||
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
|
singular: React.PropTypes.string,
|
||||||
|
plural: React.PropTypes.string
|
||||||
|
}),
|
||||||
|
|
||||||
|
allowedExtensions: React.PropTypes.string
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDrop(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
let files = event.target.files;
|
||||||
|
|
||||||
|
if(typeof this.props.onDrop === 'function' && files) {
|
||||||
|
this.props.onDrop(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
getUploadingFiles() {
|
||||||
|
return this.props.filesToUpload.filter((file) => file.status === 'uploading');
|
||||||
|
},
|
||||||
|
|
||||||
|
handleOnClick() {
|
||||||
|
let uploadingFiles = this.getUploadingFiles();
|
||||||
|
|
||||||
|
// We only want the button to be clickable if there are no files currently uploading
|
||||||
|
if(uploadingFiles.length === 0) {
|
||||||
|
// Firefox only recognizes the simulated mouse click if bubbles is set to true,
|
||||||
|
// but since Google Chrome propagates the event much further than needed, we
|
||||||
|
// need to stop propagation as soon as the event is created
|
||||||
|
var evt = new MouseEvent('click', {
|
||||||
|
view: window,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
evt.stopPropagation();
|
||||||
|
this.refs.fileinput.getDOMNode().dispatchEvent(evt);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getButtonLabel() {
|
||||||
|
let { filesToUpload, fileClassToUpload } = this.props;
|
||||||
|
|
||||||
|
// filter invalid files that might have been deleted or canceled...
|
||||||
|
filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter);
|
||||||
|
|
||||||
|
// Depending on wether there is an upload going on or not we
|
||||||
|
// display the progress
|
||||||
|
if(filesToUpload.length > 0) {
|
||||||
|
return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%';
|
||||||
|
} else {
|
||||||
|
return fileClassToUpload.singular;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let {
|
||||||
|
multiple,
|
||||||
|
fileClassToUpload,
|
||||||
|
allowedExtensions
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={this.handleOnClick}
|
||||||
|
className="btn btn-default btn-sm margin-left-2px"
|
||||||
|
disabled={this.getUploadingFiles().length !== 0}>
|
||||||
|
{this.getButtonLabel()}
|
||||||
|
<input
|
||||||
|
multiple={multiple}
|
||||||
|
ref="fileinput"
|
||||||
|
type="file"
|
||||||
|
style={{
|
||||||
|
display: 'none',
|
||||||
|
height: 0,
|
||||||
|
width: 0
|
||||||
|
}}
|
||||||
|
onChange={this.handleDrop}
|
||||||
|
accept={allowedExtensions}/>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default UploadButton;
|
|
@ -1,13 +1,13 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react/addons';
|
import React from 'react/addons';
|
||||||
|
import fineUploader from 'fineUploader';
|
||||||
import Router from 'react-router';
|
import Router from 'react-router';
|
||||||
import Q from 'q';
|
import Q from 'q';
|
||||||
|
|
||||||
import S3Fetcher from '../../fetchers/s3_fetcher';
|
import S3Fetcher from '../../fetchers/s3_fetcher';
|
||||||
|
|
||||||
import fineUploader from 'fineUploader';
|
import FileDragAndDrop from './ascribe_file_drag_and_drop/file_drag_and_drop';
|
||||||
import FileDragAndDrop from './file_drag_and_drop';
|
|
||||||
|
|
||||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||||
|
@ -15,10 +15,11 @@ import GlobalNotificationActions from '../../actions/global_notification_actions
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
|
||||||
import { computeHashOfFile } from '../../utils/file_utils';
|
import { computeHashOfFile } from '../../utils/file_utils';
|
||||||
import { displayValidFilesFilter } from './react_s3_fine_uploader_utils';
|
import { displayValidFilesFilter, transformAllowedExtensionsToInputAcceptProp } from './react_s3_fine_uploader_utils';
|
||||||
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({
|
||||||
|
@ -36,7 +37,7 @@ let ReactS3FineUploader = React.createClass({
|
||||||
React.PropTypes.number
|
React.PropTypes.number
|
||||||
])
|
])
|
||||||
}),
|
}),
|
||||||
submitKey: React.PropTypes.func,
|
submitFile: React.PropTypes.func,
|
||||||
autoUpload: React.PropTypes.bool,
|
autoUpload: React.PropTypes.bool,
|
||||||
debug: React.PropTypes.bool,
|
debug: React.PropTypes.bool,
|
||||||
objectProperties: React.PropTypes.shape({
|
objectProperties: React.PropTypes.shape({
|
||||||
|
@ -83,7 +84,8 @@ let ReactS3FineUploader = React.createClass({
|
||||||
}),
|
}),
|
||||||
validation: React.PropTypes.shape({
|
validation: React.PropTypes.shape({
|
||||||
itemLimit: React.PropTypes.number,
|
itemLimit: React.PropTypes.number,
|
||||||
sizeLimit: React.PropTypes.string
|
sizeLimit: React.PropTypes.string,
|
||||||
|
allowedExtensions: React.PropTypes.arrayOf(React.PropTypes.string)
|
||||||
}),
|
}),
|
||||||
messages: React.PropTypes.shape({
|
messages: React.PropTypes.shape({
|
||||||
unsupportedBrowser: React.PropTypes.string
|
unsupportedBrowser: React.PropTypes.string
|
||||||
|
@ -110,7 +112,22 @@ let ReactS3FineUploader = React.createClass({
|
||||||
enableLocalHashing: React.PropTypes.bool,
|
enableLocalHashing: React.PropTypes.bool,
|
||||||
|
|
||||||
// automatically injected by React-Router
|
// automatically injected by React-Router
|
||||||
query: React.PropTypes.object
|
query: React.PropTypes.object,
|
||||||
|
|
||||||
|
// A class of a file the user has to upload
|
||||||
|
// Needs to be defined both in singular as well as in plural
|
||||||
|
fileClassToUpload: React.PropTypes.shape({
|
||||||
|
singular: React.PropTypes.string,
|
||||||
|
plural: React.PropTypes.string
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Uploading functionality of react fineuploader is disconnected from its UI
|
||||||
|
// layer, which means that literally every (properly adjusted) react element
|
||||||
|
// can handle the UI handling.
|
||||||
|
fileInputElement: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.func,
|
||||||
|
React.PropTypes.element
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [Router.State],
|
mixins: [Router.State],
|
||||||
|
@ -162,7 +179,12 @@ let ReactS3FineUploader = React.createClass({
|
||||||
return name;
|
return name;
|
||||||
},
|
},
|
||||||
multiple: false,
|
multiple: false,
|
||||||
defaultErrorMessage: getLangText('Unexpected error. Please contact us if this happens repeatedly.')
|
defaultErrorMessage: getLangText('Unexpected error. Please contact us if this happens repeatedly.'),
|
||||||
|
fileClassToUpload: {
|
||||||
|
singular: getLangText('file'),
|
||||||
|
plural: getLangText('files')
|
||||||
|
},
|
||||||
|
fileInputElement: FileDragAndDrop
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -386,12 +408,12 @@ let ReactS3FineUploader = React.createClass({
|
||||||
// Only after the blob has been created server-side, we can make the form submittable.
|
// Only after the blob has been created server-side, we can make the form submittable.
|
||||||
this.createBlob(files[id])
|
this.createBlob(files[id])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey
|
// since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile
|
||||||
// are optional, we'll only trigger them when they're actually defined
|
// are optional, we'll only trigger them when they're actually defined
|
||||||
if(this.props.submitKey) {
|
if(this.props.submitFile) {
|
||||||
this.props.submitKey(files[id].key);
|
this.props.submitFile(files[id]);
|
||||||
} else {
|
} else {
|
||||||
console.warn('You didn\'t define submitKey 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
|
||||||
|
@ -426,7 +448,7 @@ let ReactS3FineUploader = React.createClass({
|
||||||
});
|
});
|
||||||
this.state.uploader.cancelAll();
|
this.state.uploader.cancelAll();
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel(this.props.defaultErrorMessage, 'danger', 5000);
|
let notification = new GlobalNotificationModel(errorReason || this.props.defaultErrorMessage, 'danger', 5000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -451,7 +473,7 @@ let ReactS3FineUploader = React.createClass({
|
||||||
let notification = new GlobalNotificationModel(getLangText('File upload canceled'), 'success', 5000);
|
let notification = new GlobalNotificationModel(getLangText('File upload canceled'), 'success', 5000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
// since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey
|
// since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile
|
||||||
// are optional, we'll only trigger them when they're actually defined
|
// are optional, we'll only trigger them when they're actually defined
|
||||||
if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
|
if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
|
||||||
if(this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
|
if(this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
|
||||||
|
@ -518,7 +540,7 @@ let ReactS3FineUploader = React.createClass({
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
// since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey
|
// since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile
|
||||||
// are optional, we'll only trigger them when they're actually defined
|
// are optional, we'll only trigger them when they're actually defined
|
||||||
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,
|
||||||
|
@ -818,27 +840,48 @@ let ReactS3FineUploader = React.createClass({
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getAllowedExtensions() {
|
||||||
|
let { validation } = this.props;
|
||||||
|
|
||||||
|
if(validation && validation.allowedExtensions && validation.allowedExtensions.length > 0) {
|
||||||
|
return transformAllowedExtensionsToInputAcceptProp(validation.allowedExtensions);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
let {
|
||||||
<div>
|
multiple,
|
||||||
<FileDragAndDrop
|
areAssetsDownloadable,
|
||||||
className="file-drag-and-drop"
|
areAssetsEditable,
|
||||||
onDrop={this.handleUploadFile}
|
onInactive,
|
||||||
filesToUpload={this.state.filesToUpload}
|
enableLocalHashing,
|
||||||
handleDeleteFile={this.handleDeleteFile}
|
fileClassToUpload,
|
||||||
handleCancelFile={this.handleCancelFile}
|
validation,
|
||||||
handlePauseFile={this.handlePauseFile}
|
fileInputElement
|
||||||
handleResumeFile={this.handleResumeFile}
|
} = this.props;
|
||||||
handleCancelHashing={this.handleCancelHashing}
|
|
||||||
multiple={this.props.multiple}
|
// Here we initialize the template that has been either provided from the outside
|
||||||
areAssetsDownloadable={this.props.areAssetsDownloadable}
|
// or the default input that is FileDragAndDrop.
|
||||||
areAssetsEditable={this.props.areAssetsEditable}
|
return React.createElement(fileInputElement, {
|
||||||
onInactive={this.props.onInactive}
|
onDrop: this.handleUploadFile,
|
||||||
dropzoneInactive={this.isDropzoneInactive()}
|
filesToUpload: this.state.filesToUpload,
|
||||||
hashingProgress={this.state.hashingProgress}
|
handleDeleteFile: this.handleDeleteFile,
|
||||||
enableLocalHashing={this.props.enableLocalHashing} />
|
handleCancelFile: this.handleCancelFile,
|
||||||
</div>
|
handlePauseFile: this.handlePauseFile,
|
||||||
);
|
handleResumeFile: this.handleResumeFile,
|
||||||
|
handleCancelHashing: this.handleCancelHashing,
|
||||||
|
multiple: multiple,
|
||||||
|
areAssetsDownloadable: areAssetsDownloadable,
|
||||||
|
areAssetsEditable: areAssetsEditable,
|
||||||
|
onInactive: onInactive,
|
||||||
|
dropzoneInactive: this.isDropzoneInactive(),
|
||||||
|
hashingProgress: this.state.hashingProgress,
|
||||||
|
enableLocalHashing: enableLocalHashing,
|
||||||
|
fileClassToUpload: fileClassToUpload,
|
||||||
|
allowedExtensions: this.getAllowedExtensions()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -52,3 +52,22 @@ export function displayValidProgressFilesFilter(file) {
|
||||||
return file.status !== 'deleted' && file.status !== 'canceled' && file.status !== 'online';
|
return file.status !== 'deleted' && file.status !== 'canceled' && file.status !== 'online';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fineuploader allows to specify the file extensions that are allowed to upload.
|
||||||
|
* For our self defined input, we can reuse those declarations to restrict which files
|
||||||
|
* the user can pick from his hard drive.
|
||||||
|
*
|
||||||
|
* Takes an array of file extensions (['pdf', 'png', ...]) and transforms them into a string
|
||||||
|
* that can be passed into an html5 input via its 'accept' prop.
|
||||||
|
* @param {array} allowedExtensions Array of strings without a dot prefixed
|
||||||
|
* @return {string} Joined string (comma-separated) of the passed-in array
|
||||||
|
*/
|
||||||
|
export function transformAllowedExtensionsToInputAcceptProp(allowedExtensions) {
|
||||||
|
// add a dot in front of the extension
|
||||||
|
let prefixedAllowedExtensions = allowedExtensions.map((ext) => '.' + ext);
|
||||||
|
|
||||||
|
// generate a comma separated list to add them to the DOM element
|
||||||
|
// See: http://stackoverflow.com/questions/4328947/limit-file-format-when-using-input-type-file
|
||||||
|
return prefixedAllowedExtensions.join(', ');
|
||||||
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ let CylandAdditionalDataForm = React.createClass({
|
||||||
</Property>
|
</Property>
|
||||||
<FurtherDetailsFileuploader
|
<FurtherDetailsFileuploader
|
||||||
uploadStarted={this.uploadStarted}
|
uploadStarted={this.uploadStarted}
|
||||||
submitKey={this.submitKey}
|
submitFile={this.submitFile}
|
||||||
setIsUploadReady={this.setIsUploadReady}
|
setIsUploadReady={this.setIsUploadReady}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.fileOptional}
|
isReadyForFormSubmission={formSubmissionValidation.fileOptional}
|
||||||
editable={!this.props.disabled}
|
editable={!this.props.disabled}
|
||||||
|
|
|
@ -57,6 +57,19 @@ let constants = {
|
||||||
// Source: http://www.w3schools.com/tags/att_input_type.asp
|
// Source: http://www.w3schools.com/tags/att_input_type.asp
|
||||||
'possibleInputTypes': ['button', 'checkbox', 'color', 'date', 'datetime', 'datetime-local', 'email', 'file', 'hidden', 'image', 'month', 'number', 'password', 'radio', 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week'],
|
'possibleInputTypes': ['button', 'checkbox', 'color', 'date', 'datetime', 'datetime-local', 'email', 'file', 'hidden', 'image', 'month', 'number', 'password', 'radio', 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week'],
|
||||||
|
|
||||||
|
'fineUploader': {
|
||||||
|
'validation': {
|
||||||
|
'additionalData': {
|
||||||
|
'itemLimit': 100,
|
||||||
|
'sizeLimit': '50000000'
|
||||||
|
},
|
||||||
|
'registerWork': {
|
||||||
|
'itemLimit': 1,
|
||||||
|
'sizeLimit': '25000000000'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// in case of whitelabel customization, we store stuff here
|
// in case of whitelabel customization, we store stuff here
|
||||||
'whitelabel': {},
|
'whitelabel': {},
|
||||||
'raven': {
|
'raven': {
|
||||||
|
|
|
@ -48,7 +48,7 @@ let OwnershipFetcher = {
|
||||||
return requests.get(ApiUrls.ownership_loans_pieces_request);
|
return requests.get(ApiUrls.ownership_loans_pieces_request);
|
||||||
},
|
},
|
||||||
|
|
||||||
makeContractPublic(contractObj){
|
changeContract(contractObj){
|
||||||
return requests.put(ApiUrls.ownership_contract, { body: contractObj, contract_id: contractObj.id });
|
return requests.put(ApiUrls.ownership_contract, { body: contractObj, contract_id: contractObj.id });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,8 @@
|
||||||
background: none;
|
background: none;
|
||||||
border: 0;
|
border: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
/* Shrink the size of the headline for a nested element */
|
.ascribe-collapsible-wrapper {
|
||||||
.ascribe-collapsible-wrapper > .ascribe-collapsible-content {
|
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
font-size: 95%;
|
font-size: 95%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
cursor: default !important;
|
cursor: default !important;
|
||||||
|
padding: 1.5em 0 1.5em 0;
|
||||||
|
|
||||||
.file-drag-and-drop-dialog > p:first-child {
|
.file-drag-and-drop-dialog > p:first-child {
|
||||||
font-size: 1.5em !important;
|
font-size: 1.5em !important;
|
||||||
|
|
|
@ -486,4 +486,4 @@ hr {
|
||||||
|
|
||||||
.ascribe-progress-bar-xs {
|
.ascribe-progress-bar-xs {
|
||||||
height: 12px;
|
height: 12px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user