1
0
mirror of https://github.com/ascribe/onion.git synced 2025-02-14 21:10:27 +01:00

finalize delete and cancel functionality

This commit is contained in:
Tim Daubenschütz 2015-06-29 11:01:45 +02:00
commit 1a9c82d683
18 changed files with 439 additions and 84 deletions

View File

@ -93,7 +93,8 @@ gulp.task('browser-sync', function() {
browserSync({ browserSync({
files: config.filesToWatch, files: config.filesToWatch,
proxy: 'http://localhost:4000', proxy: 'http://localhost:4000',
port: 3000 port: 3000,
browser: "chromium-browser"
}); });
}); });

36
js/actions/coa_actions.js Normal file
View File

@ -0,0 +1,36 @@
'use strict';
import alt from '../alt';
import CoaFetcher from '../fetchers/coa_fetcher';
class CoaActions {
constructor() {
this.generateActions(
'updateCoa'
);
}
fetchOne(id) {
CoaFetcher.fetchOne(id)
.then((res) => {
this.actions.updateCoa(res.coa);
console.log(res.coa);
})
.catch((err) => {
console.log(err);
});
}
create(edition) {
CoaFetcher.create(edition.bitcoin_id)
.then((res) => {
this.actions.updateCoa(res.coa);
console.log(res.coa);
})
.catch((err) => {
console.log(err);
});
}
}
export default alt.createActions(CoaActions);

View File

