1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 09:23:13 +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);
});
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);
});

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.setState({edited: false});
this.setState({edited: false, submitted: false});
},
handleError(err){
if (err.json) {
@ -102,10 +102,10 @@ let Form = React.createClass({
if (this.state.edited){
buttons = (
<div className="pull-right">
<p className="pull-right">
<Button className="ascribe-btn" type="submit">Save</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 DatePicker from 'react-datepicker/dist/react-datepicker';
let RegisterPiece = React.createClass( {
render() {
@ -26,7 +28,7 @@ let RegisterPiece = React.createClass( {
<FileUploader />
</div>
<div className="col-md-6">
<LoginForm />
<RegisterPieceForm />
</div>
</div>
);
@ -99,7 +101,7 @@ let FileUploader = React.createClass( {
}
});
let LoginForm = React.createClass({
let RegisterPieceForm = React.createClass({
mixins: [Router.Navigation],
@ -124,28 +126,22 @@ let LoginForm = React.createClass({
</button>
}>
<Property
name='email'
label="Email">
name='artist_name'
label="Artist Name">
<input
type="email"
placeholder="Enter your email"
autoComplete="on"
type="text"
placeholder="The name of the creator"
required/>
</Property>
<Property
name='password'
label="Password">
name='title'
label="Artwork title">
<input
type="password"
placeholder="Enter your password"
autoComplete="on"
type="text"
placeholder="The title of the artwork"
required/>
</Property>
<hr />
<div className="ascribe-login-text">
Not an ascribe user&#63; Sign up...<br/>
Forgot my password&#63; Rescue me...
</div>
</Form>
);
}

View File

@ -9,6 +9,9 @@ import UserStore from '../stores/user_store';
import WalletSettingsActions from '../actions/wallet_settings_actions';
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 GlobalNotificationActions from '../actions/global_notification_actions';
@ -28,6 +31,7 @@ let SettingsContainer = React.createClass({
<div>
<AccountSettings />
<BitcoinWalletSettings />
<APISettings />
</div>
);
}
@ -54,16 +58,13 @@ let AccountSettings = React.createClass({
handleSuccess(){
UserActions.fetchCurrentUser();
let notification = new GlobalNotificationModel('username succesfully updated', 'success', 10000);
let notification = new GlobalNotificationModel('username succesfully updated', 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
render() {
let content = <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />;
if (this.state.currentUser.username) {
return (
<CollapsibleParagraph
title="Account"
show={true}
defaultExpanded={true}>
content = (
<Form
url={apiUrls.users_username}
handleSuccess={this.handleSuccess}>
@ -86,16 +87,20 @@ let AccountSettings = React.createClass({
placeholder="Enter your username"
required/>
</Property>
<hr />
</Form>
);
}
return (
<CollapsibleParagraph
title="Account"
show={true}
defaultExpanded={true}>
{content}
</CollapsibleParagraph>
);
}
else {
return (
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
);
}
}
});
@ -120,15 +125,10 @@ let BitcoinWalletSettings = React.createClass({
},
render() {
let content = <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />;
if (this.state.walletSettings.btc_public_key) {
return (
<CollapsibleParagraph
title="Crypto Wallet"
show={true}
defaultExpanded={true}>
<Form
url={apiUrls.users_username}
handleSuccess={this.handleSuccess}>
content = (
<Form >
<Property
name='btc_public_key'
label="Bitcoin public key"
@ -147,16 +147,18 @@ let BitcoinWalletSettings = React.createClass({
type="text"
defaultValue={this.state.walletSettings.btc_root_address}/>
</Property>
</Form>
<hr />
</Form>);
}
return (
<CollapsibleParagraph
title="Crypto Wallet"
show={true}
defaultExpanded={true}>
{content}
</CollapsibleParagraph>
);
}
else {
return (
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
);
}
}
});
let ContractSettings = React.createClass({
@ -177,18 +179,86 @@ let ContractSettings = React.createClass({
});
let APISettings = React.createClass({
propTypes: {
currentUser: React.PropTypes.object
getInitialState() {
return ApplicationStore.getState();
},
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 (
<div>
<div>Username: {this.props.currentUser.username}</div>
<div>Email: {this.props.currentUser.email}</div>
<Property
name={app.name}
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 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';
let apiUrls = {
'applications': AppConstants.apiEndpoint + 'applications/',
'application_token_refresh': AppConstants.apiEndpoint + 'applications/refresh_token/',
'edition': AppConstants.apiEndpoint + 'editions/${bitcoin_id}/',
'edition_delete': AppConstants.apiEndpoint + 'editions/${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-sass": "^2.0.1",
"gulp-sourcemaps": "^1.5.2",
"gulp-template": "^3.0.0",
"gulp-template": "~3.0.0",
"gulp-uglify": "^1.2.0",
"gulp-util": "^3.0.4",
"harmonize": "^1.4.2",

View File

@ -25,9 +25,6 @@
color: rgba(169, 68, 66, 1);
font-size: 0.9em;
margin-right: 1em;
}
span {
}
input {
color: #666;
@ -42,6 +39,9 @@
span {
cursor: default;
}
div {
color: #666;
}
input {
cursor: default;
color: #666;
@ -67,6 +67,18 @@
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 {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 400;