1
0
mirror of https://github.com/ascribe/onion.git synced 2024-11-15 17:45:10 +01:00
onion/js/components/edition.js

400 lines
14 KiB
JavaScript
Raw Normal View History

'use strict';
import React from 'react';
2015-06-10 15:49:46 +02:00
2015-06-04 16:15:59 +02:00
import MediaPlayer from './ascribe_media/media_player';
2015-06-02 17:32:38 +02:00
2015-06-03 11:56:49 +02:00
import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin';
2015-06-04 16:15:59 +02:00
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
2015-06-03 11:56:49 +02:00
import Button from 'react-bootstrap/lib/Button';
2015-06-04 16:15:59 +02:00
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
2015-06-09 13:29:22 +02:00
import PersonalNoteForm from './ascribe_forms/form_note_personal';
2015-06-09 17:24:06 +02:00
import PieceExtraDataForm from './ascribe_forms/form_piece_extradata';
import RequestActionForm from './ascribe_forms/form_request_action';
2015-05-27 09:34:49 +02:00
import EditionActions from '../actions/edition_actions';
2015-06-05 11:40:49 +02:00
import AclButtonList from './ascribe_buttons/acl_button_list';
2015-06-09 17:24:06 +02:00
import GlobalNotificationModel from '../models/global_notification_model';
import GlobalNotificationActions from '../actions/global_notification_actions';
2015-06-05 14:22:02 +02:00
import classNames from 'classnames';
2015-05-26 10:41:41 +02:00
/**
2015-05-26 10:52:20 +02:00
* This is the component that implements display-specific functionality
2015-05-26 10:41:41 +02:00
*/
2015-05-26 13:48:46 +02:00
let Edition = React.createClass({
propTypes: {
edition: React.PropTypes.object,
2015-06-09 13:29:22 +02:00
loadEdition: React.PropTypes.func
},
2015-05-26 13:33:35 +02:00
render() {
2015-05-27 17:34:15 +02:00
let thumbnail = this.props.edition.thumbnail;
let mimetype = this.props.edition.digital_work.mime;
2015-06-03 16:53:27 +02:00
let extraData = null;
if (this.props.edition.digital_work.encoding_urls) {
2015-06-05 16:20:28 +02:00
extraData = this.props.edition.digital_work.encoding_urls.map(e => { return { url: e.url, type: e.label }; });
2015-06-03 16:53:27 +02:00
}
2015-05-27 17:34:15 +02:00
2015-06-05 14:22:02 +02:00
let bitcoinIdValue = (
<a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.bitcoin_id}>{this.props.edition.bitcoin_id}</a>
);
2015-06-09 13:29:22 +02:00
let hashOfArtwork = (
2015-06-05 14:22:02 +02:00
<a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.hash_as_address}>{this.props.edition.hash_as_address}</a>
);
2015-06-09 13:29:22 +02:00
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>
);
2015-05-26 13:33:35 +02:00
return (
2015-06-04 16:15:59 +02:00
<Row>
2015-06-05 16:20:28 +02:00
<Col md={6}>
2015-06-04 16:15:59 +02:00
<MediaPlayer mimetype={mimetype}
2015-06-03 16:53:27 +02:00
preview={thumbnail}
url={this.props.edition.digital_work.url}
extraData={extraData} />
2015-06-04 16:15:59 +02:00
<p className="text-center">
<Button bsSize="xsmall" href={this.props.edition.digital_work.url} target="_blank">
Download <Glyphicon glyph="cloud-download" />
</Button>
</p>
</Col>
2015-06-05 16:20:28 +02:00
<Col md={6} className="ascribe-edition-details">
2015-05-26 14:58:11 +02:00
<EditionHeader edition={this.props.edition}/>
2015-06-05 14:22:02 +02:00
<EditionSummary
edition={this.props.edition} />
2015-06-05 16:20:28 +02:00
<CollapsibleEditionDetails
title="Personal Note"
iconName="pencil">
2015-06-09 13:29:22 +02:00
<EditionPersonalNote
handleSuccess={this.props.loadEdition}
edition={this.props.edition}/>
2015-06-05 16:20:28 +02:00
</CollapsibleEditionDetails>
<CollapsibleEditionDetails
title="Further Details">
<EditionFurtherDetails
handleSuccess={this.props.loadEdition}
edition={this.props.edition}/>
</CollapsibleEditionDetails>
2015-06-05 14:22:02 +02:00
<CollapsibleEditionDetails
title="Provenance/Ownership History"
show={this.props.edition.ownership_history && this.props.edition.ownership_history.length > 0}>
2015-06-05 16:20:28 +02:00
<EditionDetailHistoryIterator
2015-06-05 14:22:02 +02:00
history={this.props.edition.ownership_history} />
</CollapsibleEditionDetails>
<CollapsibleEditionDetails
title="Consignment History"
show={this.props.edition.consign_history && this.props.edition.consign_history.length > 0}>
<EditionDetailHistoryIterator
history={this.props.edition.consign_history} />
</CollapsibleEditionDetails>
2015-06-05 14:22:02 +02:00
<CollapsibleEditionDetails
title="Loan History"
show={this.props.edition.loan_history && this.props.edition.loan_history.length > 0}>
2015-06-05 16:20:28 +02:00
<EditionDetailHistoryIterator
2015-06-05 14:22:02 +02:00
history={this.props.edition.loan_history} />
</CollapsibleEditionDetails>
<CollapsibleEditionDetails
title="SPOOL Details">
<EditionDetailProperty
label="Artwork ID"
value={bitcoinIdValue} />
<EditionDetailProperty
label="Hash of Artwork, title, etc"
value={hashOfArtwork} />
<EditionDetailProperty
label="Owned by SPOOL address"
2015-06-09 13:29:22 +02:00
value={ownerAddress} />
2015-06-05 14:22:02 +02:00
</CollapsibleEditionDetails>
2015-06-04 16:15:59 +02:00
</Col>
</Row>
2015-05-26 13:33:35 +02:00
);
}
});
2015-05-26 13:48:46 +02:00
let EditionHeader = React.createClass({
propTypes: {
edition: React.PropTypes.object
},
2015-05-26 13:33:35 +02:00
render() {
var titleHtml = <div className="ascribe-detail-title">{this.props.edition.title}</div>;
2015-05-26 13:33:35 +02:00
return (
<div className="ascribe-detail-header">
2015-06-05 14:22:02 +02:00
<EditionDetailProperty label="TITLE" value={titleHtml} />
<EditionDetailProperty label="BY" value={this.props.edition.artist_name} />
<EditionDetailProperty label="DATE" value={ this.props.edition.date_created.slice(0, 4) } />
2015-05-26 13:33:35 +02:00
<hr/>
</div>
);
}
});
2015-06-05 11:40:49 +02:00
2015-06-03 11:56:49 +02:00
let EditionSummary = React.createClass({
propTypes: {
edition: React.PropTypes.object
},
2015-06-02 11:38:18 +02:00
handleSuccess(){
EditionActions.fetchOne(this.props.edition.id);
},
showNotification(response){
this.handleSuccess();
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
},
2015-05-26 13:33:35 +02:00
render() {
let status = null;
if (this.props.edition.status.length > 0){
status = <EditionDetailProperty label="STATUS" value={ this.props.edition.status.join().replace(/_/, ' ') } />;
}
let actions = null;
if (this.props.edition.request_action){
actions = (
<RequestActionForm
editions={ [this.props.edition] }
handleSuccess={this.showNotification}/>);
}
else {
actions = (
2015-06-05 16:20:28 +02:00
<Row>
<Col md={12}>
<AclButtonList
className="pull-left"
availableAcls={this.props.edition.acl}
editions={[this.props.edition]}
handleSuccess={this.handleSuccess} />
</Col>
</Row>);
}
return (
<div className="ascribe-detail-header">
<EditionDetailProperty label="EDITION"
value={this.props.edition.edition_number + ' of ' + this.props.edition.num_editions} />
<EditionDetailProperty label="ID" value={ this.props.edition.bitcoin_id } />
<EditionDetailProperty label="OWNER" value={ this.props.edition.owner } />
{status}
<br/>
{actions}
2015-05-26 15:31:28 +02:00
<hr/>
</div>
);
2015-05-27 09:34:49 +02:00
2015-05-26 15:31:28 +02:00
}
});
2015-06-05 14:22:02 +02:00
let CollapsibleEditionDetails = React.createClass({
propTypes: {
title: React.PropTypes.string,
children: React.PropTypes.oneOfType([
React.PropTypes.object,
React.PropTypes.array
]),
2015-06-05 16:20:28 +02:00
show: React.PropTypes.bool,
iconName: React.PropTypes.string
2015-06-03 11:56:49 +02:00
},
2015-06-05 14:22:02 +02:00
getDefaultProps() {
return {
show: true
};
},
2015-06-03 11:56:49 +02:00
render() {
2015-06-05 14:22:02 +02:00
if(this.props.show) {
return (
<div className="ascribe-detail-header">
2015-06-05 16:20:28 +02:00
<CollapsibleParagraph
title={this.props.title}
iconName={this.props.iconName}>
2015-06-05 14:22:02 +02:00
{this.props.children}
</CollapsibleParagraph>
</div>
);
} else {
return null;
}
}
});
const CollapsibleParagraph = React.createClass({
propTypes: {
title: React.PropTypes.string,
children: React.PropTypes.oneOfType([
React.PropTypes.object,
React.PropTypes.array
2015-06-05 16:20:28 +02:00
]),
iconName: React.PropTypes.string
2015-06-05 14:22:02 +02:00
},
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});
},
2015-06-05 16:20:28 +02:00
render() {
2015-06-05 14:22:02 +02:00
let styles = this.getCollapsibleClassSet();
2015-06-05 16:20:28 +02:00
let text = this.isExpanded() ? '-' : '+';
let icon = this.props.iconName ? (<Glyphicon style={{fontSize: '.75em'}} glyph={this.props.iconName} />) : null;
2015-06-03 11:56:49 +02:00
return (
2015-06-05 14:22:02 +02:00
<div className="ascribe-edition-collapsible-wrapper">
<div onClick={this.onHandleToggle}>
2015-06-05 16:20:28 +02:00
<span>{text} {icon} {this.props.title} </span>
2015-06-05 14:22:02 +02:00
</div>
<div ref='panel' className={classNames(styles) + ' ascribe-edition-collapible-content'}>
{this.props.children}
</div>
2015-06-03 11:56:49 +02:00
</div>
);
}
});
2015-05-26 15:31:28 +02:00
let EditionDetailProperty = React.createClass({
propTypes: {
label: React.PropTypes.string,
2015-06-05 11:32:10 +02:00
value: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.element
2015-06-05 14:22:02 +02:00
]),
separator: React.PropTypes.string,
labelClassName: React.PropTypes.string,
valueClassName: React.PropTypes.string
},
getDefaultProps() {
return {
separator: ':',
labelClassName: 'col-xs-5 col-sm-4 col-md-3 col-lg-3',
valueClassName: 'col-xs-7 col-sm-8 col-md-9 col-lg-9'
2015-06-05 14:22:02 +02:00
};
},
2015-05-26 15:31:28 +02:00
render() {
return (
<div className="row ascribe-detail-property">
<div className="row-same-height">
2015-06-05 14:22:02 +02:00
<div className={this.props.labelClassName + ' col-xs-height col-bottom'}>
2015-06-09 13:29:22 +02:00
<div>{ this.props.label + this.props.separator}</div>
2015-05-26 13:33:35 +02:00
</div>
2015-06-05 14:22:02 +02:00
<div className={this.props.valueClassName + ' col-xs-height col-bottom'}>
2015-05-26 15:31:28 +02:00
<div>{ this.props.value }</div>
2015-05-26 13:33:35 +02:00
</div>
</div>
</div>
);
}
});
2015-06-05 14:22:02 +02:00
let EditionDetailHistoryIterator = React.createClass({
propTypes: {
history: React.PropTypes.array
},
render() {
return (
<div>
{this.props.history.map((historicalEvent, i) => {
return (
<EditionDetailProperty
key={i}
label={historicalEvent[0]}
value={historicalEvent[1]}
labelClassName="col-xs-4 col-sm-4 col-md-4 col-lg-4"
valueClassName="col-xs-8 col-sm-8 col-md-8 col-lg-8"
separator="" />
);
})}
</div>
);
}
});
2015-06-05 16:20:28 +02:00
let EditionPersonalNote = React.createClass({
propTypes: {
edition: React.PropTypes.object,
handleSuccess: React.PropTypes.func
2015-06-05 16:20:28 +02:00
},
2015-06-09 17:24:06 +02:00
showNotification(){
this.props.handleSuccess();
let notification = new GlobalNotificationModel('Note saved', 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
},
render() {
return (
<Row>
<Col md={12} className="ascribe-edition-personal-note">
<PersonalNoteForm
2015-06-09 17:24:06 +02:00
handleSuccess={this.showNotification}
editions={[this.props.edition]} />
</Col>
</Row>
);
}
});
let EditionFurtherDetails = React.createClass({
propTypes: {
edition: React.PropTypes.object,
handleSuccess: React.PropTypes.func
2015-06-05 16:20:28 +02:00
},
2015-06-10 15:49:46 +02:00
showNotification(){
this.props.handleSuccess();
let notification = new GlobalNotificationModel('Details updated', 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
},
2015-06-05 16:20:28 +02:00
render() {
return (
<Row>
<Col md={12} className="ascribe-edition-personal-note">
2015-06-09 17:24:06 +02:00
<PieceExtraDataForm
name='artist_contact_info'
title='Artist Contact Info'
2015-06-10 15:49:46 +02:00
handleSuccess={this.showNotification}
2015-06-09 17:24:06 +02:00
editions={[this.props.edition]} />
<PieceExtraDataForm
name='display_instructions'
title='Display Instructions'
2015-06-10 15:49:46 +02:00
handleSuccess={this.showNotification}
2015-06-09 17:24:06 +02:00
editions={[this.props.edition]} />
<PieceExtraDataForm
name='technology_details'
title='Technology Details'
2015-06-10 15:49:46 +02:00
handleSuccess={this.showNotification}
2015-06-09 13:29:22 +02:00
editions={[this.props.edition]} />
2015-06-05 16:20:28 +02:00
</Col>
</Row>
);
}
});
2015-05-27 09:34:49 +02:00
export default Edition;