1
0
mirror of https://github.com/ascribe/onion.git synced 2024-11-16 01:55:07 +01:00

api settings complete

This commit is contained in:
ddejongh 2015-06-22 17:33:25 +02:00
parent f836d4c2d4
commit 9e1a76a08e
10 changed files with 251 additions and 102 deletions

View File

@ -69,7 +69,7 @@ gulp.task('js:build', function() {
bundle(false); bundle(false);
}); });
gulp.task('serve', ['browser-sync', 'run-server', 'sass:watch', 'copy'], function() { gulp.task('serve', ['browser-sync', 'run-server', 'lint:watch', 'sass:build', 'sass:watch', 'copy'], function() {
bundle(true); bundle(true);
}); });

View File

@ -0,0 +1,34 @@
'use strict';
import alt from '../alt';
import ApplicationFetcher from '../fetchers/application_fetcher';
class ApplicationActions {
constructor() {
this.generateActions(
'updateApplications'
);
}
fetchApplication() {
ApplicationFetcher.fetch()
.then((res) => {
this.actions.updateApplications(res.applications);
})
.catch((err) => {
console.log(err);
});
}
refreshApplicationToken(applicationName) {
ApplicationFetcher.refreshToken(applicationName)
.then((res) => {
this.actions.updateApplications(res.applications);
})
.catch((err) => {
console.log(err);
});
}
}
export default alt.createActions(ApplicationActions);

View File

