From 9e1a76a08e33825f977a3815c61652dbb8906423 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Mon, 22 Jun 2015 17:33:25 +0200 Subject: [PATCH 01/10] api settings complete --- gulpfile.js | 2 +- js/actions/application_actions.js | 34 +++++ js/components/ascribe_forms/form.js | 6 +- js/components/register_piece.js | 28 ++-- js/components/settings_container.js | 226 ++++++++++++++++++---------- js/constants/api_urls.js | 2 + js/fetchers/application_fetcher.js | 17 +++ js/stores/application_store.js | 18 +++ package.json | 2 +- sass/ascribe_settings.scss | 18 ++- 10 files changed, 251 insertions(+), 102 deletions(-) create mode 100644 js/actions/application_actions.js create mode 100644 js/fetchers/application_fetcher.js create mode 100644 js/stores/application_store.js diff --git a/gulpfile.js b/gulpfile.js index d40726a2..e570c2ff 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -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); }); diff --git a/js/actions/application_actions.js b/js/actions/application_actions.js new file mode 100644 index 00000000..33932ebd --- /dev/null +++ b/js/actions/application_actions.js @@ -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); diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index 403100c8..6cd8638a 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -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 = ( -
+

-

+

); } diff --git a/js/components/register_piece.js b/js/components/register_piece.js index 3a3520b5..1687fe3f 100644 --- a/js/components/register_piece.js +++ b/js/components/register_piece.js @@ -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( {
- +
); @@ -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({ }> + name='artist_name' + label="Artist Name"> + name='title' + label="Artwork title">
-
- Not an ascribe user? Sign up...
- Forgot my password? Rescue me... -
); } diff --git a/js/components/settings_container.js b/js/components/settings_container.js index b07c69c0..d6fc4bcc 100644 --- a/js/components/settings_container.js +++ b/js/components/settings_container.js @@ -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({
+
); } @@ -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 = ; if (this.state.currentUser.username) { - return ( - -
- - - - - - -
-
- ); - } - else { - return ( - + content = ( +
+ + + + + + +
+
); } + return ( + + {content} + + + ); } }); @@ -120,42 +125,39 @@ let BitcoinWalletSettings = React.createClass({ }, render() { - if (this.state.walletSettings.btc_public_key) { - return ( - -
- - - - - - -
-
- ); - } - else { - return ( - - ); + let content = ; + if (this.state.walletSettings.btc_public_key) { + content = ( +
+ + + + + + +
+
); } + return ( + + {content} + + ); } }); @@ -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 = ; + if (this.state.applications.length > 0) { + content = this.state.applications.map(function(app) { + return ( + +
+
+ {'Bearer ' + app.bearer_token.token} +
+
+ +
+
+
); + }, this); + content = ( +
+
+ {content} +
+
+
); + + } return ( -
-
Username: {this.props.currentUser.username}
-
Email: {this.props.currentUser.email}
-
+ +
+ + + +
+
+ {content} +
); } }); diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index 461ed453..e284b7b1 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -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}/', diff --git a/js/fetchers/application_fetcher.js b/js/fetchers/application_fetcher.js new file mode 100644 index 00000000..f87d76f7 --- /dev/null +++ b/js/fetchers/application_fetcher.js @@ -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; diff --git a/js/stores/application_store.js b/js/stores/application_store.js new file mode 100644 index 00000000..5eb89e24 --- /dev/null +++ b/js/stores/application_store.js @@ -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'); diff --git a/package.json b/package.json index 6c37fccc..8ca3e4fa 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/sass/ascribe_settings.scss b/sass/ascribe_settings.scss index 37a8c31e..85cfa926 100644 --- a/sass/ascribe_settings.scss +++ b/sass/ascribe_settings.scss @@ -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; From 02f8193743d408208fcdd7f4ad4df5e6d4d59971 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Mon, 22 Jun 2015 18:02:04 +0200 Subject: [PATCH 02/10] style tweaks --- js/components/ascribe_forms/form.js | 10 ++++++---- js/components/settings_container.js | 20 ++++++++------------ sass/ascribe_settings.scss | 11 +++++------ sass/ascribe_textarea.scss | 3 +++ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index 6cd8638a..b24b796b 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -102,10 +102,12 @@ let Form = React.createClass({ if (this.state.edited){ buttons = ( -

- - -

+
+

+ + +

+
); } diff --git a/js/components/settings_container.js b/js/components/settings_container.js index d6fc4bcc..bd2307e0 100644 --- a/js/components/settings_container.js +++ b/js/components/settings_container.js @@ -133,19 +133,13 @@ let BitcoinWalletSettings = React.createClass({ name='btc_public_key' label="Bitcoin public key" editable={false}> - +
{this.state.walletSettings.btc_public_key}
- +
{this.state.walletSettings.btc_root_address}

); @@ -204,7 +198,7 @@ let APISettings = React.createClass({ handleTokenRefresh: function(event){ let applicationName = event.target.getAttribute('data-id'); ApplicationActions.refreshApplicationToken(applicationName); - let notification = new GlobalNotificationModel('Token refreshed', 'success'); + let notification = new GlobalNotificationModel('Token refreshed', 'success', 2000); GlobalNotificationActions.appendGlobalNotification(notification); }, render() { @@ -235,9 +229,8 @@ let APISettings = React.createClass({
{content}
-
- ); - + + ); } return (
+
+                    Usage: curl <url> -H 'Authorization: Bearer <token>'
+                
{content}
); diff --git a/sass/ascribe_settings.scss b/sass/ascribe_settings.scss index 85cfa926..1cebf723 100644 --- a/sass/ascribe_settings.scss +++ b/sass/ascribe_settings.scss @@ -39,10 +39,7 @@ span { cursor: default; } - div { - color: #666; - } - input { + input, div, pre { cursor: default; color: #666; } @@ -60,8 +57,10 @@ cursor:pointer; - span { + input, div, span, pre { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + span { font-weight: normal; font-size: 0.9em; color: rgba(0,0,0,.7); @@ -79,7 +78,7 @@ } } - input { + input, pre { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 400; font-size: 1.1em; diff --git a/sass/ascribe_textarea.scss b/sass/ascribe_textarea.scss index f349628d..0e6d5ada 100644 --- a/sass/ascribe_textarea.scss +++ b/sass/ascribe_textarea.scss @@ -18,4 +18,7 @@ font-family: inherit; text-align: justify; background-color: white; + border: none; + padding: 0; + margin:0; } From 89884ced1fb8947fff8efe9c5c16df84e544be07 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Mon, 22 Jun 2015 23:32:41 +0200 Subject: [PATCH 03/10] edition detail updated with forms --- .../collapsible_paragraph.js | 32 ++- js/components/ascribe_forms/form.js | 3 + .../ascribe_forms/form_piece_extradata.js | 61 +++-- .../ascribe_forms/input_textarea_toggable.js | 46 +--- js/components/ascribe_forms/property.js | 18 +- js/components/edition.js | 240 ++++++++---------- js/components/header.js | 2 +- js/components/settings_container.js | 3 +- js/routes.js | 4 +- sass/ascribe_edition.scss | 24 +- sass/ascribe_settings.scss | 26 +- sass/ascribe_textarea.scss | 3 +- 12 files changed, 224 insertions(+), 238 deletions(-) diff --git a/js/components/ascribe_collapsible/collapsible_paragraph.js b/js/components/ascribe_collapsible/collapsible_paragraph.js index 5156c306..4c3a779f 100644 --- a/js/components/ascribe_collapsible/collapsible_paragraph.js +++ b/js/components/ascribe_collapsible/collapsible_paragraph.js @@ -18,6 +18,12 @@ const CollapsibleParagraph = React.createClass({ iconName: React.PropTypes.string }, + getDefaultProps() { + return { + show: true + }; + }, + mixins: [CollapsibleMixin], getCollapsibleDOMNode(){ @@ -35,19 +41,23 @@ const CollapsibleParagraph = React.createClass({ render() { let styles = this.getCollapsibleClassSet(); - let text = this.isExpanded() ? '-' : '+'; - return ( -
-
-
- {text} {this.props.title} -
-
- {this.props.children} + let text = this.isExpanded() ? '[hide]' : '[show]'; + if(this.props.show) { + return ( +
+
+
+ {this.props.title}{text} +
+
+ {this.props.children} +
-
- ); + ); + } else { + return null; + } } }); diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index b24b796b..3070717c 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -47,6 +47,9 @@ let Form = React.createClass({ }, 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; diff --git a/js/components/ascribe_forms/form_piece_extradata.js b/js/components/ascribe_forms/form_piece_extradata.js index 045c6adb..c2cebeb5 100644 --- a/js/components/ascribe_forms/form_piece_extradata.js +++ b/js/components/ascribe_forms/form_piece_extradata.js @@ -5,47 +5,58 @@ import React from 'react'; import requests from '../../utils/requests'; import apiUrls from '../../constants/api_urls'; -import FormMixin from '../../mixins/form_mixin'; +import Form from './form'; +import Property from './property'; import InputTextAreaToggable from './input_textarea_toggable'; - let PieceExtraDataForm = React.createClass({ - mixins: [FormMixin], - - url() { - return requests.prepareUrl(apiUrls.piece_extradata, {piece_id: this.props.editions[0].bitcoin_id}); + propTypes: { + edition: React.PropTypes.object, + handleSuccess: React.PropTypes.func, + name: React.PropTypes.string, + title: React.PropTypes.string, + editable: React.PropTypes.bool }, - - getFormData() { + getFormData(){ let extradata = {}; - extradata[this.props.name] = this.refs[this.props.name].state.value; + extradata[this.props.name] = this.refs.form.refs[this.props.name].state.value; return { - bitcoin_id: this.getBitcoinIds().join(), + bitcoin_id: this.props.edition.bitcoin_id, extradata: extradata }; }, - - renderForm() { - let defaultValue = this.props.editions[0].extra_data[this.props.name] || ''; + render() { + let defaultValue = this.props.edition.extra_data[this.props.name] || ''; if (defaultValue.length === 0 && !this.props.editable){ return null; } + let url = requests.prepareUrl(apiUrls.piece_extradata, {piece_id: this.props.edition.bitcoin_id}); return ( -
-
{this.props.title}
- - +
+ + + + +
+
); } }); + export default PieceExtraDataForm; diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js index 22e95fda..222a6e36 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -2,56 +2,29 @@ import React from 'react'; -import AlertMixin from '../../mixins/alert_mixin'; import TextareaAutosize from 'react-textarea-autosize'; -import Button from 'react-bootstrap/lib/Button'; let InputTextAreaToggable = React.createClass({ propTypes: { editable: React.PropTypes.bool.isRequired, - submitted: React.PropTypes.bool, rows: React.PropTypes.number.isRequired, - onSubmit: React.PropTypes.func.isRequired, required: React.PropTypes.string, defaultValue: React.PropTypes.string }, - mixins: [AlertMixin], - getInitialState() { return { - value: this.props.defaultValue, - edited: false, - alerts: null // needed in AlertMixin + value: this.props.defaultValue }; }, handleChange(event) { - this.setState({ - value: event.target.value, - edited: true - }); - }, - reset(){ - this.setState(this.getInitialState()); - }, - submit(){ - this.props.onSubmit(); - this.setState({edited: false}); + this.setState({value: event.target.value}); + this.props.onChange(event); }, render() { let className = 'form-control ascribe-textarea'; - let buttons = null; let textarea = null; - if (this.props.editable && this.state.edited){ - buttons = ( -
- - -
- ); - - } if (this.props.editable){ className = className + ' ascribe-textarea-editable'; textarea = ( @@ -61,21 +34,16 @@ let InputTextAreaToggable = React.createClass({ rows={this.props.rows} required={this.props.required} onChange={this.handleChange} - placeholder='Write something...' /> + onBlur={this.props.onBlur} + placeholder={this.props.placeholder} /> ); } else{ textarea =
{this.state.value}
; } - let alerts = (this.props.submitted) ? null : this.state.alerts; - return ( -
- {alerts} - {textarea} - {buttons} -
- ); + return textarea; } }); + export default InputTextAreaToggable; \ No newline at end of file diff --git a/js/components/ascribe_forms/property.js b/js/components/ascribe_forms/property.js index 6181dbc9..f0c445f3 100644 --- a/js/components/ascribe_forms/property.js +++ b/js/components/ascribe_forms/property.js @@ -8,7 +8,9 @@ import Tooltip from 'react-bootstrap/lib/Tooltip'; let Property = React.createClass({ propTypes: { + hidden: React.PropTypes.bool, editable: React.PropTypes.bool, + tooltip: React.PropTypes.element, label: React.PropTypes.string, value: React.PropTypes.oneOfType([ React.PropTypes.string, @@ -19,7 +21,8 @@ let Property = React.createClass({ getDefaultProps() { return { - editable: true + editable: true, + hidden: false }; }, @@ -38,8 +41,16 @@ let Property = React.createClass({ }); }, reset(){ + // maybe do reset by reload instead of frontend state? this.setState({value: this.state.initialValue}); - this.refs.input.getDOMNode().value = this.state.initialValue; + if (this.refs.input.state){ + // This is probably not the right way but easy fix + this.refs.input.state.value = this.state.initialValue; + } + else{ + this.refs.input.getDOMNode().value = this.state.initialValue; + } + }, handleChange(event) { @@ -74,6 +85,9 @@ let Property = React.createClass({ this.setState({errors: null}); }, getClassName() { + if(this.props.hidden){ + return 'is-hidden'; + } if(!this.props.editable){ return 'is-fixed'; } diff --git a/js/components/edition.js b/js/components/edition.js index 21469f22..34975699 100644 --- a/js/components/edition.js +++ b/js/components/edition.js @@ -2,19 +2,21 @@ import React from 'react'; +import Row from 'react-bootstrap/lib/Row'; +import Col from 'react-bootstrap/lib/Col'; +import Button from 'react-bootstrap/lib/Button'; +import Glyphicon from 'react-bootstrap/lib/Glyphicon'; + import UserActions from '../actions/user_actions'; import UserStore from '../stores/user_store'; import MediaPlayer from './ascribe_media/media_player'; -import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin'; -import Row from 'react-bootstrap/lib/Row'; -import Col from 'react-bootstrap/lib/Col'; -import Button from 'react-bootstrap/lib/Button'; -import Glyphicon from 'react-bootstrap/lib/Glyphicon'; +import CollapsibleParagraph from './ascribe_collapsible/collapsible_paragraph'; -import PersonalNoteForm from './ascribe_forms/form_note_personal'; -import EditionNoteForm from './ascribe_forms/form_note_edition'; +import Form from './ascribe_forms/form'; +import Property from './ascribe_forms/property'; +import InputTextAreaToggable from './ascribe_forms/input_textarea_toggable'; import PieceExtraDataForm from './ascribe_forms/form_piece_extradata'; import RequestActionForm from './ascribe_forms/form_request_action'; @@ -25,7 +27,8 @@ import AclButtonList from './ascribe_buttons/acl_button_list'; import GlobalNotificationModel from '../models/global_notification_model'; import GlobalNotificationActions from '../actions/global_notification_actions'; -import classNames from 'classnames'; +import requests from '../utils/requests'; +import apiUrls from '../constants/api_urls'; /** * This is the component that implements display-specific functionality @@ -92,64 +95,72 @@ let Edition = React.createClass({ - + -1 || this.props.edition.public_note)}> - - - -1 || this.props.edition.public_note}> - + - -1 || Object.keys(this.props.edition.extra_data).length > 0}> - + - 0}> - + - 0}> - + - 0}> - + - - - - - +
+ +
{bitcoinIdValue}
+
+ +
{hashOfArtwork}
+
+ +
{ownerAddress}
+
+
+
+ ); @@ -229,85 +240,6 @@ let EditionSummary = React.createClass({ } }); -let CollapsibleEditionDetails = React.createClass({ - propTypes: { - title: React.PropTypes.string, - children: React.PropTypes.oneOfType([ - React.PropTypes.object, - React.PropTypes.array - ]), - show: React.PropTypes.bool, - iconName: React.PropTypes.string - }, - - getDefaultProps() { - return { - show: true - }; - }, - - render() { - if(this.props.show) { - return ( -
- - {this.props.children} - -
- ); - } else { - return null; - } - } -}); - -const CollapsibleParagraph = React.createClass({ - - propTypes: { - title: React.PropTypes.string, - children: React.PropTypes.oneOfType([ - React.PropTypes.object, - React.PropTypes.array - ]), - iconName: React.PropTypes.string - }, - - mixins: [CollapsibleMixin], - - getCollapsibleDOMNode(){ - return React.findDOMNode(this.refs.panel); - }, - - getCollapsibleDimensionValue(){ - return React.findDOMNode(this.refs.panel).scrollHeight; - }, - - onHandleToggle(e){ - e.preventDefault(); - this.setState({expanded: !this.state.expanded}); - }, - - render() { - let styles = this.getCollapsibleClassSet(); - let text = this.isExpanded() ? '-' : '+'; - - let icon = this.props.iconName ? () : null; - - return ( -
-
- {text} {icon} {this.props.title} -
-
- {this.props.children} -
-
- ); - } -}); - let EditionDetailProperty = React.createClass({ propTypes: { @@ -372,6 +304,7 @@ let EditionDetailHistoryIterator = React.createClass({ let EditionPersonalNote = React.createClass({ propTypes: { edition: React.PropTypes.object, + currentUser: React.PropTypes.object, handleSuccess: React.PropTypes.func }, showNotification(){ @@ -379,21 +312,35 @@ let EditionPersonalNote = React.createClass({ let notification = new GlobalNotificationModel('Private note saved', 'success'); GlobalNotificationActions.appendGlobalNotification(notification); }, + render() { - return ( - - - - - - ); + if (this.props.currentUser.username && true || false) { + return ( +
+ + + + +
+
+ ); + } + return null; } }); - let EditionPublicEditionNote = React.createClass({ propTypes: { edition: React.PropTypes.object, @@ -405,16 +352,31 @@ let EditionPublicEditionNote = React.createClass({ GlobalNotificationActions.appendGlobalNotification(notification); }, render() { - return ( - - - -1} - handleSuccess={this.showNotification} - editions={[this.props.edition]} /> - - - ); + let isEditable = this.props.edition.acl.indexOf('edit') > -1; + if (this.props.edition.acl.indexOf('edit') > -1 || this.props.edition.public_note){ + return ( +
+ + + + +
+
+ ); + } + return null; } }); @@ -440,19 +402,19 @@ let EditionFurtherDetails = React.createClass({ title='Artist Contact Info' handleSuccess={this.showNotification} editable={editable} - editions={[this.props.edition]} /> + edition={this.props.edition} /> + edition={this.props.edition} /> + edition={this.props.edition} /> ); diff --git a/js/components/header.js b/js/components/header.js index 583802dd..4699972c 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -39,6 +39,7 @@ let Header = React.createClass({ handleLogout(){ UserActions.logoutCurrentUser(); Alt.flush(); + this.transitionTo('login'); }, onChange(state) { this.setState(state); @@ -71,7 +72,6 @@ let Header = React.createClass({ -