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({ -