mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 09:23:13 +01:00
solve merge conflicts
This commit is contained in:
commit
7910384d99
@ -105,7 +105,7 @@ gulp.task('sass:build', function () {
|
||||
});
|
||||
|
||||
gulp.task('sass:watch', function () {
|
||||
gulp.watch('./sass/**/*.scss', ['sass']);
|
||||
gulp.watch('./sass/**/*.scss', ['sass:build']);
|
||||
});
|
||||
|
||||
gulp.task('copy', function () {
|
||||
|
@ -7,6 +7,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="//brick.a.ssl.fastly.net/Source+Sans+Pro:400,600,700,900">
|
||||
<link rel="stylesheet" href="<%= BASE_URL %>static/css/main.css">
|
||||
<link rel="stylesheet" href="<%= BASE_URL %>static/css/maps/main.css.map">
|
||||
<script>
|
||||
window.BASE_URL = '<%= BASE_URL %>';
|
||||
window.API_ENDPOINT = '<%= API_ENDPOINT %>';
|
||||
|
@ -9,7 +9,9 @@ class EditionListActions {
|
||||
this.generateActions(
|
||||
'updateEditionList',
|
||||
'selectEdition',
|
||||
'clearAllEditionSelections'
|
||||
'clearAllEditionSelections',
|
||||
'closeAllEditionLists',
|
||||
'toggleEditionList'
|
||||
);
|
||||
}
|
||||
|
||||
@ -19,19 +21,24 @@ class EditionListActions {
|
||||
orderAsc = true;
|
||||
}
|
||||
|
||||
EditionListFetcher
|
||||
.fetch(pieceId, orderBy, orderAsc)
|
||||
.then((res) => {
|
||||
this.actions.updateEditionList({
|
||||
'editionListOfPiece': res.editions,
|
||||
pieceId,
|
||||
orderBy,
|
||||
orderAsc
|
||||
return new Promise((resolve, reject) => {
|
||||
EditionListFetcher
|
||||
.fetch(pieceId, orderBy, orderAsc)
|
||||
.then((res) => {
|
||||
this.actions.updateEditionList({
|
||||
'editionListOfPiece': res.editions,
|
||||
pieceId,
|
||||
orderBy,
|
||||
orderAsc
|
||||
});
|
||||
resolve(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
console.log(err);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,7 @@ import PieceListFetcher from '../fetchers/piece_list_fetcher';
|
||||
class PieceListActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
'updatePieceList',
|
||||
'showEditionList',
|
||||
'closeAllEditionLists'
|
||||
'updatePieceList'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let Link = Router.Link;
|
||||
|
||||
let AccordionListItem = React.createClass({
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
|
@ -13,7 +13,6 @@ let AccordionListItemTable = React.createClass({
|
||||
parentId: React.PropTypes.number,
|
||||
itemList: React.PropTypes.array,
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
numOfTableItems: React.PropTypes.number,
|
||||
show: React.PropTypes.bool,
|
||||
changeOrder: React.PropTypes.func,
|
||||
orderBy: React.PropTypes.string,
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import EditionListStore from '../../stores/edition_list_store';
|
||||
import EditionListActions from '../../actions/edition_list_actions';
|
||||
@ -19,15 +18,11 @@ import TableItemAclFiltered from '../ascribe_table/table_item_acl_filtered';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let Link = Router.Link;
|
||||
|
||||
let AccordionListItemTableEditions = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
parentId: React.PropTypes.number,
|
||||
numOfEditions: React.PropTypes.number,
|
||||
show: React.PropTypes.bool
|
||||
parentId: React.PropTypes.number
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -64,8 +59,13 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
},
|
||||
|
||||
toggleTable() {
|
||||
PieceListActions.showEditionList(this.props.parentId);
|
||||
EditionListActions.fetchEditionList(this.props.parentId);
|
||||
let isEditionListOpen = this.state.isEditionListOpenForPieceId[this.props.parentId] ? this.state.isEditionListOpenForPieceId[this.props.parentId].show : false;
|
||||
if(isEditionListOpen) {
|
||||
EditionListActions.toggleEditionList(this.props.parentId);
|
||||
} else {
|
||||
EditionListActions.toggleEditionList(this.props.parentId);
|
||||
EditionListActions.fetchEditionList(this.props.parentId);
|
||||
}
|
||||
},
|
||||
|
||||
changeEditionListOrder(orderBy, orderAsc) {
|
||||
@ -77,6 +77,7 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
let allEditionsCount = 0;
|
||||
let orderBy;
|
||||
let orderAsc;
|
||||
let show;
|
||||
|
||||
// here we need to check if all editions of a specific
|
||||
// piece are already defined. Otherwise .length will throw an error and we'll not
|
||||
@ -88,7 +89,11 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
orderAsc = this.state.editionList[this.props.parentId].orderAsc;
|
||||
}
|
||||
|
||||
let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id', PieceListActions.closeAllEditionLists);
|
||||
if(this.props.parentId in this.state.isEditionListOpenForPieceId) {
|
||||
show = this.state.isEditionListOpenForPieceId[this.props.parentId].show;
|
||||
}
|
||||
|
||||
let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id');
|
||||
|
||||
let columnList = [
|
||||
new ColumnModel(
|
||||
@ -111,10 +116,10 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
new ColumnModel(
|
||||
(item) => {
|
||||
return {
|
||||
'content': item.edition_number
|
||||
'content': item.edition_number + ' of ' + item.num_editions
|
||||
}; },
|
||||
'edition_number',
|
||||
'#',
|
||||
'Edition',
|
||||
TableItemText,
|
||||
1,
|
||||
true,
|
||||
@ -153,16 +158,14 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
parentId={this.props.parentId}
|
||||
itemList={this.state.editionList[this.props.parentId]}
|
||||
columnList={columnList}
|
||||
numOfTableItems={this.props.numOfEditions}
|
||||
show={this.props.show}
|
||||
show={show}
|
||||
orderBy={orderBy}
|
||||
orderAsc={orderAsc}
|
||||
changeOrder={this.changeEditionListOrder}>
|
||||
<AccordionListItemTableToggle
|
||||
className="ascribe-accordion-list-table-toggle"
|
||||
onClick={this.toggleTable}
|
||||
show={this.props.show}
|
||||
numOfTableItems={this.props.numOfEditions} />
|
||||
show={show} />
|
||||
</AccordionListItemTable>
|
||||
|
||||
</div>
|
||||
|
@ -6,8 +6,7 @@ let AccordionListItemTableToggle = React.createClass({
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
onClick: React.PropTypes.func,
|
||||
show: React.PropTypes.bool,
|
||||
numOfTableItems: React.PropTypes.number
|
||||
show: React.PropTypes.bool
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -15,7 +14,7 @@ let AccordionListItemTableToggle = React.createClass({
|
||||
<span
|
||||
className={this.props.className}
|
||||
onClick={this.props.onClick}>
|
||||
{this.props.show ? 'Hide all ' + this.props.numOfTableItems + ' Editions' : 'Show all ' + this.props.numOfTableItems + ' Editions'}
|
||||
{this.props.show ? 'Hide all Editions' : 'Show all Editions'}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -3,12 +3,16 @@
|
||||
import React from 'react';
|
||||
|
||||
import ConsignForm from '../ascribe_forms/form_consign';
|
||||
import UnConsignForm from '../ascribe_forms/form_unconsign';
|
||||
import TransferForm from '../ascribe_forms/form_transfer';
|
||||
import LoanForm from '../ascribe_forms/form_loan';
|
||||
import ShareForm from '../ascribe_forms/form_share_email';
|
||||
import ModalWrapper from '../ascribe_modal/modal_wrapper';
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
let AclButton = React.createClass({
|
||||
propTypes: {
|
||||
action: React.PropTypes.oneOf(AppConstants.aclList).isRequired,
|
||||
@ -23,31 +27,47 @@ let AclButton = React.createClass({
|
||||
return {
|
||||
title: 'Consign artwork',
|
||||
tooltip: 'Have someone else sell the artwork',
|
||||
form: <ConsignForm />
|
||||
form: <ConsignForm currentUser={ this.props.currentUser } editions={ this.props.editions }/>,
|
||||
handleSuccess: this.showNotification
|
||||
};
|
||||
}
|
||||
else if (this.props.action === 'transfer') {
|
||||
if (this.props.action === 'unconsign'){
|
||||
return {
|
||||
title: 'Unconsign artwork',
|
||||
tooltip: 'Have the owner manage his sales again',
|
||||
form: <UnConsignForm currentUser={ this.props.currentUser } editions={ this.props.editions }/>,
|
||||
handleSuccess: this.showNotification
|
||||
};
|
||||
}else if (this.props.action === 'transfer') {
|
||||
return {
|
||||
title: 'Transfer artwork',
|
||||
tooltip: 'Transfer the ownership of the artwork',
|
||||
form: <TransferForm />
|
||||
form: <TransferForm currentUser={ this.props.currentUser } editions={ this.props.editions }/>,
|
||||
handleSuccess: this.showNotification
|
||||
};
|
||||
}
|
||||
else if (this.props.action === 'loan'){
|
||||
return {
|
||||
title: 'Loan artwork',
|
||||
tooltip: 'Loan your artwork for a limited period of time',
|
||||
form: <LoanForm />
|
||||
form: <LoanForm currentUser={ this.props.currentUser } editions={ this.props.editions }/>,
|
||||
handleSuccess: this.showNotification
|
||||
};
|
||||
}
|
||||
else if (this.props.action === 'share'){
|
||||
return {
|
||||
title: 'Share artwork',
|
||||
tooltip: 'Share the artwork',
|
||||
form: <ShareForm />
|
||||
form: <ShareForm currentUser={ this.props.currentUser } editions={ this.props.editions }/>,
|
||||
handleSuccess: this.showNotification
|
||||
};
|
||||
}
|
||||
},
|
||||
showNotification(response){
|
||||
this.props.handleSuccess();
|
||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
render() {
|
||||
let shouldDisplay = this.props.availableAcls.indexOf(this.props.action) > -1;
|
||||
let aclProps = this.actionProperties();
|
||||
@ -58,9 +78,7 @@ let AclButton = React.createClass({
|
||||
{this.props.action.toUpperCase()}
|
||||
</div>
|
||||
}
|
||||
currentUser={ this.props.currentUser }
|
||||
editions={ this.props.editions }
|
||||
handleSuccess={ this.props.handleSuccess }
|
||||
handleSuccess={ aclProps.handleSuccess }
|
||||
title={ aclProps.title }
|
||||
tooltip={ aclProps.tooltip }>
|
||||
{ aclProps.form }
|
||||
|
@ -6,6 +6,7 @@ import UserActions from '../../actions/user_actions';
|
||||
import UserStore from '../../stores/user_store';
|
||||
|
||||
import AclButton from '../ascribe_buttons/acl_button';
|
||||
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||
|
||||
let AclButtonList = React.createClass({
|
||||
propTypes: {
|
||||
@ -47,6 +48,12 @@ let AclButtonList = React.createClass({
|
||||
editions={this.props.editions}
|
||||
currentUser={this.state.currentUser}
|
||||
handleSuccess={this.props.handleSuccess} />
|
||||
<AclButton
|
||||
availableAcls={this.props.availableAcls}
|
||||
action="unconsign"
|
||||
editions={this.props.editions}
|
||||
currentUser={this.state.currentUser}
|
||||
handleSuccess={this.props.handleSuccess} />
|
||||
<AclButton
|
||||
availableAcls={this.props.availableAcls}
|
||||
action="loan"
|
||||
@ -59,6 +66,7 @@ let AclButtonList = React.createClass({
|
||||
editions={this.props.editions}
|
||||
currentUser={this.state.currentUser}
|
||||
handleSuccess={this.props.handleSuccess} />
|
||||
<DeleteButton editions={this.props.editions}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -2,19 +2,20 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
/*
|
||||
Is this even used somewhere?
|
||||
Deprecate? 5.6.15 - Tim
|
||||
|
||||
*/
|
||||
let ButtonSubmitOrClose = React.createClass({
|
||||
propTypes: {
|
||||
submitted: React.PropTypes.bool.isRequired,
|
||||
text: React.PropTypes.string.isRequired,
|
||||
onClose: React.PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
if (this.props.submitted){
|
||||
return (
|
||||
<div className="modal-footer">
|
||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="modal-footer">
|
||||
|
67
js/components/ascribe_buttons/delete_button.js
Normal file
67
js/components/ascribe_buttons/delete_button.js
Normal file
@ -0,0 +1,67 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
|
||||
import EditionDeleteForm from '../ascribe_forms/form_delete_edition';
|
||||
import EditionRemoveFromCollectionForm from '../ascribe_forms/form_remove_editions_from_collection';
|
||||
import ModalWrapper from '../ascribe_modal/modal_wrapper';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import { getAvailableAcls } from '../../utils/acl_utils';
|
||||
|
||||
import EditionListActions from '../../actions/edition_list_actions';
|
||||
|
||||
let DeleteButton = React.createClass({
|
||||
propTypes: {
|
||||
editions: React.PropTypes.array.isRequired
|
||||
},
|
||||
|
||||
mixins: [Router.Navigation],
|
||||
|
||||
showNotification(response) {
|
||||
this.props.editions
|
||||
.forEach((edition) => {
|
||||
EditionListActions.fetchEditionList(edition.parent);
|
||||
});
|
||||
EditionListActions.clearAllEditionSelections();
|
||||
EditionListActions.closeAllEditionLists();
|
||||
this.transitionTo('pieces');
|
||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
let availableAcls = getAvailableAcls(this.props.editions);
|
||||
let btnDelete = null;
|
||||
let content = null;
|
||||
|
||||
if (availableAcls.indexOf('delete') > -1) {
|
||||
content = <EditionDeleteForm editions={ this.props.editions }/>;
|
||||
btnDelete = <Button bsStyle="danger" bsSize="small">DELETE</Button>;
|
||||
}
|
||||
else if (availableAcls.indexOf('del_from_collection') > -1){
|
||||
content = <EditionRemoveFromCollectionForm editions={ this.props.editions }/>;
|
||||
btnDelete = <Button bsStyle="danger" bsSize="small">REMOVE FROM COLLECTION</Button>;
|
||||
}
|
||||
else{
|
||||
return <div></div>;
|
||||
}
|
||||
return (
|
||||
<ModalWrapper
|
||||
button={ btnDelete }
|
||||
handleSuccess={ this.showNotification }
|
||||
title='Remove Edition'
|
||||
tooltip='Click to remove edition'>
|
||||
{ content }
|
||||
</ModalWrapper>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default DeleteButton;
|
||||
|
@ -4,6 +4,10 @@ import React from 'react';
|
||||
import Alert from 'react-bootstrap/lib/Alert';
|
||||
|
||||
let AlertDismissable = React.createClass({
|
||||
propTypes: {
|
||||
error: React.PropTypes.array.isRequired
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
alertVisible: true
|
||||
@ -20,7 +24,6 @@ let AlertDismissable = React.createClass({
|
||||
|
||||
render() {
|
||||
if (this.state.alertVisible) {
|
||||
let key = this.props.error;
|
||||
return (
|
||||
<Alert bsStyle='danger' onDismiss={this.hide}>
|
||||
{this.props.error}
|
||||
|
@ -11,6 +11,7 @@ import ButtonSubmitOrClose from '../ascribe_buttons/button_submit_close';
|
||||
let ConsignForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
|
||||
url() {
|
||||
return ApiUrls.ownership_consigns;
|
||||
},
|
||||
|
35
js/components/ascribe_forms/form_delete_edition.js
Normal file
35
js/components/ascribe_forms/form_delete_edition.js
Normal file
@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import fetch from '../../utils/fetch';
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import FormMixin from '../../mixins/form_mixin';
|
||||
|
||||
let EditionDeleteForm = React.createClass({
|
||||
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return fetch.prepareUrl(ApiUrls.edition_delete, {edition_id: this.getBitcoinIds().join()});
|
||||
},
|
||||
httpVerb(){
|
||||
return 'delete';
|
||||
},
|
||||
|
||||
renderForm () {
|
||||
return (
|
||||
<div className="modal-body">
|
||||
<p>Are you sure you would like to permanently delete this edition?</p>
|
||||
<p>This is an irrevocable action.</p>
|
||||
<div className="modal-footer">
|
||||
<button type="submit" className="btn btn-ascribe-inv" onClick={this.submit}>YES, DELETE</button>
|
||||
<button className="btn btn-ascribe" onClick={this.props.onRequestHide}>CLOSE</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default EditionDeleteForm;
|
@ -52,7 +52,7 @@ let LoanForm = React.createClass({
|
||||
loaneeHasContract: true
|
||||
});
|
||||
}
|
||||
else{
|
||||
else {
|
||||
this.resetLoanContract();
|
||||
}
|
||||
})
|
||||
@ -63,10 +63,11 @@ let LoanForm = React.createClass({
|
||||
},
|
||||
|
||||
resetLoanContract(){
|
||||
this.setState({contract_key: null,
|
||||
contract_url: null,
|
||||
loaneeHasContract: false
|
||||
});
|
||||
this.setState({
|
||||
contract_key: null,
|
||||
contract_url: null,
|
||||
loaneeHasContract: false
|
||||
});
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
|
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;
|
48
js/components/ascribe_forms/form_piece_extradata.js
Normal file
48
js/components/ascribe_forms/form_piece_extradata.js
Normal file
@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import fetch from '../../utils/fetch';
|
||||
|
||||
import apiUrls from '../../constants/api_urls';
|
||||
import FormMixin from '../../mixins/form_mixin';
|
||||
|
||||
import InputTextAreaToggable from './input_textarea_toggable';
|
||||
|
||||
|
||||
let PieceExtraDataForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return fetch.prepareUrl(apiUrls.piece_extradata, {piece_id: this.props.editions[0].bitcoin_id});
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
let extradata = {};
|
||||
extradata[this.props.name] = this.refs[this.props.name].state.value;
|
||||
return {
|
||||
bitcoin_id: this.getBitcoinIds().join(),
|
||||
extradata: extradata
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
|
||||
return (
|
||||
<form role="form" key={this.props.name}>
|
||||
<h5>{this.props.title}</h5>
|
||||
<InputTextAreaToggable
|
||||
ref={this.props.name}
|
||||
className="form-control"
|
||||
defaultValue={this.props.editions[0].extra_data[this.props.name]}
|
||||
rows={3}
|
||||
editable={true}
|
||||
required=""
|
||||
onSubmit={this.submit}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default PieceExtraDataForm;
|
@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import fetch from '../../utils/fetch';
|
||||
import apiUrls from '../../constants/api_urls';
|
||||
import FormMixin from '../../mixins/form_mixin';
|
||||
|
||||
let EditionRemoveFromCollectionForm = React.createClass({
|
||||
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return fetch.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()});
|
||||
},
|
||||
httpVerb(){
|
||||
return 'delete';
|
||||
},
|
||||
|
||||
renderForm () {
|
||||
return (
|
||||
<div className="modal-body">
|
||||
<p>Are you sure you would like to remove these editions from your collection?</p>
|
||||
<p>This is an irrevocable action.</p>
|
||||
<div className="modal-footer">
|
||||
<button type="submit" className="btn btn-ascribe-inv" onClick={this.submit}>YES, REMOVE</button>
|
||||
<button className="btn btn-ascribe" onClick={this.props.onRequestHide}>CLOSE</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default EditionRemoveFromCollectionForm;
|
79
js/components/ascribe_forms/form_request_action.js
Normal file
79
js/components/ascribe_forms/form_request_action.js
Normal file
@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Alert from 'react-bootstrap/lib/Alert';
|
||||
|
||||
import apiUrls from '../../constants/api_urls';
|
||||
import FormMixin from '../../mixins/form_mixin';
|
||||
|
||||
let RequestActionForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url(e){
|
||||
let edition = this.props.editions[0];
|
||||
if (e.target.id === 'request_accept'){
|
||||
if (edition.request_action === 'consign'){
|
||||
return apiUrls.ownership_consigns_confirm;
|
||||
}
|
||||
else if (edition.request_action === 'unconsign'){
|
||||
return apiUrls.ownership_unconsigns;
|
||||
}
|
||||
else if (edition.request_action === 'loan'){
|
||||
return apiUrls.ownership_loans_confirm;
|
||||
}
|
||||
}
|
||||
else if(e.target.id === 'request_deny'){
|
||||
if (edition.request_action === 'consign') {
|
||||
return apiUrls.ownership_consigns_deny;
|
||||
}
|
||||
else if (edition.request_action === 'unconsign') {
|
||||
return apiUrls.ownership_unconsigns_deny;
|
||||
}
|
||||
else if (edition.request_action === 'loan') {
|
||||
return apiUrls.ownership_loans_deny;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleRequest: function(e){
|
||||
e.preventDefault();
|
||||
this.submit(e);
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.getBitcoinIds().join()
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let edition = this.props.editions[0];
|
||||
let buttons = (
|
||||
<span>
|
||||
<span>
|
||||
<div id="request_accept" onClick={this.handleRequest} className='btn btn-default btn-sm'>ACCEPT</div>
|
||||
</span>
|
||||
<span>
|
||||
<div id="request_deny" onClick={this.handleRequest} className='btn btn-default btn-sm'>REJECT</div>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
if (this.state.submitted){
|
||||
buttons = (
|
||||
<span>
|
||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_small.gif" />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Alert bsStyle='warning'>
|
||||
<span>{ edition.owner } requests you { edition.request_action } this edition. </span>
|
||||
{buttons}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default RequestActionForm;
|
@ -17,19 +17,20 @@ let UnConsignForm = React.createClass({
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.props.edition.bitcoin_id,
|
||||
bitcoin_id: this.getBitcoinIds().join(),
|
||||
unconsign_message: this.refs.unconsign_message.state.value,
|
||||
password: this.refs.password.state.value
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let title = this.props.edition.title;
|
||||
let title = this.getTitlesString().join('');
|
||||
let username = this.props.currentUser.username;
|
||||
let message =
|
||||
`Hi,
|
||||
|
||||
I un-consign \" ${title} \" from you.
|
||||
I un-consign:
|
||||
${title}from you.
|
||||
|
||||
Truly yours,
|
||||
${username}`;
|
||||
|
@ -5,6 +5,11 @@ import React from 'react';
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputCheckbox = React.createClass({
|
||||
propTypes: {
|
||||
submitted: React.PropTypes.bool.isRequired,
|
||||
required: React.PropTypes.string.isRequired,
|
||||
label: React.PropTypes.string.isRequired
|
||||
},
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
|
@ -6,6 +6,10 @@ import AlertMixin from '../../mixins/alert_mixin';
|
||||
import DatePicker from 'react-datepicker/dist/react-datepicker';
|
||||
|
||||
let InputDate = React.createClass({
|
||||
propTypes: {
|
||||
submitted: React.PropTypes.bool,
|
||||
placeholderText: React.PropTypes.string
|
||||
},
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
@ -20,11 +24,10 @@ let InputDate = React.createClass({
|
||||
handleChange(date) {
|
||||
this.setState({
|
||||
value: date,
|
||||
value_formatted: date.format("YYYY-MM-DD")});
|
||||
value_formatted: date.format('YYYY-MM-DD')});
|
||||
},
|
||||
|
||||
render: function () {
|
||||
let className = 'form-control input-text-ascribe';
|
||||
let alerts = (this.props.submitted) ? null : this.state.alerts;
|
||||
return (
|
||||
<div className="form-group">
|
||||
@ -37,24 +40,6 @@ let InputDate = React.createClass({
|
||||
placeholderText={this.props.placeholderText}/>
|
||||
</div>
|
||||
);
|
||||
// CAN THIS BE REMOVED???
|
||||
//
|
||||
// - Tim?
|
||||
//
|
||||
//return (
|
||||
// <div className="input-group date"
|
||||
// ref={this.props.name + "_picker"}
|
||||
// onChange={this.handleChange}>
|
||||
// <input className={className}
|
||||
// ref={this.props.name}
|
||||
// placeholder={this.props.placeholder}
|
||||
// required={this.props.required}
|
||||
// type="text"/>
|
||||
// <span className="input-group-addon input-text-ascribe">
|
||||
// <span className="glyphicon glyphicon-calendar" style={{"color": "black"}}></span>
|
||||
// </span>
|
||||
// </div>
|
||||
//)
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -5,6 +5,10 @@ import React from 'react';
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputHidden = React.createClass({
|
||||
propTypes: {
|
||||
submitted: React.PropTypes.bool,
|
||||
value: React.PropTypes.string
|
||||
},
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
|
@ -5,6 +5,13 @@ import React from 'react';
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputText = React.createClass({
|
||||
propTypes: {
|
||||
submitted: React.PropTypes.bool,
|
||||
onBlur: React.PropTypes.func,
|
||||
type: React.PropTypes.string,
|
||||
required: React.PropTypes.string,
|
||||
placeHolder: React.PropTypes.string
|
||||
},
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
|
@ -5,6 +5,11 @@ import React from 'react';
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputTextArea = React.createClass({
|
||||
propTypes: {
|
||||
submitted: React.PropTypes.bool,
|
||||
required: React.PropTypes.string,
|
||||
defaultValue: React.PropTypes.string
|
||||
},
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
|
81
js/components/ascribe_forms/input_textarea_toggable.js
Normal file
81
js/components/ascribe_forms/input_textarea_toggable.js
Normal file
@ -0,0 +1,81 @@
|
||||
'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({
|
||||
|
||||
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
|
||||
};
|
||||
},
|
||||
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;
|
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import LoanForm from '../ascribe_forms/form_loan';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let LoanModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left"
|
||||
overlay={<Tooltip>Loan your artwork for a limited period of time</Tooltip>}>
|
||||
<ModalTrigger modal={<LoanModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv">
|
||||
LOAN
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let LoanModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Loan artwork">
|
||||
<div className="modal-body">
|
||||
<LoanForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default LoanModalButton;
|
@ -1,44 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
import ShareForm from '../ascribe_forms/form_share_email';
|
||||
|
||||
let ShareModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left" overlay={<Tooltip>Share the artwork</Tooltip>}>
|
||||
<ModalTrigger modal={<ShareModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv btn-glyph-ascribe">
|
||||
<span className="glyph-ascribe-share2"></span>
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let ShareModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Share artwork">
|
||||
<div className="modal-body">
|
||||
<ShareForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default ShareModalButton;
|
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import UnConsignForm from '../ascribe_forms/form_unconsign';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let UnConsignModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left"
|
||||
overlay={<Tooltip>Unconsign this artwork</Tooltip>}>
|
||||
<ModalTrigger modal={<UnConsignModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv">
|
||||
UNCONSIGN
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let UnConsignModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Consign artwork">
|
||||
<div className="modal-body">
|
||||
<UnConsignForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default UnConsignModalButton;
|
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import UnConsignRequestForm from '../ascribe_forms/form_unconsign_request';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let UnConsignRequestModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left"
|
||||
overlay={<Tooltip>Request to unconsign the artwork</Tooltip>}>
|
||||
<ModalTrigger modal={<UnConsignRequestModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv">
|
||||
UNCONSIGN REQUEST
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let UnConsignRequestModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Request to unconsign artwork">
|
||||
<div className="modal-body">
|
||||
<UnConsignRequestForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default UnConsignRequestModalButton;
|
@ -11,6 +11,14 @@ import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let ModalWrapper = React.createClass({
|
||||
propTypes: {
|
||||
title: React.PropTypes.string.isRequired,
|
||||
onRequestHide: React.PropTypes.func,
|
||||
handleSuccess: React.PropTypes.func.isRequired,
|
||||
button: React.PropTypes.object.isRequired,
|
||||
children: React.PropTypes.object,
|
||||
tooltip: React.PropTypes.string.isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
@ -19,8 +27,6 @@ let ModalWrapper = React.createClass({
|
||||
<ModalTrigger modal={
|
||||
<ModalBody
|
||||
title={this.props.title}
|
||||
editions={this.props.editions}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.props.handleSuccess}>
|
||||
{this.props.children}
|
||||
</ModalBody>
|
||||
@ -32,22 +38,26 @@ let ModalWrapper = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
let ModalBody = React.createClass({
|
||||
propTypes: {
|
||||
onRequestHide: React.PropTypes.func,
|
||||
handleSuccess: React.PropTypes.func,
|
||||
children: React.PropTypes.object,
|
||||
title: React.PropTypes.string.isRequired
|
||||
},
|
||||
|
||||
mixins: [ModalMixin],
|
||||
|
||||
handleSuccess(){
|
||||
this.props.handleSuccess();
|
||||
handleSuccess(response){
|
||||
this.props.handleSuccess(response);
|
||||
this.props.onRequestHide();
|
||||
},
|
||||
|
||||
renderChildren() {
|
||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||
return ReactAddons.addons.cloneWithProps(child, {
|
||||
editions: this.props.editions,
|
||||
currentUser: this.props.currentUser,
|
||||
onRequestHide: this.onRequestHide,
|
||||
onRequestHide: this.props.onRequestHide,
|
||||
handleSuccess: this.handleSuccess
|
||||
});
|
||||
});
|
||||
|
@ -13,7 +13,9 @@ import UserActions from '../../actions/user_actions';
|
||||
import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget';
|
||||
import AclButtonList from '../ascribe_buttons/acl_button_list';
|
||||
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import { getAvailableAcls } from '../../utils/acl_utils';
|
||||
|
||||
|
||||
let PieceListBulkModal = React.createClass({
|
||||
propTypes: {
|
||||
@ -61,31 +63,9 @@ let PieceListBulkModal = React.createClass({
|
||||
return selectedEditionList;
|
||||
},
|
||||
|
||||
intersectAcls(a, b) {
|
||||
return a.filter((val) => b.indexOf(val) > -1);
|
||||
},
|
||||
|
||||
getAvailableAcls() {
|
||||
let availableAcls = [];
|
||||
let selectedEditionList = this.fetchSelectedEditionList();
|
||||
|
||||
// If no edition has been selected, availableActions is empty
|
||||
// If only one edition has been selected, their actions are available
|
||||
// If more than one editions have been selected, their acl properties are intersected
|
||||
if(selectedEditionList.length >= 1) {
|
||||
availableAcls = selectedEditionList[0].acl;
|
||||
}
|
||||
if(selectedEditionList.length >= 2) {
|
||||
for(let i = 1; i < selectedEditionList.length; i++) {
|
||||
availableAcls = this.intersectAcls(availableAcls, selectedEditionList[i].acl);
|
||||
}
|
||||
}
|
||||
|
||||
return availableAcls;
|
||||
},
|
||||
|
||||
clearAllSelections() {
|
||||
EditionListActions.clearAllEditionSelections();
|
||||
EditionListActions.closeAllEditionLists();
|
||||
},
|
||||
|
||||
handleSuccess() {
|
||||
@ -93,13 +73,12 @@ let PieceListBulkModal = React.createClass({
|
||||
.forEach((pieceId) => {
|
||||
EditionListActions.fetchEditionList(pieceId, this.state.orderBy, this.state.orderAsc);
|
||||
});
|
||||
GlobalNotificationActions.updateGlobalNotification({message: 'Transfer successful'});
|
||||
EditionListActions.clearAllEditionSelections();
|
||||
},
|
||||
|
||||
render() {
|
||||
let availableAcls = this.getAvailableAcls();
|
||||
let selectedEditions = this.fetchSelectedEditionList();
|
||||
let availableAcls = getAvailableAcls(selectedEditions);
|
||||
|
||||
if(availableAcls.length > 0) {
|
||||
return (
|
||||
|
@ -20,7 +20,6 @@ let Table = React.createClass({
|
||||
},
|
||||
|
||||
renderChildren() {
|
||||
var that = this;
|
||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||
return ReactAddons.addons.cloneWithProps(child, {
|
||||
columnList: this.props.columnList,
|
||||
|
@ -17,7 +17,9 @@ let TableItemCheckbox = React.createClass({
|
||||
|
||||
render() {
|
||||
return (
|
||||
<input type="checkbox" onChange={this.selectItem} checked={this.props.selected}/>
|
||||
<span>
|
||||
<input type="checkbox" onChange={this.selectItem} checked={this.props.selected}/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import { ColumnModel } from './models/table_models';
|
||||
import TableColumnMixin from '../../mixins/table_column_mixin';
|
||||
|
||||
let Link = Router.Link;
|
||||
|
||||
@ -15,7 +14,7 @@ let TableItemWrapper = React.createClass({
|
||||
columnWidth: React.PropTypes.number.isRequired
|
||||
},
|
||||
|
||||
mixins: [TableColumnMixin, Router.Navigation],
|
||||
mixins: [Router.Navigation],
|
||||
|
||||
render() {
|
||||
return (
|
||||
@ -25,8 +24,6 @@ let TableItemWrapper = React.createClass({
|
||||
let TypeElement = column.displayType;
|
||||
let typeElementProps = column.transformFn(this.props.columnContent);
|
||||
|
||||
let columnClass = this.calcColumnClasses(this.props.columnList, i, this.props.columnWidth);
|
||||
|
||||
if(!column.transition) {
|
||||
return (
|
||||
<td
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import MediaPlayer from './ascribe_media/media_player';
|
||||
|
||||
import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin';
|
||||
@ -8,11 +9,17 @@ 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 TextareaAutosize from 'react-textarea-autosize';
|
||||
|
||||
import PersonalNoteForm from './ascribe_forms/form_note_personal';
|
||||
import PieceExtraDataForm from './ascribe_forms/form_piece_extradata';
|
||||
import RequestActionForm from './ascribe_forms/form_request_action';
|
||||
|
||||
import EditionActions from '../actions/edition_actions';
|
||||
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';
|
||||
|
||||
/**
|
||||
@ -21,9 +28,7 @@ import classNames from 'classnames';
|
||||
let Edition = React.createClass({
|
||||
propTypes: {
|
||||
edition: React.PropTypes.object,
|
||||
currentUser: React.PropTypes.object,
|
||||
deleteEdition: React.PropTypes.func,
|
||||
savePersonalNote: React.PropTypes.func
|
||||
loadEdition: React.PropTypes.func
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -39,10 +44,14 @@ let Edition = React.createClass({
|
||||
<a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.bitcoin_id}>{this.props.edition.bitcoin_id}</a>
|
||||
);
|
||||
|
||||
let hashOfArtwork = (
|
||||
let hashOfArtwork = (
|
||||
<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 (
|
||||
<Row>
|
||||
<Col md={6}>
|
||||
@ -59,13 +68,19 @@ let Edition = React.createClass({
|
||||
<Col md={6} className="ascribe-edition-details">
|
||||
<EditionHeader edition={this.props.edition}/>
|
||||
<EditionSummary
|
||||
edition={this.props.edition}
|
||||
currentUser={ this.props.currentUser }/>
|
||||
edition={this.props.edition} />
|
||||
<CollapsibleEditionDetails
|
||||
title="Personal Note"
|
||||
iconName="pencil">
|
||||
<EditionPersonalNote
|
||||
savePersonalNote={this.props.savePersonalNote}/>
|
||||
<EditionPersonalNote
|
||||
handleSuccess={this.props.loadEdition}
|
||||
edition={this.props.edition}/>
|
||||
</CollapsibleEditionDetails>
|
||||
<CollapsibleEditionDetails
|
||||
title="Further Details">
|
||||
<EditionFurtherDetails
|
||||
handleSuccess={this.props.loadEdition}
|
||||
edition={this.props.edition}/>
|
||||
</CollapsibleEditionDetails>
|
||||
|
||||
<CollapsibleEditionDetails
|
||||
@ -75,6 +90,13 @@ let Edition = React.createClass({
|
||||
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>
|
||||
|
||||
<CollapsibleEditionDetails
|
||||
title="Loan History"
|
||||
show={this.props.edition.loan_history && this.props.edition.loan_history.length > 0}>
|
||||
@ -92,16 +114,7 @@ let Edition = React.createClass({
|
||||
value={hashOfArtwork} />
|
||||
<EditionDetailProperty
|
||||
label="Owned by SPOOL address"
|
||||
value="MISSING IN /editions/<id> RESOURCE!" />
|
||||
</CollapsibleEditionDetails>
|
||||
|
||||
<CollapsibleEditionDetails
|
||||
title="Delete Actions">
|
||||
<Button
|
||||
bsStyle="danger"
|
||||
onClick={this.props.deleteEdition}>
|
||||
Remove this artwork from your list
|
||||
</Button>
|
||||
value={ownerAddress} />
|
||||
</CollapsibleEditionDetails>
|
||||
</Col>
|
||||
</Row>
|
||||
@ -130,22 +143,31 @@ let EditionHeader = React.createClass({
|
||||
|
||||
let EditionSummary = React.createClass({
|
||||
propTypes: {
|
||||
edition: React.PropTypes.object,
|
||||
currentUser: React.PropTypes.object
|
||||
edition: React.PropTypes.object
|
||||
},
|
||||
|
||||
handleSuccess(){
|
||||
EditionActions.fetchOne(this.props.edition.id);
|
||||
},
|
||||
|
||||
showNotification(response){
|
||||
this.handleSuccess();
|
||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
render() {
|
||||
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 } />
|
||||
<br/>
|
||||
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 = (
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<AclButtonList
|
||||
@ -154,7 +176,18 @@ let EditionSummary = React.createClass({
|
||||
editions={[this.props.edition]}
|
||||
handleSuccess={this.handleSuccess} />
|
||||
</Col>
|
||||
</Row>
|
||||
</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}
|
||||
<hr/>
|
||||
</div>
|
||||
);
|
||||
@ -257,8 +290,8 @@ let EditionDetailProperty = React.createClass({
|
||||
getDefaultProps() {
|
||||
return {
|
||||
separator: ':',
|
||||
labelClassName: 'col-xs-5 col-sm-5 col-md-5 col-lg-5',
|
||||
valueClassName: 'col-xs-7 col-sm-7 col-md-7 col-lg-7'
|
||||
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'
|
||||
};
|
||||
},
|
||||
|
||||
@ -267,7 +300,7 @@ let EditionDetailProperty = React.createClass({
|
||||
<div className="row ascribe-detail-property">
|
||||
<div className="row-same-height">
|
||||
<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 className={this.props.valueClassName + ' col-xs-height col-bottom'}>
|
||||
<div>{ this.props.value }</div>
|
||||
@ -304,26 +337,21 @@ let EditionDetailHistoryIterator = React.createClass({
|
||||
|
||||
let EditionPersonalNote = React.createClass({
|
||||
propTypes: {
|
||||
savePersonalNote: React.PropTypes.func
|
||||
edition: React.PropTypes.object,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
|
||||
prepareSavePersonalNote() {
|
||||
let personalNote = React.findDOMNode(this.refs.personalNote).value;
|
||||
this.props.savePersonalNote(personalNote);
|
||||
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">
|
||||
<TextareaAutosize
|
||||
ref="personalNote"
|
||||
className="form-control"
|
||||
rows={3}
|
||||
placeholder='Write something...' />
|
||||
<Button
|
||||
onClick={this.prepareSavePersonalNote}
|
||||
className="pull-right">Save</Button>
|
||||
<PersonalNoteForm
|
||||
handleSuccess={this.showNotification}
|
||||
editions={[this.props.edition]} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
@ -331,4 +359,41 @@ let EditionPersonalNote = React.createClass({
|
||||
});
|
||||
|
||||
|
||||
|
||||
let EditionFurtherDetails = React.createClass({
|
||||
propTypes: {
|
||||
edition: React.PropTypes.object,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
showNotification(){
|
||||
this.props.handleSuccess();
|
||||
let notification = new GlobalNotificationModel('Details updated', 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Row>
|
||||
<Col md={12} className="ascribe-edition-personal-note">
|
||||
<PieceExtraDataForm
|
||||
name='artist_contact_info'
|
||||
title='Artist Contact Info'
|
||||
handleSuccess={this.showNotification}
|
||||
editions={[this.props.edition]} />
|
||||
<PieceExtraDataForm
|
||||
name='display_instructions'
|
||||
title='Display Instructions'
|
||||
handleSuccess={this.showNotification}
|
||||
editions={[this.props.edition]} />
|
||||
<PieceExtraDataForm
|
||||
name='technology_details'
|
||||
title='Technology Details'
|
||||
handleSuccess={this.showNotification}
|
||||
editions={[this.props.edition]} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default Edition;
|
||||
|
@ -2,12 +2,8 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { mergeOptions } from '../utils/general_utils';
|
||||
|
||||
import EditionActions from '../actions/edition_actions';
|
||||
import EditionStore from '../stores/edition_store';
|
||||
import UserActions from '../actions/user_actions';
|
||||
import UserStore from '../stores/user_store';
|
||||
|
||||
import Edition from './edition';
|
||||
|
||||
@ -16,7 +12,7 @@ import Edition from './edition';
|
||||
*/
|
||||
let EditionContainer = React.createClass({
|
||||
getInitialState() {
|
||||
return mergeOptions(UserStore.getState(), EditionStore.getState());
|
||||
return EditionStore.getState();
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
@ -25,24 +21,16 @@ let EditionContainer = React.createClass({
|
||||
|
||||
componentDidMount() {
|
||||
EditionStore.listen(this.onChange);
|
||||
UserStore.listen(this.onChange);
|
||||
|
||||
UserActions.fetchCurrentUser();
|
||||
EditionActions.fetchOne(this.props.params.editionId);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
EditionStore.unlisten(this.onChange);
|
||||
UserStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
deleteEdition() {
|
||||
// Delete Edition from server
|
||||
},
|
||||
|
||||
savePersonalNote(note) {
|
||||
console.log(note);
|
||||
// Save personalNote to server
|
||||
loadEdition() {
|
||||
EditionActions.fetchOne(this.props.params.editionId);
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -50,9 +38,7 @@ let EditionContainer = React.createClass({
|
||||
return (
|
||||
<Edition
|
||||
edition={this.state.edition}
|
||||
currentUser={this.state.currentUser}
|
||||
deleteEdition={this.deleteEdition}
|
||||
savePersonalNote={this.savePersonalNote}/>
|
||||
loadEdition={this.loadEdition}/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
|
@ -38,7 +38,7 @@ let Header = React.createClass({
|
||||
return (
|
||||
<Navbar>
|
||||
<Nav>
|
||||
<Link className="navbar-brand" to="pieces">
|
||||
<Link className="navbar-brand" to="pieces" path="/?page=1">
|
||||
<span>ascribe </span>
|
||||
<span className="glyph-ascribe-spool-chunked ascribe-color"></span>
|
||||
</Link>
|
||||
|
@ -27,7 +27,10 @@ let PieceList = React.createClass({
|
||||
componentDidMount() {
|
||||
let page = this.props.query.page || 1;
|
||||
PieceListStore.listen(this.onChange);
|
||||
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
|
||||
if (this.state.pieceList.length === 0){
|
||||
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -74,9 +77,7 @@ let PieceList = React.createClass({
|
||||
key={i}>
|
||||
<AccordionListItemTableEditions
|
||||
className="ascribe-accordion-list-item-table col-xs-12 col-sm-8 col-md-6 col-lg-6 col-sm-offset-2 col-md-offset-3 col-lg-offset-3"
|
||||
parentId={item.id}
|
||||
show={item.show}
|
||||
numOfEditions={item.num_editions}/>
|
||||
parentId={item.id} />
|
||||
</AccordionListItem>
|
||||
);
|
||||
})}
|
||||
|
@ -3,17 +3,26 @@
|
||||
import AppConstants from './application_constants';
|
||||
|
||||
let apiUrls = {
|
||||
'ownership_shares_mail': AppConstants.apiEndpoint + 'ownership/shares/mail/',
|
||||
'ownership_transfers': AppConstants.apiEndpoint + 'ownership/transfers/',
|
||||
'user': AppConstants.apiEndpoint + 'users/',
|
||||
'pieces_list': AppConstants.apiEndpoint + 'pieces/',
|
||||
'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}',
|
||||
'pieces_list': AppConstants.apiEndpoint + 'pieces/',
|
||||
'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/',
|
||||
'edition': AppConstants.apiEndpoint + 'editions/${bitcoin_id}/',
|
||||
'editions_list': AppConstants.apiEndpoint + 'pieces/${piece_id}/editions/',
|
||||
'ownership_loans': AppConstants.apiEndpoint + 'ownership/loans/',
|
||||
'edition_delete': AppConstants.apiEndpoint + 'editions/${edition_id}/',
|
||||
'edition_remove_from_collection': AppConstants.apiEndpoint + 'ownership/shares/${edition_id}/',
|
||||
'ownership_shares_mail': AppConstants.apiEndpoint + 'ownership/shares/mail/',
|
||||
'ownership_transfers': AppConstants.apiEndpoint + 'ownership/transfers/',
|
||||
'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/',
|
||||
'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/',
|
||||
'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/',
|
||||
'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/',
|
||||
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/'
|
||||
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',
|
||||
'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/',
|
||||
'ownership_loans': AppConstants.apiEndpoint + 'ownership/loans/',
|
||||
'ownership_loans_confirm': AppConstants.apiEndpoint + 'ownership/loans/confirm/',
|
||||
'ownership_loans_deny': AppConstants.apiEndpoint + 'ownership/loans/deny/',
|
||||
'note_notes': AppConstants.apiEndpoint + 'note/notes/'
|
||||
};
|
||||
|
||||
export default apiUrls;
|
||||
|
@ -8,7 +8,8 @@ let constants = {
|
||||
'baseUrl': window.BASE_URL,
|
||||
'apiEndpoint': window.API_ENDPOINT,
|
||||
'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000
|
||||
'aclList': ['edit', 'consign', 'transfer', 'loan', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
|
||||
'aclList': ['edit', 'consign', 'consign_request', 'unconsign', 'unconsign_request', 'transfer',
|
||||
'loan', 'loan_request', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
|
||||
};
|
||||
|
||||
export default constants;
|
||||
|
@ -6,6 +6,11 @@ import React from 'react';
|
||||
import AlertDismissable from '../components/ascribe_forms/alert';
|
||||
|
||||
export const FormMixin = {
|
||||
propTypes: {
|
||||
editions: React.PropTypes.array,
|
||||
currentUser: React.PropTypes.object
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
submitted: false,
|
||||
@ -14,22 +19,44 @@ export const FormMixin = {
|
||||
},
|
||||
|
||||
submit(e) {
|
||||
e.preventDefault();
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.setState({submitted: true});
|
||||
this.clearErrors();
|
||||
let action = (this.httpVerb && this.httpVerb()) || 'post';
|
||||
this[action](e);
|
||||
},
|
||||
|
||||
post(e){
|
||||
fetch
|
||||
.post(this.url(), { body: this.getFormData() })
|
||||
.then(() => this.props.handleSuccess())
|
||||
.post(this.url(e), { body: this.getFormData() })
|
||||
.then(this.handleSuccess)
|
||||
.catch(this.handleError);
|
||||
},
|
||||
|
||||
delete(e){
|
||||
fetch
|
||||
.delete(this.url(e))
|
||||
.then(this.handleSuccess)
|
||||
.catch(this.handleError);
|
||||
},
|
||||
|
||||
clearErrors(){
|
||||
for (var ref in this.refs){
|
||||
this.refs[ref].clearAlerts();
|
||||
if ('clearAlerts' in this.refs[ref]){
|
||||
this.refs[ref].clearAlerts();
|
||||
}
|
||||
|
||||
}
|
||||
this.setState({errors: []});
|
||||
},
|
||||
handleSuccess(response){
|
||||
if ('handleSuccess' in this.props){
|
||||
this.props.handleSuccess(response);
|
||||
}
|
||||
|
||||
},
|
||||
handleError(err){
|
||||
if (err.json) {
|
||||
for (var input in err.json.errors){
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
export default class GlobalNotificationModel {
|
||||
constructor(message, type = 'info', dismissAfter = 3500) {
|
||||
constructor(message, type = 'info', dismissAfter = 5000) {
|
||||
if(message) {
|
||||
this.message = message;
|
||||
} else {
|
||||
|
@ -8,6 +8,7 @@ import EditionsListActions from '../actions/edition_list_actions';
|
||||
class EditionListStore {
|
||||
constructor() {
|
||||
this.editionList = {};
|
||||
this.isEditionListOpenForPieceId = {};
|
||||
this.bindActions(EditionsListActions);
|
||||
}
|
||||
|
||||
@ -16,13 +17,16 @@ class EditionListStore {
|
||||
this.editionList[pieceId].forEach((edition, i) => {
|
||||
// This uses the index of the new editionList for determining the edition.
|
||||
// If the list of editions can be sorted in the future, this needs to be changed!
|
||||
editionListOfPiece[i] = React.addons.update(edition, {$merge: editionListOfPiece[i]});
|
||||
if (editionListOfPiece[i]) {
|
||||
editionListOfPiece[i] = React.addons.update(edition, {$merge: editionListOfPiece[i]});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.editionList[pieceId] = editionListOfPiece;
|
||||
|
||||
/**
|
||||
* orderBy and orderAsc are specific to a single list of editons
|
||||
* orderBy and orderAsc are specific to a single list of editions
|
||||
* therefore they need to be saved in relation to their parent-piece.
|
||||
*
|
||||
* Default values for both are set in the editon_list-actions.
|
||||
@ -34,7 +38,7 @@ class EditionListStore {
|
||||
onSelectEdition({pieceId, editionId, toValue}) {
|
||||
this.editionList[pieceId].forEach((edition) => {
|
||||
|
||||
// http://stackoverflow.com/a/519157/1263876
|
||||
// Taken from: http://stackoverflow.com/a/519157/1263876
|
||||
if(typeof toValue !== 'undefined' && edition.id === editionId) {
|
||||
edition.selected = toValue;
|
||||
} else if(edition.id === editionId) {
|
||||
@ -55,12 +59,20 @@ class EditionListStore {
|
||||
.forEach((edition) => {
|
||||
try {
|
||||
delete edition.selected;
|
||||
} catch(err) {
|
||||
//just ignore
|
||||
}
|
||||
} catch(err) {/* ignore and keep going */}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onToggleEditionList(pieceId) {
|
||||
this.isEditionListOpenForPieceId[pieceId] = {
|
||||
show: this.isEditionListOpenForPieceId[pieceId] ? !this.isEditionListOpenForPieceId[pieceId].show : true
|
||||
};
|
||||
}
|
||||
|
||||
onCloseAllEditionLists() {
|
||||
this.isEditionListOpenForPieceId = {};
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createStore(EditionListStore, 'EditionListStore');
|
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import alt from '../alt';
|
||||
|
||||
import PieceListActions from '../actions/piece_list_actions';
|
||||
@ -27,7 +28,7 @@ class PieceListStore {
|
||||
this.bindActions(PieceListActions);
|
||||
}
|
||||
|
||||
onShowEditionList(pieceId) {
|
||||
/*onShowEditionList(pieceId) {
|
||||
this.pieceList
|
||||
.forEach((piece) => {
|
||||
if(piece.id === pieceId) {
|
||||
@ -38,14 +39,14 @@ class PieceListStore {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}*/
|
||||
|
||||
onCloseAllEditionLists() {
|
||||
/*onCloseAllEditionLists() {
|
||||
this.pieceList
|
||||
.forEach((piece) => {
|
||||
piece.show = false;
|
||||
});
|
||||
}
|
||||
}*/
|
||||
|
||||
onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) {
|
||||
this.page = page;
|
||||
@ -72,6 +73,16 @@ class PieceListStore {
|
||||
* We did not implement this, as we're going to add pagination to pieceList at some
|
||||
* point anyway. Then, this problem is automatically resolved.
|
||||
*/
|
||||
pieceList.forEach((piece, i) => {
|
||||
let oldPiece = this.pieceList[i];
|
||||
if(oldPiece) {
|
||||
piece = React.addons.update(piece, {
|
||||
show: { $set: oldPiece.show }
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.pieceList = pieceList;
|
||||
}
|
||||
}
|
||||
|
23
js/utils/acl_utils.js
Normal file
23
js/utils/acl_utils.js
Normal file
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
export function getAvailableAcls(editions) {
|
||||
let availableAcls = [];
|
||||
|
||||
// If no edition has been selected, availableActions is empty
|
||||
// If only one edition has been selected, their actions are available
|
||||
// If more than one editions have been selected, their acl properties are intersected
|
||||
if(editions.length >= 1) {
|
||||
availableAcls = editions[0].acl;
|
||||
}
|
||||
if(editions.length >= 2) {
|
||||
for(let i = 1; i < editions.length; i++) {
|
||||
availableAcls = intersectAcls(availableAcls, editions[i].acl);
|
||||
}
|
||||
}
|
||||
|
||||
return availableAcls;
|
||||
}
|
||||
|
||||
export function intersectAcls(a, b) {
|
||||
return a.filter((val) => b.indexOf(val) > -1);
|
||||
}
|
@ -88,19 +88,25 @@ class Fetch {
|
||||
|
||||
get(url, params) {
|
||||
let paramsCopy = this._merge(params);
|
||||
let newUrl = this.prepareUrl(url, params, true);
|
||||
let newUrl = this.prepareUrl(url, paramsCopy, true);
|
||||
return this.request('get', newUrl);
|
||||
}
|
||||
|
||||
delete(url, params) {
|
||||
let paramsCopy = this._merge(params);
|
||||
let newUrl = this.prepareUrl(url, paramsCopy, true);
|
||||
return this.request('delete', newUrl);
|
||||
}
|
||||
|
||||
post(url, params) {
|
||||
let paramsCopy = this._merge(params);
|
||||
let newUrl = this.prepareUrl(url, params);
|
||||
let newUrl = this.prepareUrl(url, paramsCopy);
|
||||
let body = null;
|
||||
|
||||
if (params.body) {
|
||||
body = JSON.stringify(params.body);
|
||||
if (paramsCopy && paramsCopy.body) {
|
||||
body = JSON.stringify(paramsCopy.body);
|
||||
}
|
||||
return this.request('post', url, { body });
|
||||
return this.request('post', newUrl, { body });
|
||||
}
|
||||
|
||||
defaults(options) {
|
||||
|
44
sass/ascribe_table.scss
Normal file
44
sass/ascribe_table.scss
Normal file
@ -0,0 +1,44 @@
|
||||
.ascribe-table {
|
||||
margin-bottom:0;
|
||||
}
|
||||
|
||||
/*This is aligning the first checkbox in pieclist detail with all the other ones*/
|
||||
.table > thead:first-child > tr:first-child > th {
|
||||
padding-left:0;
|
||||
}
|
||||
|
||||
|
||||
.ascribe-table-header-column > span {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
font-family: 'Source Sans Pro';
|
||||
font-weight: 600;
|
||||
color: #424242;
|
||||
}
|
||||
|
||||
.ascribe-table-item-column {
|
||||
display: table;
|
||||
font-family: 'Source Sans Pro';
|
||||
font-size: .8em;
|
||||
height:3em;
|
||||
}
|
||||
|
||||
.ascribe-table-item-column > * {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ascribe-table-item-column > span > input {
|
||||
margin-top:14px;
|
||||
}
|
||||
|
||||
.ascribe-table-item-selected {
|
||||
background-color: rgba(2, 182, 163, 0.5);
|
||||
}
|
||||
|
||||
.ascribe-table-item-selectable {
|
||||
cursor: default;
|
||||
}
|
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;
|
||||
}
|
@ -9,10 +9,12 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
@import '../node_modules/react-datepicker/dist/react-datepicker';
|
||||
@import './ascribe-fonts/style';
|
||||
@import './ascribe-fonts/ascribe-fonts';
|
||||
@import 'ascribe_table';
|
||||
@import 'ascribe_accordion_list';
|
||||
@import 'ascribe_piece_list_bulk_modal';
|
||||
@import 'ascribe_piece_list_toolbar';
|
||||
@import 'ascribe_edition';
|
||||
@import 'ascribe_textarea';
|
||||
@import 'ascribe_media_player';
|
||||
@import 'ascribe-global-notification';
|
||||
@import 'offset_right';
|
||||
@ -28,6 +30,10 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
border-top:0;
|
||||
}
|
||||
|
||||
.navbar-right {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.clear-paddings {
|
||||
padding-left:0;
|
||||
padding-right:0;
|
||||
@ -44,45 +50,6 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
float: none;
|
||||
}
|
||||
|
||||
.ascribe-table {
|
||||
margin-bottom:0;
|
||||
}
|
||||
|
||||
.ascribe-table-header-column > span {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
font-family: 'Source Sans Pro';
|
||||
font-weight: 600;
|
||||
color: #424242;
|
||||
}
|
||||
|
||||
.ascribe-table-header-column > span > .glyphicon {
|
||||
font-size: .5em;
|
||||
}
|
||||
|
||||
.ascribe-table-item-column {
|
||||
display: table;
|
||||
font-family: 'Source Sans Pro';
|
||||
font-size: .8em;
|
||||
height:3em;
|
||||
}
|
||||
|
||||
.ascribe-table-item-column > * {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ascribe-table-item-selected {
|
||||
background-color: rgba(2, 182, 163, 0.5);
|
||||
}
|
||||
|
||||
.ascribe-table-item-selectable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.no-margin {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
@ -95,7 +62,6 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
margin-left: 0 !important;
|
||||
font-family: sans-serif !important;
|
||||
border-radius: 0 !important;
|
||||
|
||||
}
|
||||
|
||||
.btn-ascribe, .btn-ascribe-inv:active, .btn-ascribe-inv:hover {
|
||||
@ -125,7 +91,6 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
margin-left: 0 !important;
|
||||
font-family: sans-serif !important;
|
||||
border-radius: 0 !important;
|
||||
|
||||
}
|
||||
|
||||
.btn-ascribe-green, .btn-ascribe-green-inv:active, .btn-ascribe-green-inv:hover {
|
||||
@ -144,7 +109,6 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
|
||||
.ascribe-detail-title {
|
||||
font-size: 2em;
|
||||
margin-bottom: -0.2em;
|
||||
|
Loading…
Reference in New Issue
Block a user