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:
parent
f836d4c2d4
commit
9e1a76a08e
@ -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);
|
||||
});
|
||||
|
||||
|
34
js/actions/application_actions.js
Normal file
34
js/actions/application_actions.js
Normal 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);
|
@ -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>
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -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? Sign up...<br/>
|
||||
Forgot my password? Rescue me...
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
@ -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,47 +58,48 @@ 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}>
|
||||
<Form
|
||||
url={apiUrls.users_username}
|
||||
handleSuccess={this.handleSuccess}>
|
||||
<Property
|
||||
name='username'
|
||||
label="Username">
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.currentUser.username}
|
||||
placeholder="Enter your username"
|
||||
required/>
|
||||
</Property>
|
||||
<Property
|
||||
name='email'
|
||||
label="Email"
|
||||
editable={false}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.currentUser.email}
|
||||
placeholder="Enter your username"
|
||||
required/>
|
||||
</Property>
|
||||
</Form>
|
||||
</CollapsibleParagraph>
|
||||
);
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
|
||||
content = (
|
||||
<Form
|
||||
url={apiUrls.users_username}
|
||||
handleSuccess={this.handleSuccess}>
|
||||
<Property
|
||||
name='username'
|
||||
label="Username">
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.currentUser.username}
|
||||
placeholder="Enter your username"
|
||||
required/>
|
||||
</Property>
|
||||
<Property
|
||||
name='email'
|
||||
label="Email"
|
||||
editable={false}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.currentUser.email}
|
||||
placeholder="Enter your username"
|
||||
required/>
|
||||
</Property>
|
||||
<hr />
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<CollapsibleParagraph
|
||||
title="Account"
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
{content}
|
||||
|
||||
</CollapsibleParagraph>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -120,42 +125,39 @@ let BitcoinWalletSettings = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
if (this.state.walletSettings.btc_public_key) {
|
||||
return (
|
||||
<CollapsibleParagraph
|
||||
title="Crypto Wallet"
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
<Form
|
||||
url={apiUrls.users_username}
|
||||
handleSuccess={this.handleSuccess}>
|
||||
<Property
|
||||
name='btc_public_key'
|
||||
label="Bitcoin public key"
|
||||
editable={false}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.walletSettings.btc_public_key}
|
||||
placeholder="Enter your username"
|
||||
required/>
|
||||
</Property>
|
||||
<Property
|
||||
name='btc_root_address'
|
||||
label="Root Address"
|
||||
editable={false}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.walletSettings.btc_root_address}/>
|
||||
</Property>
|
||||
</Form>
|
||||
</CollapsibleParagraph>
|
||||
);
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
|
||||
);
|
||||
let content = <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />;
|
||||
if (this.state.walletSettings.btc_public_key) {
|
||||
content = (
|
||||
<Form >
|
||||
<Property
|
||||
name='btc_public_key'
|
||||
label="Bitcoin public key"
|
||||
editable={false}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.walletSettings.btc_public_key}
|
||||
placeholder="Enter your username"
|
||||
required/>
|
||||
</Property>
|
||||
<Property
|
||||
name='btc_root_address'
|
||||
label="Root Address"
|
||||
editable={false}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.walletSettings.btc_root_address}/>
|
||||
</Property>
|
||||
<hr />
|
||||
</Form>);
|
||||
}
|
||||
return (
|
||||
<CollapsibleParagraph
|
||||
title="Crypto Wallet"
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
{content}
|
||||
</CollapsibleParagraph>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -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 (
|
||||
<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 (
|
||||
<div>
|
||||
<div>Username: {this.props.currentUser.username}</div>
|
||||
<div>Email: {this.props.currentUser.email}</div>
|
||||
</div>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -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}/',
|
||||
|
17
js/fetchers/application_fetcher.js
Normal file
17
js/fetchers/application_fetcher.js
Normal 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;
|
18
js/stores/application_store.js
Normal file
18
js/stores/application_store.js
Normal 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');
|
@ -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",
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user