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:
parent
f836d4c2d4
commit
9e1a76a08e
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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.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>
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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? Sign up...<br/>
|
|
||||||
Forgot my password? Rescue me...
|
|
||||||
</div>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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}/',
|
||||||
|
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-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",
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user