@ -66,7 +66,7 @@ let Form = React.createClass({
this.refs[ref].handleSuccess(); this.refs[ref].handleSuccess();
} }
} }
this.setState({edited: false}); this.setState({edited: false, submitted: false});
}, },
handleError(err){ handleError(err){
if (err.json) { if (err.json) {
@ -102,10 +102,10 @@ let Form = React.createClass({
if (this.state.edited){ if (this.state.edited){
buttons = ( buttons = (
<div className="pull-right"> <p className="pull-right">
<Button className="ascribe-btn" type="submit">Save</Button> <Button className="ascribe-btn" type="submit">Save</Button>
<Button className="ascribe-btn" onClick={this.reset}>Cancel</Button> <Button className="ascribe-btn" onClick={this.reset}>Cancel</Button>
</div> </p>
); );
} }

View File

@ -17,6 +17,8 @@ import apiUrls from '../constants/api_urls';
import ReactS3FineUploader from 'ReactS3FineUploader'; import ReactS3FineUploader from 'ReactS3FineUploader';
import DatePicker from 'react-datepicker/dist/react-datepicker';
let RegisterPiece = React.createClass( { let RegisterPiece = React.createClass( {
render() { render() {
@ -26,7 +28,7 @@ let RegisterPiece = React.createClass( {
<FileUploader /> <FileUploader />
</div> </div>
<div className="col-md-6"> <div className="col-md-6">
<LoginForm /> <RegisterPieceForm />
</div> </div>
</div> </div>
); );
@ -99,7 +101,7 @@ let FileUploader = React.createClass( {
} }
}); });
let LoginForm = React.createClass({ let RegisterPieceForm = React.createClass({
mixins: [Router.Navigation], mixins: [Router.Navigation],
@ -124,28 +126,22 @@ let LoginForm = React.createClass({
</button> </button>
}> }>
<Property <Property
name='email' name='artist_name'
label="Email"> label="Artist Name">
<input <input
type="email" type="text"
placeholder="Enter your email" placeholder="The name of the creator"
autoComplete="on"
required/> required/>
</Property> </Property>
<Property <Property
name='password' name='title'
label="Password"> label="Artwork title">
<input <input
type="password" type="text"
placeholder="Enter your password" placeholder="The title of the artwork"
autoComplete="on"
required/> required/>
</Property> </Property>
<hr /> <hr />
<div className="ascribe-login-text">
Not an ascribe user&#63; Sign up...<br/>
Forgot my password&#63; Rescue me...
</div>
</Form> </Form>
); );
} }

View File

@ -9,6 +9,9 @@ import UserStore from '../stores/user_store';
import WalletSettingsActions from '../actions/wallet_settings_actions'; import WalletSettingsActions from '../actions/wallet_settings_actions';
import WalletSettingsStore from '../stores/wallet_settings_store'; import WalletSettingsStore from '../stores/wallet_settings_store';
import ApplicationActions from '../actions/application_actions';
import ApplicationStore from '../stores/application_store';
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';
@ -28,6 +31,7 @@ let SettingsContainer = React.createClass({
<div> <div>
<AccountSettings /> <AccountSettings />
<BitcoinWalletSettings /> <BitcoinWalletSettings />
<APISettings />
</div> </div>
); );
} }
@ -54,16 +58,13 @@ let AccountSettings = React.createClass({
handleSuccess(){ handleSuccess(){
UserActions.fetchCurrentUser(); UserActions.fetchCurrentUser();
let notification = new GlobalNotificationModel('username succesfully updated', 'success', 10000); let notification = new GlobalNotificationModel('username succesfully updated', 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification); GlobalNotificationActions.appendGlobalNotification(notification);
}, },
render() { render() {
let content = <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />;
if (this.state.currentUser.username) { if (this.state.currentUser.username) {
return ( content = (
<CollapsibleParagraph
title="Account"
show={true}
defaultExpanded={true}>
<Form <Form
url={apiUrls.users_username} url={apiUrls.users_username}
handleSuccess={this.handleSuccess}> handleSuccess={this.handleSuccess}>
@ -86,16 +87,20 @@ let AccountSettings = React.createClass({
placeholder="Enter your username" placeholder="Enter your username"
required/> required/>
</Property> </Property>
<hr />
</Form> </Form>
);
}
return (
<CollapsibleParagraph
title="Account"
show={true}
defaultExpanded={true}>
{content}
</CollapsibleParagraph> </CollapsibleParagraph>
); );
} }
else {
return (
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
);
}
}
}); });
@ -120,15 +125,10 @@ let BitcoinWalletSettings = React.createClass({
}, },
render() { render() {
let content = <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />;
if (this.state.walletSettings.btc_public_key) { if (this.state.walletSettings.btc_public_key) {
return ( content = (
<CollapsibleParagraph <Form >
title="Crypto Wallet"
show={true}
defaultExpanded={true}>
<Form
url={apiUrls.users_username}
handleSuccess={this.handleSuccess}>
<Property <Property
name='btc_public_key' name='btc_public_key'
label="Bitcoin public key" label="Bitcoin public key"
@ -147,16 +147,18 @@ let BitcoinWalletSettings = React.createClass({
type="text" type="text"
defaultValue={this.state.walletSettings.btc_root_address}/> defaultValue={this.state.walletSettings.btc_root_address}/>
</Property> </Property>
</Form> <hr />
</Form>);
}
return (
<CollapsibleParagraph
title="Crypto Wallet"
show={true}
defaultExpanded={true}>
{content}
</CollapsibleParagraph> </CollapsibleParagraph>
); );
} }
else {
return (
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
);
}
}
}); });
let ContractSettings = React.createClass({ let ContractSettings = React.createClass({
@ -177,18 +179,86 @@ let ContractSettings = React.createClass({
}); });
let APISettings = React.createClass({ let APISettings = React.createClass({
getInitialState() {
propTypes: { return ApplicationStore.getState();
currentUser: React.PropTypes.object
}, },
render() { componentDidMount() {
ApplicationStore.listen(this.onChange);
ApplicationActions.fetchApplication();
},
componentWillUnmount() {
ApplicationStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
handleCreateSuccess: function(){
ApplicationActions.fetchApplication();
let notification = new GlobalNotificationModel('Application successfully created', 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
handleTokenRefresh: function(event){
let applicationName = event.target.getAttribute('data-id');
ApplicationActions.refreshApplicationToken(applicationName);
let notification = new GlobalNotificationModel('Token refreshed', 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
},
render() {
let content = <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />;
if (this.state.applications.length > 0) {
content = this.state.applications.map(function(app) {
return ( return (
<div> <Property
<div>Username: {this.props.currentUser.username}</div> name={app.name}
<div>Email: {this.props.currentUser.email}</div> label={app.name}>
<div className="row-same-height">
<div className="col-xs-6 col-xs-height col-middle">
{'Bearer ' + app.bearer_token.token}
</div> </div>
<div className="col-xs-6 col-xs-height">
<button
className="btn btn-default btn-sm"
onClick={this.handleTokenRefresh}
data-id={app.name}>
REFRESH
</button>
</div>
</div>
</Property>);
}, this);
content = (
<div>
<Form>
{content}
<hr />
</Form>
</div>);
}
return (
<CollapsibleParagraph
title="API Integration"
show={true}
defaultExpanded={true}>
<Form
url={apiUrls.applications}
handleSuccess={this.handleCreateSuccess}>
<Property
name='name'
label='Application Name'>
<input
type="text"
placeholder="Enter the name of your app"
required/>
</Property>
<hr />
</Form>
{content}
</CollapsibleParagraph>
); );
} }
}); });

View File

@ -3,6 +3,8 @@
import AppConstants from './application_constants'; import AppConstants from './application_constants';
let apiUrls = { let apiUrls = {
'applications': AppConstants.apiEndpoint + 'applications/',
'application_token_refresh': AppConstants.apiEndpoint + 'applications/refresh_token/',
'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}/',

View File

@ -0,0 +1,17 @@
'use strict';
import requests from '../utils/requests';
let ApplicationFetcher = {
/**
* Fetch the registered applications of a user from the API.
*/
fetch() {
return requests.get('applications');
},
refreshToken(applicationName) {
return requests.post('application_token_refresh', { body: {'name': applicationName}});
}
};
export default ApplicationFetcher;

View File

@ -0,0 +1,18 @@
'use strict';
import alt from '../alt';
import ApplicationActions from '../actions/application_actions';
class ApplicationStore {
constructor() {
this.applications = {};
this.bindActions(ApplicationActions);
}
onUpdateApplications(applications) {
this.applications = applications;
}
}
export default alt.createStore(ApplicationStore, 'ApplicationStore');

View File

@ -60,7 +60,7 @@
"gulp-notify": "^2.2.0", "gulp-notify": "^2.2.0",
"gulp-sass": "^2.0.1", "gulp-sass": "^2.0.1",
"gulp-sourcemaps": "^1.5.2", "gulp-sourcemaps": "^1.5.2",
"gulp-template": "^3.0.0", "gulp-template": "~3.0.0",
"gulp-uglify": "^1.2.0", "gulp-uglify": "^1.2.0",
"gulp-util": "^3.0.4", "gulp-util": "^3.0.4",
"harmonize": "^1.4.2", "harmonize": "^1.4.2",

View File

@ -25,9 +25,6 @@
color: rgba(169, 68, 66, 1); color: rgba(169, 68, 66, 1);
font-size: 0.9em; font-size: 0.9em;
margin-right: 1em; margin-right: 1em;
}
span {
} }
input { input {
color: #666; color: #666;
@ -42,6 +39,9 @@
span { span {
cursor: default; cursor: default;
} }
div {
color: #666;
}
input { input {
cursor: default; cursor: default;
color: #666; color: #666;
@ -67,6 +67,18 @@
color: rgba(0,0,0,.7); color: rgba(0,0,0,.7);
} }
div {
margin-top: 10px;
div {
padding-left: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: normal;
font-size: 1.1em;
cursor: default;
color: rgba(0, 0, 0, .7);
}
}
input { input {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 400; font-weight: 400;