mirror of
https://github.com/ascribe/onion.git
synced 2024-12-23 01:39:36 +01:00
toggable textarea
This commit is contained in:
parent
b49f3fe9f2
commit
6563bf97b0
@ -45,7 +45,7 @@ gulp.task('build', function() {
|
|||||||
bundle(false);
|
bundle(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('serve', ['browser-sync', 'lint:watch', 'sass', 'sass:watch', 'copy'], function() {
|
gulp.task('serve', ['browser-sync', 'sass', 'sass:watch', 'copy'], function() {
|
||||||
bundle(true);
|
bundle(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ let ButtonSubmitOrClose = React.createClass({
|
|||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
|
43
js/components/ascribe_forms/form_note_personal.js
Normal file
43
js/components/ascribe_forms/form_note_personal.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import apiUrls from '../../constants/api_urls';
|
||||||
|
import FormMixin from '../../mixins/form_mixin';
|
||||||
|
|
||||||
|
import InputTextAreaToggable from './input_textarea_toggable';
|
||||||
|
|
||||||
|
|
||||||
|
let PersonalNoteForm = React.createClass({
|
||||||
|
mixins: [FormMixin],
|
||||||
|
|
||||||
|
url() {
|
||||||
|
return apiUrls.note_notes;
|
||||||
|
},
|
||||||
|
|
||||||
|
getFormData() {
|
||||||
|
return {
|
||||||
|
bitcoin_id: this.getBitcoinIds().join(),
|
||||||
|
note: this.refs.personalNote.state.value
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
renderForm() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form id="personal_note_content" role="form" key="personal_note_content">
|
||||||
|
<InputTextAreaToggable
|
||||||
|
ref="personalNote"
|
||||||
|
className="form-control"
|
||||||
|
defaultValue={this.props.editions[0].note_from_user}
|
||||||
|
rows={3}
|
||||||
|
editable={true}
|
||||||
|
required=""
|
||||||
|
onSubmit={this.submit}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default PersonalNoteForm;
|
72
js/components/ascribe_forms/input_textarea_toggable.js
Normal file
72
js/components/ascribe_forms/input_textarea_toggable.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
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({
|
||||||
|
|
||||||
|
mixins: [AlertMixin],
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
value: this.props.defaultValue,
|
||||||
|
edited: false,
|
||||||
|
alerts: null // needed in AlertMixin
|
||||||
|
};
|
||||||
|
},
|
||||||
|
handleChange(event) {
|
||||||
|
this.setState({
|
||||||
|
value: event.target.value,
|
||||||
|
edited: true
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reset(){
|
||||||
|
this.setState(this.getInitialState());
|
||||||
|
},
|
||||||
|
submit(){
|
||||||
|
this.props.onSubmit();
|
||||||
|
this.setState({edited: false});
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
let className = 'form-control ascribe-textarea';
|
||||||
|
let buttons = null;
|
||||||
|
let textarea = null;
|
||||||
|
if (this.props.editable && this.state.edited){
|
||||||
|
buttons = (
|
||||||
|
<div className="pull-right">
|
||||||
|
<Button className="ascribe-btn" onClick={this.submit}>Save</Button>
|
||||||
|
<Button className="ascribe-btn" onClick={this.reset}>Cancel</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (this.props.editable){
|
||||||
|
className = className + ' ascribe-textarea-editable';
|
||||||
|
textarea = (
|
||||||
|
<TextareaAutosize
|
||||||
|
className={className}
|
||||||
|
value={this.state.value}
|
||||||
|
rows={this.props.rows}
|
||||||
|
required={this.props.required}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
placeholder='Write something...' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
textarea = <pre className="ascribe-pre">{this.state.value}</pre>;
|
||||||
|
}
|
||||||
|
let alerts = (this.props.submitted) ? null : this.state.alerts;
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
{alerts}
|
||||||
|
{textarea}
|
||||||
|
{buttons}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default InputTextAreaToggable;
|
@ -8,7 +8,8 @@ import Row from 'react-bootstrap/lib/Row';
|
|||||||
import Col from 'react-bootstrap/lib/Col';
|
import Col from 'react-bootstrap/lib/Col';
|
||||||
import Button from 'react-bootstrap/lib/Button';
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||||
import TextareaAutosize from 'react-textarea-autosize';
|
|
||||||
|
import PersonalNoteForm from './ascribe_forms/form_note_personal';
|
||||||
|
|
||||||
import EditionActions from '../actions/edition_actions';
|
import EditionActions from '../actions/edition_actions';
|
||||||
import AclButtonList from './ascribe_buttons/acl_button_list';
|
import AclButtonList from './ascribe_buttons/acl_button_list';
|
||||||
@ -23,7 +24,7 @@ let Edition = React.createClass({
|
|||||||
edition: React.PropTypes.object,
|
edition: React.PropTypes.object,
|
||||||
currentUser: React.PropTypes.object,
|
currentUser: React.PropTypes.object,
|
||||||
deleteEdition: React.PropTypes.func,
|
deleteEdition: React.PropTypes.func,
|
||||||
savePersonalNote: React.PropTypes.func
|
loadEdition: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -43,6 +44,10 @@ let Edition = React.createClass({
|
|||||||
<a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.hash_as_address}>{this.props.edition.hash_as_address}</a>
|
<a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.hash_as_address}>{this.props.edition.hash_as_address}</a>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let ownerAddress = (
|
||||||
|
<a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.btc_owner_address_noprefix}>{this.props.edition.btc_owner_address_noprefix}</a>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={6}>
|
<Col md={6}>
|
||||||
@ -65,7 +70,8 @@ let Edition = React.createClass({
|
|||||||
title="Personal Note"
|
title="Personal Note"
|
||||||
iconName="pencil">
|
iconName="pencil">
|
||||||
<EditionPersonalNote
|
<EditionPersonalNote
|
||||||
savePersonalNote={this.props.savePersonalNote}/>
|
handleSuccess={this.props.loadEdition}
|
||||||
|
edition={this.props.edition}/>
|
||||||
</CollapsibleEditionDetails>
|
</CollapsibleEditionDetails>
|
||||||
|
|
||||||
<CollapsibleEditionDetails
|
<CollapsibleEditionDetails
|
||||||
@ -92,7 +98,7 @@ let Edition = React.createClass({
|
|||||||
value={hashOfArtwork} />
|
value={hashOfArtwork} />
|
||||||
<EditionDetailProperty
|
<EditionDetailProperty
|
||||||
label="Owned by SPOOL address"
|
label="Owned by SPOOL address"
|
||||||
value="MISSING IN /editions/<id> RESOURCE!" />
|
value={ownerAddress} />
|
||||||
</CollapsibleEditionDetails>
|
</CollapsibleEditionDetails>
|
||||||
|
|
||||||
<CollapsibleEditionDetails
|
<CollapsibleEditionDetails
|
||||||
@ -267,7 +273,7 @@ let EditionDetailProperty = React.createClass({
|
|||||||
<div className="row ascribe-detail-property">
|
<div className="row ascribe-detail-property">
|
||||||
<div className="row-same-height">
|
<div className="row-same-height">
|
||||||
<div className={this.props.labelClassName + ' col-xs-height col-bottom'}>
|
<div className={this.props.labelClassName + ' col-xs-height col-bottom'}>
|
||||||
<div>{ this.props.label }{this.props.separator}</div>
|
<div>{ this.props.label + this.props.separator}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={this.props.valueClassName + ' col-xs-height col-bottom'}>
|
<div className={this.props.valueClassName + ' col-xs-height col-bottom'}>
|
||||||
<div>{ this.props.value }</div>
|
<div>{ this.props.value }</div>
|
||||||
@ -304,7 +310,7 @@ let EditionDetailHistoryIterator = React.createClass({
|
|||||||
|
|
||||||
let EditionPersonalNote = React.createClass({
|
let EditionPersonalNote = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
savePersonalNote: React.PropTypes.func
|
edition: React.PropTypes.object
|
||||||
},
|
},
|
||||||
|
|
||||||
prepareSavePersonalNote() {
|
prepareSavePersonalNote() {
|
||||||
@ -316,14 +322,9 @@ let EditionPersonalNote = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={12} className="ascribe-edition-personal-note">
|
<Col md={12} className="ascribe-edition-personal-note">
|
||||||
<TextareaAutosize
|
<PersonalNoteForm
|
||||||
ref="personalNote"
|
handleSuccess={this.props.handleSuccess}
|
||||||
className="form-control"
|
editions={[this.props.edition]} />
|
||||||
rows={3}
|
|
||||||
placeholder='Write something...' />
|
|
||||||
<Button
|
|
||||||
onClick={this.prepareSavePersonalNote}
|
|
||||||
className="pull-right">Save</Button>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
@ -4,6 +4,9 @@ import React from 'react';
|
|||||||
|
|
||||||
import { mergeOptions } from '../utils/general_utils';
|
import { mergeOptions } from '../utils/general_utils';
|
||||||
|
|
||||||
|
import apiUrls from '../constants/api_urls';
|
||||||
|
import fetch from '../utils/fetch';
|
||||||
|
|
||||||
import EditionActions from '../actions/edition_actions';
|
import EditionActions from '../actions/edition_actions';
|
||||||
import EditionStore from '../stores/edition_store';
|
import EditionStore from '../stores/edition_store';
|
||||||
import UserActions from '../actions/user_actions';
|
import UserActions from '../actions/user_actions';
|
||||||
@ -40,9 +43,8 @@ let EditionContainer = React.createClass({
|
|||||||
// Delete Edition from server
|
// Delete Edition from server
|
||||||
},
|
},
|
||||||
|
|
||||||
savePersonalNote(note) {
|
loadEdition() {
|
||||||
console.log(note);
|
EditionActions.fetchOne(this.props.params.editionId);
|
||||||
// Save personalNote to server
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -52,7 +54,7 @@ let EditionContainer = React.createClass({
|
|||||||
edition={this.state.edition}
|
edition={this.state.edition}
|
||||||
currentUser={this.state.currentUser}
|
currentUser={this.state.currentUser}
|
||||||
deleteEdition={this.deleteEdition}
|
deleteEdition={this.deleteEdition}
|
||||||
savePersonalNote={this.savePersonalNote}/>
|
loadEdition={this.loadEdition}/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
@ -13,7 +13,8 @@ let apiUrls = {
|
|||||||
'ownership_loans': AppConstants.baseUrl + 'ownership/loans/',
|
'ownership_loans': AppConstants.baseUrl + 'ownership/loans/',
|
||||||
'ownership_consigns': AppConstants.baseUrl + 'ownership/consigns/',
|
'ownership_consigns': AppConstants.baseUrl + 'ownership/consigns/',
|
||||||
'ownership_unconsigns': AppConstants.baseUrl + 'ownership/unconsigns/',
|
'ownership_unconsigns': AppConstants.baseUrl + 'ownership/unconsigns/',
|
||||||
'ownership_unconsigns_request': AppConstants.baseUrl + 'ownership/unconsigns/request/'
|
'ownership_unconsigns_request': AppConstants.baseUrl + 'ownership/unconsigns/request/',
|
||||||
|
'note_notes': AppConstants.baseUrl + 'note/notes/'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default apiUrls;
|
export default apiUrls;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let constants = {
|
let constants = {
|
||||||
//'baseUrl': 'http://localhost:8000/api/',
|
'baseUrl': 'http://localhost:8000/api/',
|
||||||
'baseUrl': 'http://staging.ascribe.io/api/',
|
//'baseUrl': 'http://staging.ascribe.io/api/',
|
||||||
'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000
|
'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000
|
||||||
'aclList': ['edit', 'consign', 'transfer', 'loan', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
|
'aclList': ['edit', 'consign', 'transfer', 'loan', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
|
||||||
};
|
};
|
||||||
|
@ -14,22 +14,32 @@ export const FormMixin = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
submit(e) {
|
submit(e) {
|
||||||
|
if (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
}
|
||||||
this.setState({submitted: true});
|
this.setState({submitted: true});
|
||||||
this.clearErrors();
|
this.clearErrors();
|
||||||
fetch
|
fetch
|
||||||
.post(this.url(), { body: this.getFormData() })
|
.post(this.url(), { body: this.getFormData() })
|
||||||
.then(() => this.props.handleSuccess())
|
.then(() => this.handleSuccess() )
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
},
|
},
|
||||||
|
|
||||||
clearErrors(){
|
clearErrors(){
|
||||||
for (var ref in this.refs){
|
for (var ref in this.refs){
|
||||||
|
if ('clearAlerts' in this.refs[ref]){
|
||||||
this.refs[ref].clearAlerts();
|
this.refs[ref].clearAlerts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
this.setState({errors: []});
|
this.setState({errors: []});
|
||||||
},
|
},
|
||||||
|
handleSuccess(){
|
||||||
|
if ('handleSuccess' in this.props){
|
||||||
|
this.props.handleSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
handleError(err){
|
handleError(err){
|
||||||
if (err.json) {
|
if (err.json) {
|
||||||
for (var input in err.json.errors){
|
for (var input in err.json.errors){
|
||||||
|
21
sass/ascribe_textarea.scss
Normal file
21
sass/ascribe_textarea.scss
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.ascribe-textarea {
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ascribe-textarea-editable:hover {
|
||||||
|
border: 1px solid #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ascribe-pre{
|
||||||
|
word-break: break-word;
|
||||||
|
/* white-space: pre-wrap; */
|
||||||
|
white-space: -moz-pre-wrap;
|
||||||
|
white-space: -pre-wrap;
|
||||||
|
white-space: -o-pre-wrap;
|
||||||
|
/* word-wrap: break-word; */
|
||||||
|
font-family: inherit;
|
||||||
|
text-align: justify;
|
||||||
|
background-color: white;
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
@import 'ascribe_piece_list_bulk_modal';
|
@import 'ascribe_piece_list_bulk_modal';
|
||||||
@import 'ascribe_piece_list_toolbar';
|
@import 'ascribe_piece_list_toolbar';
|
||||||
@import 'ascribe_edition';
|
@import 'ascribe_edition';
|
||||||
|
@import 'ascribe_textarea';
|
||||||
@import 'ascribe_media_player';
|
@import 'ascribe_media_player';
|
||||||
@import 'offset_right';
|
@import 'offset_right';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user