@ -107,7 +107,7 @@ var FileDragAndDrop = React.createClass({
}, },
render: function () { render: function () {
let hasFiles = this.props.filesToUpload.length > 0; let hasFiles = this.props.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled').length > 0;
let className = hasFiles ? 'file-drag-and-drop has-files ' : 'file-drag-and-drop '; let className = hasFiles ? 'file-drag-and-drop has-files ' : 'file-drag-and-drop ';
className += this.props.dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone'; className += this.props.dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone';

View File

@ -16,13 +16,17 @@ let FileDragAndDropPreviewIterator = React.createClass({
return ( return (
<div> <div>
{this.props.files.map((file, i) => { {this.props.files.map((file, i) => {
return ( if(file.status !== 'deleted' && file.status !== 'canceled') {
<FileDragAndDropPreview return (
key={i} <FileDragAndDropPreview
file={file} key={i}
handleDeleteFile={this.props.handleDeleteFile} file={file}
handleCancelFile={this.props.handleCancelFile}/> handleDeleteFile={this.props.handleDeleteFile}
); handleCancelFile={this.props.handleCancelFile}/>
);
} else {
return null;
}
})} })}
</div> </div>
); );

View File

@ -6,6 +6,9 @@ import promise from 'es6-promise';
promise.polyfill(); promise.polyfill();
import fetch from 'isomorphic-fetch'; import fetch from 'isomorphic-fetch';
import AppConstants from '../../constants/application_constants';
import { getCookie } from '../../utils/fetch_api_utils';
import fineUploader from 'fineUploader'; import fineUploader from 'fineUploader';
import FileDragAndDrop from './file_drag_and_drop'; import FileDragAndDrop from './file_drag_and_drop';
@ -18,7 +21,8 @@ var ReactS3FineUploader = React.createClass({
propTypes: { propTypes: {
keyRoutine: React.PropTypes.shape({ keyRoutine: React.PropTypes.shape({
url: React.PropTypes.string, url: React.PropTypes.string,
fileClass: React.PropTypes.string fileClass: React.PropTypes.string,
bitcoinId: React.PropTypes.string
}), }),
createBlobRoutine: React.PropTypes.shape({ createBlobRoutine: React.PropTypes.shape({
url: React.PropTypes.string url: React.PropTypes.string
@ -79,8 +83,67 @@ var ReactS3FineUploader = React.createClass({
}) })
}, },
getDefaultProps() {
return {
autoUpload: true,
debug: false,
objectProperties: {
acl: 'public-read',
bucket: 'ascribe0'
},
request: {
endpoint: 'https://ascribe0.s3.amazonaws.com',
accessKey: 'AKIAIVCZJ33WSCBQ3QDA'
},
uploadSuccess: {
params: {
isBrowserPreviewCapable: fineUploader.supportedFeatures.imagePreviews
}
},
signature: {
endpoint: AppConstants.serverUrl + 's3/signature/',
customHeaders: {
'X-CSRFToken': getCookie('csrftoken')
},
},
deleteFile: {
enabled: true,
method: 'DELETE',
endpoint: AppConstants.serverUrl + 's3/delete',
customHeaders: {
'X-CSRFToken': getCookie('csrftoken')
}
},
cors: {
expected: true,
sendCredentials: true
},
chunking: {
enabled: true
},
resume: {
enabled: true
},
retry: {
enableAuto: false
},
session: {
endpoint: null
},
messages: {
unsupportedBrowser: '<h3>Upload is not functional in IE7 as IE7 has no support for CORS!</h3>'
},
formatFileName: function(name){// fix maybe
if (name !== undefined && name.length > 26) {
name = name.slice(0, 15) + '...' + name.slice(-15);
}
return name;
},
multiple: false
};
},
getInitialState() { getInitialState() {
console.log(this.props);
return { return {
filesToUpload: [], filesToUpload: [],
uploader: new fineUploader.s3.FineUploaderBasic(this.propsToConfig()) uploader: new fineUploader.s3.FineUploaderBasic(this.propsToConfig())
@ -143,7 +206,8 @@ var ReactS3FineUploader = React.createClass({
credentials: 'include', credentials: 'include',
body: JSON.stringify({ body: JSON.stringify({
'filename': filename, 'filename': filename,
'file_class': 'digitalwork' 'file_class': this.props.keyRoutine.fileClass,
'bitcoin_id': this.props.keyRoutine.bitcoinId
}) })
}) })
.then((res) => { .then((res) => {
@ -270,7 +334,7 @@ var ReactS3FineUploader = React.createClass({
// If multiple set and user already uploaded its work, // If multiple set and user already uploaded its work,
// cancel upload // cancel upload
if(!this.props.multiple && this.state.filesToUpload.length > 0) { if(!this.props.multiple && this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled').length > 0) {
return; return;
} }
@ -313,6 +377,7 @@ var ReactS3FineUploader = React.createClass({
} }
} }
// set the new file array
let newState = React.addons.update(this.state, { let newState = React.addons.update(this.state, {
filesToUpload: { $set: oldAndNewFiles } filesToUpload: { $set: oldAndNewFiles }
}); });
@ -341,7 +406,7 @@ var ReactS3FineUploader = React.createClass({
handleDeleteFile={this.handleDeleteFile} handleDeleteFile={this.handleDeleteFile}
handleCancelFile={this.handleCancelFile} handleCancelFile={this.handleCancelFile}
multiple={this.props.multiple} multiple={this.props.multiple}
dropzoneInactive={!this.props.multiple && this.state.filesToUpload.length > 0} /> dropzoneInactive={!this.props.multiple && this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled').length > 0} />
); );
} }

View File

@ -0,0 +1,101 @@
'use strict';
import React from 'react';
import Router from 'react-router';
import GlobalNotificationModel from '../models/global_notification_model';
import GlobalNotificationActions from '../actions/global_notification_actions';
import Form from './ascribe_forms/form';
import Property from './ascribe_forms/property';
import InputTextAreaToggable from './ascribe_forms/input_textarea_toggable';
import apiUrls from '../constants/api_urls';
let CoaVerifyContainer = React.createClass({
mixins: [Router.Navigation],
render() {
return (
<div className="ascribe-login-wrapper">
<br/>
<div className="ascribe-login-text ascribe-login-header">
Verify your Certificate of Authenticity
</div>
<CoaVerifyForm />
<br />
<br />
ascribe is using the following public key for verification:
<br />
<pre>
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDddadqY31kKPFYk8PQA8BWSTbm
gaGf9KEYBALp2nWAJcwq80qBzGF+gfi0Z+yb4ooeKHl27GnuxZYValE1Z5ZujfeJ
TgO4li59ZMYiah8oXZp/OysrBwCvWw0PtWd8/D9Nc4PqyOz5gzEh6kFah5VsuAke
Znu2w7KmeLZ85SmwEQIDAQAB
-----END PUBLIC KEY-----
</pre>
</div>
);
}
});
let CoaVerifyForm = React.createClass({
mixins: [Router.Navigation],
handleSuccess(response){
let notification = null;
if (response.verdict){
notification = new GlobalNotificationModel('Certificate of Authenticity successfully verified', 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
}
},
render() {
return (
<div>
<Form
url={apiUrls.coa_verify}
handleSuccess={this.handleSuccess}
buttons={
<button
type="submit"
className="btn ascribe-btn ascribe-btn-login">
Verify your Certificate of Authenticity
</button>}
spinner={
<button 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" />
</button>
}>
<Property
name='message'
label="Message">
<input
type="text"
placeholder="Copy paste the message on the bottom of your Certificate of Authenticity"
autoComplete="on"
name="username"
required/>
</Property>
<Property
name='signature'
label="Signature">
<InputTextAreaToggable
rows={3}
editable={true}
placeholder="Copy paste the signature on the bottom of your Certificate of Authenticity"
required/>
</Property>
<hr />
</Form>
</div>
);
}
});
export default CoaVerifyContainer;

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
import React from 'react'; import React from 'react';
import Router from 'react-router';
import Row from 'react-bootstrap/lib/Row'; import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col'; import Col from 'react-bootstrap/lib/Col';
@ -9,6 +10,8 @@ import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import UserActions from '../actions/user_actions'; import UserActions from '../actions/user_actions';
import UserStore from '../stores/user_store'; import UserStore from '../stores/user_store';
import CoaActions from '../actions/coa_actions';
import CoaStore from '../stores/coa_store';
import MediaPlayer from './ascribe_media/media_player'; import MediaPlayer from './ascribe_media/media_player';
@ -24,12 +27,16 @@ import RequestActionForm from './ascribe_forms/form_request_action';
import EditionActions from '../actions/edition_actions'; import EditionActions from '../actions/edition_actions';
import AclButtonList from './ascribe_buttons/acl_button_list'; import AclButtonList from './ascribe_buttons/acl_button_list';
import fineUploader from 'fineUploader';
import ReactS3FineUploader from './ascribe_uploader/react_s3_fine_uploader';
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 requests from '../utils/requests';
import apiUrls from '../constants/api_urls'; import apiUrls from '../constants/api_urls';
import AppConstants from '../constants/application_constants';
let Link = Router.Link;
/** /**
* This is the component that implements display-specific functionality * This is the component that implements display-specific functionality
*/ */
@ -93,6 +100,7 @@ let Edition = React.createClass({
<Col md={6} className="ascribe-edition-details"> <Col md={6} className="ascribe-edition-details">
<EditionHeader edition={this.props.edition}/> <EditionHeader edition={this.props.edition}/>
<EditionSummary <EditionSummary
currentUser={this.state.currentUser}
edition={this.props.edition} /> edition={this.props.edition} />
<CollapsibleParagraph <CollapsibleParagraph
@ -109,13 +117,20 @@ let Edition = React.createClass({
</CollapsibleParagraph> </CollapsibleParagraph>
<CollapsibleParagraph <CollapsibleParagraph
title="Further Details (all editions)" title="Further Details"
show={this.props.edition.acl.indexOf('edit') > -1 || Object.keys(this.props.edition.extra_data).length > 0}> show={this.props.edition.acl.indexOf('edit') > -1 || Object.keys(this.props.edition.extra_data).length > 0}>
<EditionFurtherDetails <EditionFurtherDetails
handleSuccess={this.props.loadEdition} handleSuccess={this.props.loadEdition}
edition={this.props.edition}/> edition={this.props.edition}/>
</CollapsibleParagraph> </CollapsibleParagraph>
<CollapsibleParagraph
title="Certificate of Authenticity"
show={this.props.edition.acl.indexOf('coa') > -1}>
<CoaDetails
edition={this.props.edition}/>
</CollapsibleParagraph>
<CollapsibleParagraph <CollapsibleParagraph
title="Provenance/Ownership History" title="Provenance/Ownership History"
show={this.props.edition.ownership_history && this.props.edition.ownership_history.length > 0}> show={this.props.edition.ownership_history && this.props.edition.ownership_history.length > 0}>
@ -191,6 +206,9 @@ let EditionSummary = React.createClass({
edition: React.PropTypes.object edition: React.PropTypes.object
}, },
getTransferWithdrawData(){
return {'bitcoin_id': this.props.edition.bitcoin_id};
},
handleSuccess(){ handleSuccess(){
EditionActions.fetchOne(this.props.edition.id); EditionActions.fetchOne(this.props.edition.id);
}, },
@ -202,7 +220,24 @@ let EditionSummary = React.createClass({
render() { render() {
let status = null; let status = null;
if (this.props.edition.status.length > 0){ if (this.props.edition.status.length > 0){
status = <EditionDetailProperty label="STATUS" value={ this.props.edition.status.join().replace(/_/, ' ') } />; let statusStr = this.props.edition.status.join().replace(/_/, ' ');
status = <EditionDetailProperty label="STATUS" value={ statusStr }/>;
if (this.props.edition.pending_new_owner && this.props.edition.acl.indexOf('withdraw_transfer') > -1){
status = (
<Form
url={apiUrls.ownership_transfers_withdraw}
getFormData={this.getTransferWithdrawData}
handleSuccess={this.showNotification}>
<EditionDetailProperty label="STATUS" value={ statusStr }>
<button
type="submit"
className="pull-right btn btn-default btn-sm">
WITHDRAW
</button>
</EditionDetailProperty>
</Form>
);
}
} }
let actions = null; let actions = null;
if (this.props.edition.request_action && this.props.edition.request_action.length > 0){ if (this.props.edition.request_action && this.props.edition.request_action.length > 0){
@ -262,6 +297,18 @@ let EditionDetailProperty = React.createClass({
}, },
render() { render() {
let value = this.props.value;
if (this.props.children){
value = (
<div className="row-same-height">
<div className="col-xs-6 col-xs-height col-bottom no-padding">
{ this.props.value }
</div>
<div className="col-xs-6 col-xs-height">
{ this.props.children }
</div>
</div>);
}
return ( return (
<div className="row ascribe-detail-property"> <div className="row ascribe-detail-property">
<div className="row-same-height"> <div className="row-same-height">
@ -269,7 +316,7 @@ let EditionDetailProperty = React.createClass({
<div>{ this.props.label + this.props.separator}</div> <div>{ this.props.label + this.props.separator}</div>
</div> </div>
<div className={this.props.valueClassName + ' col-xs-height col-bottom'}> <div className={this.props.valueClassName + ' col-xs-height col-bottom'}>
<div>{ this.props.value }</div> {value}
</div> </div>
</div> </div>
</div> </div>
@ -284,19 +331,20 @@ let EditionDetailHistoryIterator = React.createClass({
render() { render() {
return ( return (
<div> <Form>
{this.props.history.map((historicalEvent, i) => { {this.props.history.map((historicalEvent, i) => {
return ( return (
<EditionDetailProperty <Property
key={i} name={i}
label={historicalEvent[0]} key={i}
value={historicalEvent[1]} label={ historicalEvent[0] }
labelClassName="col-xs-4 col-sm-4 col-md-4 col-lg-4" editable={false}>
valueClassName="col-xs-8 col-sm-8 col-md-8 col-lg-8" <pre className="ascribe-pre">{ historicalEvent[1] }</pre>
separator="" /> </Property>
); );
})} })}
</div> <hr />
</Form>
); );
} }
}); });
@ -415,10 +463,92 @@ let EditionFurtherDetails = React.createClass({
handleSuccess={this.showNotification} handleSuccess={this.showNotification}
editable={editable} editable={editable}
edition={this.props.edition} /> edition={this.props.edition} />
<FileUploader
edition={this.props.edition}
ref='uploader'/>
</Col> </Col>
</Row> </Row>
); );
} }
}); });
let FileUploader = React.createClass( {
handleChange(){
this.setState({other_data_key: this.refs.fineuploader.state.filesToUpload[0].key});
},
render() {
return (
<ReactS3FineUploader
ref='fineuploader'
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'otherdata',
bitcoinId: this.props.edition.bitcoin_id
}}
createBlobRoutine={{
url: apiUrls.blob_digitalworks
}}
handleChange={this.handleChange}
validation={{
itemLimit: 100000,
sizeLimit: '10000000'
}}/>
);
}
});
let CoaDetails = React.createClass({
propTypes: {
edition: React.PropTypes.object
},
getInitialState() {
return CoaStore.getState();
},
componentDidMount() {
CoaStore.listen(this.onChange);
if (this.props.edition.coa) {
CoaActions.fetchOne(this.props.edition.coa);
}
else{
console.log('create coa');
CoaActions.create(this.props.edition);
}
},
componentWillUnmount() {
CoaStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
render() {
if (this.state.coa.url_safe) {
return (
<div>
<p className="text-center">
<Button bsSize="xsmall" href={this.state.coa.url_safe} target="_blank">
Download <Glyphicon glyph="cloud-download"/>
</Button>
<Link to="coa_verify">
<Button bsSize="xsmall">
Verify <Glyphicon glyph="check"/>
</Button>
</Link>
</p>
</div>
);
}
return (
<div className="text-center">
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
</div>);
}
});
export default Edition; export default Edition;

View File

@ -12,6 +12,7 @@ import Form from './ascribe_forms/form';
import Property from './ascribe_forms/property'; import Property from './ascribe_forms/property';
import apiUrls from '../constants/api_urls'; import apiUrls from '../constants/api_urls';
import AppConstants from '../constants/application_constants';
let LoginContainer = React.createClass({ let LoginContainer = React.createClass({
@ -65,7 +66,7 @@ let LoginForm = React.createClass({
Users on Stack Overflow claim this is a bug in chrome and should be fixed in the future. Users on Stack Overflow claim this is a bug in chrome and should be fixed in the future.
Until then, we redirect the HARD way, but reloading the whole page using window.location Until then, we redirect the HARD way, but reloading the whole page using window.location
*/ */
window.location = '/collection'; window.location = AppConstants.baseUrl + 'collection';
}, },
render() { render() {

View File

@ -2,8 +2,8 @@
import React from 'react'; import React from 'react';
import { getCookie } from '../utils/fetch_api_utils';
import AppConstants from '../constants/application_constants'; import AppConstants from '../constants/application_constants';
import fineUploader from 'fineUploader';
import Router from 'react-router'; import Router from 'react-router';
@ -19,6 +19,7 @@ import ReactS3FineUploader from './ascribe_uploader/react_s3_fine_uploader';
import DatePicker from 'react-datepicker/dist/react-datepicker'; import DatePicker from 'react-datepicker/dist/react-datepicker';
let RegisterPiece = React.createClass( { let RegisterPiece = React.createClass( {
mixins: [Router.Navigation], mixins: [Router.Navigation],
@ -135,61 +136,10 @@ let FileUploader = React.createClass({
url: apiUrls.blob_digitalworks url: apiUrls.blob_digitalworks
}} }}
handleChange={this.props.handleChange} handleChange={this.props.handleChange}
autoUpload={true}
debug={false}
objectProperties={{
acl: 'public-read',
bucket: 'ascribe0'
}}
request={{
endpoint: 'https://ascribe0.s3.amazonaws.com',
accessKey: 'AKIAIVCZJ33WSCBQ3QDA'
}}
signature={{
endpoint: AppConstants.serverUrl + 's3/signature/'
}}
uploadSuccess={{
params: {
isBrowserPreviewCapable: fineUploader.supportedFeatures.imagePreviews
}
}}
cors={{
expected: true
}}
chunking={{
enabled: true
}}
resume={{
enabled: true
}}
retry={{
enableAuto: false
}}
deleteFile={{
enabled: true,
method: 'DELETE',
endpoint: AppConstants.serverUrl + 's3/delete',
customHeaders: {
'X-CSRFToken': 'asdasd'
}
}}
validation={{ validation={{
itemLimit: 100000, itemLimit: 100000,
sizeLimit: '25000000000' sizeLimit: '25000000000'
}} }}/>
session={{
endpoint: null
}}
messages={{
unsupportedBrowser: '<h3>Upload is not functional in IE7 as IE7 has no support for CORS!</h3>'
}}
formatFileName={(name) => {// fix maybe
if (name !== undefined && name.length > 26) {
name = name.slice(0, 15) + '...' + name.slice(-15);
}
return name;
}}
multiple={true}/>
); );
} }
}); });

View File

@ -137,7 +137,7 @@ let SignupForm = React.createClass({
name='promo_code' name='promo_code'
label="Promocode"> label="Promocode">
<input <input
type="password" type="text"
placeholder="Enter a promocode here (Optional)"/> placeholder="Enter a promocode here (Optional)"/>
</Property> </Property>
<hr /> <hr />

View File

@ -6,6 +6,9 @@ let apiUrls = {
'applications': AppConstants.apiEndpoint + 'applications/', 'applications': AppConstants.apiEndpoint + 'applications/',
'application_token_refresh': AppConstants.apiEndpoint + 'applications/refresh_token/', 'application_token_refresh': AppConstants.apiEndpoint + 'applications/refresh_token/',
'blob_digitalworks': AppConstants.apiEndpoint + 'blob/digitalworks/', 'blob_digitalworks': AppConstants.apiEndpoint + 'blob/digitalworks/',
'coa': AppConstants.apiEndpoint + 'coa/${id}/',
'coa_create': AppConstants.apiEndpoint + 'coa/',
'coa_verify': AppConstants.apiEndpoint + 'coa/verify_coa/',
'edition': AppConstants.apiEndpoint + 'editions/${bitcoin_id}/', 'edition': AppConstants.apiEndpoint + 'editions/${bitcoin_id}/',
'edition_delete': AppConstants.apiEndpoint + 'editions/${edition_id}/', 'edition_delete': AppConstants.apiEndpoint + 'editions/${edition_id}/',
'edition_remove_from_collection': AppConstants.apiEndpoint + 'ownership/shares/${edition_id}/', 'edition_remove_from_collection': AppConstants.apiEndpoint + 'ownership/shares/${edition_id}/',
@ -20,6 +23,7 @@ let apiUrls = {
'ownership_loans_deny': AppConstants.apiEndpoint + 'ownership/loans/deny/', 'ownership_loans_deny': AppConstants.apiEndpoint + 'ownership/loans/deny/',
'ownership_shares': AppConstants.apiEndpoint + 'ownership/shares/', 'ownership_shares': AppConstants.apiEndpoint + 'ownership/shares/',
'ownership_transfers': AppConstants.apiEndpoint + 'ownership/transfers/', 'ownership_transfers': AppConstants.apiEndpoint + 'ownership/transfers/',
'ownership_transfers_withdraw': AppConstants.apiEndpoint + 'ownership/transfers/withdraw/',
'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/', 'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/',
'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/', 'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/',
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/', 'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',

View File

@ -0,0 +1,19 @@
'use strict';
import requests from '../utils/requests';
let CoaFetcher = {
/**
* Fetch one user from the API.
* If no arg is supplied, load the current user
*/
fetchOne(id) {
return requests.get('coa', {'id': id});
},
create(bitcoinId) {
console.log(bitcoinId);
return requests.post('coa_create', {body: {'bitcoin_id': bitcoinId}});
}
};
export default CoaFetcher;

View File

@ -12,6 +12,8 @@ import SignupContainer from './components/signup_container';
import PasswordResetContainer from './components/password_reset_container'; import PasswordResetContainer from './components/password_reset_container';
import SettingsContainer from './components/settings_container'; import SettingsContainer from './components/settings_container';
import CoaVerifyContainer from './components/coa_verify_container';
import AppConstants from './constants/application_constants'; import AppConstants from './constants/application_constants';
import RegisterPiece from './components/register_piece'; import RegisterPiece from './components/register_piece';
@ -28,6 +30,7 @@ let routes = (
<Route name="password_reset" path="password_reset" handler={PasswordResetContainer} /> <Route name="password_reset" path="password_reset" handler={PasswordResetContainer} />
<Route name="register_piece" path="register_piece" handler={RegisterPiece} /> <Route name="register_piece" path="register_piece" handler={RegisterPiece} />
<Route name="settings" path="settings" handler={SettingsContainer} /> <Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<Redirect from={baseUrl} to="login" /> <Redirect from={baseUrl} to="login" />
<Redirect from={baseUrl + '/'} to="login" /> <Redirect from={baseUrl + '/'} to="login" />

18
js/stores/coa_store.js Normal file
View File

@ -0,0 +1,18 @@
'use strict';
import alt from '../alt';
import CoaActions from '../actions/coa_actions';
class CoaStore {
constructor() {
this.coa = {};
this.bindActions(CoaActions);
}
onUpdateCoa(coa) {
this.coa = coa;
}
}
export default alt.createStore(CoaStore, 'CoaStore');

View File

@ -35,7 +35,6 @@
"devDependencies": { "devDependencies": {
"babel-eslint": "^3.1.11", "babel-eslint": "^3.1.11",
"babel-jest": "^5.2.0", "babel-jest": "^5.2.0",
"browserify-shim": "^3.8.9",
"jest-cli": "^0.4.0" "jest-cli": "^0.4.0"
}, },
"dependencies": { "dependencies": {
@ -44,6 +43,7 @@
"bootstrap-sass": "^3.3.4", "bootstrap-sass": "^3.3.4",
"browser-sync": "^2.7.5", "browser-sync": "^2.7.5",
"browserify": "^9.0.8", "browserify": "^9.0.8",
"browserify-shim": "^3.8.9",
"classnames": "^1.2.2", "classnames": "^1.2.2",
"compression": "^1.4.4", "compression": "^1.4.4",
"envify": "^3.4.0", "envify": "^3.4.0",

View File

@ -28,4 +28,20 @@
width:100%; width:100%;
margin-top: 1em; margin-top: 1em;
}
.coa-file-wrapper{
display: table;
height: 200px;
overflow: hidden;
margin: 0 auto;
width: 100%;
padding: 1em;
}
.coa-file {
display: table-cell;
vertical-align: middle;
border: 1px solid #CCC;
background-color: #F8F8F8;
} }

View File

@ -5,7 +5,8 @@
} }
.ascribe-textarea-editable:hover { .ascribe-textarea-editable:hover {
border: 1px solid #AAA; //border: 1px solid #AAA;;
border: none;
} }
.ascribe-pre{ .ascribe-pre{

View File

@ -32,6 +32,12 @@ body {
display: none; display: none;
} }
.no-margin{
margin: 0;
}
.no-padding{
padding: 0;
}
.navbar-default { .navbar-default {
border: none; border: none;
border-left:0; border-left:0;