From 95f6c087060d796fd35f96576a521a0d91611eb1 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Tue, 23 Jun 2015 16:02:48 +0200 Subject: [PATCH] localization --- js/components/ascribe_forms/form.js | 153 +++++++++++++++ js/components/settings_container.js | 279 ++++++++++++++++++++++++++++ js/routes.js | 1 - sass/ascribe_settings.scss | 123 ++++++++++++ 4 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 js/components/ascribe_forms/form.js create mode 100644 js/components/settings_container.js create mode 100644 sass/ascribe_settings.scss diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js new file mode 100644 index 00000000..b8ff1539 --- /dev/null +++ b/js/components/ascribe_forms/form.js @@ -0,0 +1,153 @@ +'use strict'; + +import React from 'react'; +import ReactAddons from 'react/addons'; + +import Button from 'react-bootstrap/lib/Button'; + +import requests from '../../utils/requests'; +import AlertDismissable from './alert'; + +let Form = React.createClass({ + propTypes: { + url: React.PropTypes.string, + handleSuccess: React.PropTypes.func, + getFormData: React.PropTypes.func, + children: React.PropTypes.oneOfType([ + React.PropTypes.object, + React.PropTypes.array + ]) + }, + + getInitialState() { + return { + edited: false, + submitted: false, + errors: [] + }; + }, + reset(){ + for (let ref in this.refs){ + if (typeof this.refs[ref].reset === 'function'){ + this.refs[ref].reset(); + } + } + }, + submit(event){ + if (event) { + event.preventDefault(); + } + this.setState({submitted: true}); + this.clearErrors(); + let action = (this.httpVerb && this.httpVerb()) || 'post'; + this[action](); + }, + post(){ + requests + .post(this.props.url, { body: this.getFormData() }) + .then(this.handleSuccess) + .catch(this.handleError); + }, + + getFormData(){ + if ('getFormData' in this.props){ + return this.props.getFormData(); + } + let data = {}; + for (let ref in this.refs){ + data[this.refs[ref].props.name] = this.refs[ref].state.value; + } + return data; + }, + + handleChangeChild(){ + this.setState({edited: true}); + }, + handleSuccess(response){ + if ('handleSuccess' in this.props){ + this.props.handleSuccess(response); + } + for (var ref in this.refs){ + if ('handleSuccess' in this.refs[ref]){ + this.refs[ref].handleSuccess(); + } + } + this.setState({edited: false, submitted: false}); + }, + handleError(err){ + if (err.json) { + for (var input in err.json.errors){ + if (this.refs && this.refs[input] && this.refs[input].state) { + this.refs[input].setErrors( err.json.errors[input]); + } else { + this.setState({errors: this.state.errors.concat(err.json.errors[input])}); + } + } + } + else { + this.setState({errors: ['Something went wrong, please try again later']}); + } + this.setState({submitted: false}); + }, + clearErrors(){ + for (var ref in this.refs){ + if ('clearErrors' in this.refs[ref]){ + this.refs[ref].clearErrors(); + } + } + this.setState({errors: []}); + }, + getButtons() { + if (this.state.submitted){ + return this.props.spinner; + } + if (this.props.buttons){ + return this.props.buttons; + } + let buttons = null; + + if (this.state.edited){ + buttons = ( +
+

+ + +

+
+ ); + + } + return buttons; + }, + getErrors() { + let errors = null; + if (this.state.errors.length > 0){ + errors = this.state.errors.map((error) => { + return ; + }); + } + return errors; + }, + renderChildren() { + return ReactAddons.Children.map(this.props.children, (child) => { + return ReactAddons.addons.cloneWithProps(child, { + handleChange: this.handleChangeChild, + ref: child.props.name + }); + }); + }, + render() { + + return ( +
+ {this.getErrors()} + {this.renderChildren()} + {this.getButtons()} +
+ + ); + } +}); + + +export default Form; \ No newline at end of file diff --git a/js/components/settings_container.js b/js/components/settings_container.js new file mode 100644 index 00000000..5f5ed777 --- /dev/null +++ b/js/components/settings_container.js @@ -0,0 +1,279 @@ +'use strict'; + +import React from 'react'; +import Router from 'react-router'; + +import UserActions from '../actions/user_actions'; +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'; + +import CollapsibleParagraph from './ascribe_collapsible/collapsible_paragraph'; +import Form from './ascribe_forms/form'; +import Property from './ascribe_forms/property'; + +import apiUrls from '../constants/api_urls'; +import AppConstants from '../constants/application_constants'; + + +let SettingsContainer = React.createClass({ + mixins: [Router.Navigation], + + render() { + return ( +
+ + + +
+ ); + } +}); + + +let AccountSettings = React.createClass({ + getInitialState() { + return UserStore.getState(); + }, + + componentDidMount() { + UserStore.listen(this.onChange); + UserActions.fetchCurrentUser(); + }, + + componentWillUnmount() { + UserStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + handleSuccess(){ + UserActions.fetchCurrentUser(); + let notification = new GlobalNotificationModel('username succesfully updated', 'success', 5000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + render() { + let content = ; + if (this.state.currentUser.username) { + content = ( +
+ + + + + + +
+
+ ); + } + return ( + + {content} +
+ + + +
+
+
+ ); + } +}); + + + +let BitcoinWalletSettings = React.createClass({ + + getInitialState() { + return WalletSettingsStore.getState(); + }, + + componentDidMount() { + WalletSettingsStore.listen(this.onChange); + WalletSettingsActions.fetchWalletSettings(); + }, + + componentWillUnmount() { + WalletSettingsStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + render() { + let content = ; + if (this.state.walletSettings.btc_public_key) { + content = ( +
+ +
{this.state.walletSettings.btc_public_key}
+
+ +
{this.state.walletSettings.btc_root_address}
+
+
+
); + } + return ( + + {content} + + ); + } +}); + +let ContractSettings = React.createClass({ + + propTypes: { + currentUser: React.PropTypes.object + }, + + render() { + + return ( +
+
Username: {this.props.currentUser.username}
+
Email: {this.props.currentUser.email}
+
+ ); + } +}); + +let APISettings = React.createClass({ + getInitialState() { + return ApplicationStore.getState(); + }, + + 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', 2000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + render() { + let content = ; + if (this.state.applications.length > -1) { + content = this.state.applications.map(function(app) { + return ( + +
+
+ {'Bearer ' + app.bearer_token.token} +
+
+ +
+
+
); + }, this); + content = ( +
+
+ {content} +
+
+
); + } + return ( + +
+ + + +
+
+
+                    Usage: curl <url> -H 'Authorization: Bearer <token>'
+                
+ {content} +
+ ); + } +}); + +export default SettingsContainer; \ No newline at end of file diff --git a/js/routes.js b/js/routes.js index ab515462..f749e4f0 100644 --- a/js/routes.js +++ b/js/routes.js @@ -7,7 +7,6 @@ import EditionContainer from './components/edition_container'; let Route = Router.Route; - let routes = ( diff --git a/sass/ascribe_settings.scss b/sass/ascribe_settings.scss new file mode 100644 index 00000000..41c4eb85 --- /dev/null +++ b/sass/ascribe_settings.scss @@ -0,0 +1,123 @@ + +.ascribe-settings-wrapper { + width: 100%; + text-align: center; + padding-bottom: 1em; + + background-color: white; + + border-left: 3px solid rgba(0,0,0,0); + + &div:last-of-type { + border-bottom: 1px solid rgba(0,0,0,.2); + } + &:hover{ + border-left: 3px solid rgba(2, 182, 163, 0.4); + } +} + +.is-hidden{ + display: none; +} + +.is-focused { + background-color: rgba(2, 182, 163, 0.05); + border-left: 3px solid rgba(2, 182, 163, 1)!important; +} + +.is-error { + background-color: rgba(169, 68, 66, 0.05); + border-left: 3px solid rgba(169, 68, 66, 1); + div { + span { + color: rgba(169, 68, 66, 1); + font-size: 0.9em; + margin-right: 1em; + } + input, textarea { + color: #666; + } + } + + &:hover{ + border-left: 3px solid rgba(169, 68, 66, 1); + } +} + +.is-fixed { + cursor: default; + div { + cursor: default; + span { + cursor: default; + } + input, div, pre, textarea { + cursor: default; + color: #666; + } + } +} + + + +.ascribe-settings-property { + display: inline-block; + width: 100%; + text-align: left; + border-top: 1px solid rgba(0,0,0,.2); + + padding-top: 1em; + padding-left: 1.5em; + + cursor:pointer; + + input, div, span, pre, textarea, select { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + span { + font-weight: normal; + font-size: 0.9em; + 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, pre, textarea, select { + font-weight: 400; + font-size: 1.1em; + width:100%; + margin-top: .5em; + border: 0; + background-color: rgba(0,0,0,0); + color: #38BAAD; + padding-left: 0; + + &:focus { + border:0; + outline:0; + box-shadow: none; + } + + &::selection { + color: white; + background-color: rgba(0,0,0,1); + } + + } + + textarea{ + color: #666; + margin-top: 1em; + padding: 0; + } +}