1
0
mirror of https://github.com/ascribe/onion.git synced 2024-06-30 21:52:08 +02:00

Merge remote-tracking branch 'origin/AD-419-decouple-piece-registration-from-' into AD-419-decouple-piece-registration-from-

Conflicts:
	js/components/ascribe_detail/edition.js
This commit is contained in:
diminator 2015-07-14 17:45:39 +02:00
commit 982b701a5c
16 changed files with 296 additions and 84 deletions

View File

@ -8,6 +8,7 @@ class EditionListActions {
constructor() { constructor() {
this.generateActions( this.generateActions(
'updateEditionList', 'updateEditionList',
'refreshEditionList',
'selectEdition', 'selectEdition',
'clearAllEditionSelections', 'clearAllEditionSelections',
'closeAllEditionLists', 'closeAllEditionLists',
@ -16,7 +17,7 @@ class EditionListActions {
} }
fetchEditionList(pieceId, page, pageSize, orderBy, orderAsc) { fetchEditionList(pieceId, page, pageSize, orderBy, orderAsc) {
if(!orderBy && typeof orderAsc == 'undefined') { if(!orderBy && typeof orderAsc === 'undefined') {
orderBy = 'edition_number'; orderBy = 'edition_number';
orderAsc = true; orderAsc = true;
} }

View File

@ -13,6 +13,9 @@ import CreateEditionsForm from '../ascribe_forms/create_editions_form';
import PieceListActions from '../../actions/piece_list_actions'; import PieceListActions from '../../actions/piece_list_actions';
import EditionListActions from '../../actions/edition_list_actions'; import EditionListActions from '../../actions/edition_list_actions';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
import { getLangText } from '../../utils/lang_utils'; import { getLangText } from '../../utils/lang_utils';
let Link = Router.Link; let Link = Router.Link;
@ -63,6 +66,9 @@ let AccordionListItem = React.createClass({
}); });
EditionListActions.toggleEditionList(pieceId); EditionListActions.toggleEditionList(pieceId);
let notification = new GlobalNotificationModel('Editions successfully created', 'success', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
}, },
getCreateEditionsDialog() { getCreateEditionsDialog() {

View File

@ -6,7 +6,6 @@ import UserActions from '../../actions/user_actions';
import UserStore from '../../stores/user_store'; import UserStore from '../../stores/user_store';
import AclButton from '../ascribe_buttons/acl_button'; import AclButton from '../ascribe_buttons/acl_button';
import DeleteButton from '../ascribe_buttons/delete_button';
let AclButtonList = React.createClass({ let AclButtonList = React.createClass({
propTypes: { propTypes: {
@ -73,9 +72,6 @@ let AclButtonList = React.createClass({
pieceOrEditions={this.props.editions} pieceOrEditions={this.props.editions}
currentUser={this.state.currentUser} currentUser={this.state.currentUser}
handleSuccess={this.props.handleSuccess} /> handleSuccess={this.props.handleSuccess} />
<DeleteButton
handleSuccess={this.props.handleSuccess}
editions={this.props.editions}/>
{this.props.children} {this.props.children}
</div> </div>
); );

View File

@ -6,66 +6,71 @@ import Router from 'react-router';
import Button from 'react-bootstrap/lib/Button'; import Button from 'react-bootstrap/lib/Button';
import EditionDeleteForm from '../ascribe_forms/form_delete_edition'; import EditionDeleteForm from '../ascribe_forms/form_delete_edition';
import EditionRemoveFromCollectionForm from '../ascribe_forms/form_remove_editions_from_collection'; import PieceDeleteForm from '../ascribe_forms/form_delete_piece';
import ModalWrapper from '../ascribe_modal/modal_wrapper';
import GlobalNotificationModel from '../../models/global_notification_model'; import EditionRemoveFromCollectionForm from '../ascribe_forms/form_remove_editions_from_collection';
import GlobalNotificationActions from '../../actions/global_notification_actions'; import PieceRemoveFromCollectionForm from '../ascribe_forms/form_remove_piece_from_collection';
import ModalWrapper from '../ascribe_modal/modal_wrapper';
import { getAvailableAcls } from '../../utils/acl_utils'; import { getAvailableAcls } from '../../utils/acl_utils';
import { getLangText } from '../../utils/lang_utils.js'; import { getLangText } from '../../utils/lang_utils.js';
import EditionListActions from '../../actions/edition_list_actions';
let DeleteButton = React.createClass({ let DeleteButton = React.createClass({
propTypes: { propTypes: {
editions: React.PropTypes.array.isRequired, editions: React.PropTypes.array,
piece: React.PropTypes.object,
handleSuccess: React.PropTypes.func handleSuccess: React.PropTypes.func
}, },
mixins: [Router.Navigation], mixins: [Router.Navigation],
showNotification(response) {
if (this.props.editions.constructor === Array){
this.props.editions
.forEach((edition) => {
EditionListActions.fetchEditionList(edition.parent);
});
}
else {
EditionListActions.fetchEditionList(this.props.editions.id);
}
EditionListActions.clearAllEditionSelections();
EditionListActions.closeAllEditionLists();
this.props.handleSuccess();
this.transitionTo('pieces');
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
},
render: function () { render: function () {
let availableAcls = getAvailableAcls(this.props.editions); let availableAcls;
let btnDelete = null; let btnDelete;
let content = null; let content;
let title;
if (availableAcls.acl_delete) { if(this.props.piece && !this.props.editions) {
content = <EditionDeleteForm editions={ this.props.editions }/>; availableAcls = getAvailableAcls([this.props.piece]);
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('DELETE')}</Button>; } else {
availableAcls = getAvailableAcls(this.props.editions);
} }
else if (availableAcls.acl_unshare || (this.props.editions.constructor !== Array && this.props.editions.acl.acl_unshare)){
content = <EditionRemoveFromCollectionForm editions={ this.props.editions }/>; if(availableAcls.acl_delete) {
if(this.props.piece && !this.props.editions) {
content = <PieceDeleteForm pieceId={this.props.piece.id}/>;
title = getLangText('Remove Piece');
} else {
content = <EditionDeleteForm editions={this.props.editions}/>;
title = getLangText('Remove Edition');
}
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('DELETE')}</Button>;
} else if(availableAcls.acl_unshare){
if(this.props.editions && this.props.editions.constructor !== Array && this.props.editions.acl.acl_unshare) {
content = <EditionRemoveFromCollectionForm editions={this.props.editions}/>;
title = getLangText('Remove Edition from Collection');
} else {
content = <PieceRemoveFromCollectionForm pieceId={this.props.piece.id}/>;
title = getLangText('Remove Piece from Collection');
}
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('REMOVE FROM COLLECTION')}</Button>; btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('REMOVE FROM COLLECTION')}</Button>;
} }
else{ else {
return null; return null;
} }
return ( return (
<ModalWrapper <ModalWrapper
button={ btnDelete } button={btnDelete}
handleSuccess={ this.showNotification } handleSuccess={this.props.handleSuccess}
title={getLangText('Remove Edition')} title={title}>
tooltip={getLangText('Click to remove edition')}> {content}
{ content }
</ModalWrapper> </ModalWrapper>
); );
} }

View File

@ -12,6 +12,10 @@ import UserActions from '../../actions/user_actions';
import UserStore from '../../stores/user_store'; import UserStore from '../../stores/user_store';
import CoaActions from '../../actions/coa_actions'; import CoaActions from '../../actions/coa_actions';
import CoaStore from '../../stores/coa_store'; import CoaStore from '../../stores/coa_store';
import PieceListActions from '../../actions/piece_list_actions';
import PieceListStore from '../../stores/piece_list_store';
import EditionListActions from '../../actions/edition_list_actions';
import MediaContainer from './media_container'; import MediaContainer from './media_container';
@ -24,13 +28,11 @@ import InputTextAreaToggable from './../ascribe_forms/input_textarea_toggable';
import EditionFurtherDetails from './further_details'; import EditionFurtherDetails from './further_details';
//import PieceExtraDataForm from './../ascribe_forms/form_piece_extradata';
import RequestActionForm from './../ascribe_forms/form_request_action'; import RequestActionForm from './../ascribe_forms/form_request_action';
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';
import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button'; import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button';
import DeleteButton from '../ascribe_buttons/delete_button';
//import ReactS3FineUploader from './../ascribe_uploader/react_s3_fine_uploader';
import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions'; import GlobalNotificationActions from '../../actions/global_notification_actions';
@ -39,6 +41,7 @@ import apiUrls from '../../constants/api_urls';
import AppConstants from '../../constants/application_constants'; import AppConstants from '../../constants/application_constants';
import { getLangText } from '../../utils/lang_utils'; import { getLangText } from '../../utils/lang_utils';
import { mergeOptions } from '../../utils/general_utils';
let Link = Router.Link; let Link = Router.Link;
/** /**
@ -50,23 +53,44 @@ let Edition = React.createClass({
loadEdition: React.PropTypes.func loadEdition: React.PropTypes.func
}, },
mixins: [Router.Navigation],
getInitialState() { getInitialState() {
return UserStore.getState(); return mergeOptions(
UserStore.getState(),
PieceListStore.getState()
);
}, },
componentDidMount() { componentDidMount() {
UserStore.listen(this.onChange); UserStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserActions.fetchCurrentUser(); UserActions.fetchCurrentUser();
}, },
componentWillUnmount() { componentWillUnmount() {
UserStore.unlisten(this.onChange); UserStore.unlisten(this.onChange);
PieceListStore.unlisten(this.onChange);
}, },
onChange(state) { onChange(state) {
this.setState(state); this.setState(state);
}, },
handleDeleteSuccess(response) {
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
// we don't need to refresh the edition list for a piece here, since its reloaded from
// scatch once you click on show-editions anyway
EditionListActions.closeAllEditionLists();
EditionListActions.clearAllEditionSelections();
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
this.transitionTo('pieces');
},
render() { render() {
return ( return (
<Row> <Row>
@ -84,7 +108,8 @@ let Edition = React.createClass({
<EditionSummary <EditionSummary
handleSuccess={this.props.loadEdition} handleSuccess={this.props.loadEdition}
currentUser={this.state.currentUser} currentUser={this.state.currentUser}
edition={this.props.edition} /> edition={this.props.edition}
handleDeleteSuccess={this.handleDeleteSuccess}/>
<CollapsibleParagraph <CollapsibleParagraph
title={getLangText('Certificate of Authenticity')} title={getLangText('Certificate of Authenticity')}
@ -157,6 +182,7 @@ let EditionSummary = React.createClass({
edition: React.PropTypes.object, edition: React.PropTypes.object,
handleSuccess: React.PropTypes.func, handleSuccess: React.PropTypes.func,
currentUser: React.PropTypes.object currentUser: React.PropTypes.object
handleDeleteSuccess: React.PropTypes.func
}, },
getTransferWithdrawData(){ getTransferWithdrawData(){
@ -176,14 +202,13 @@ let EditionSummary = React.createClass({
status = <EditionDetailProperty label="STATUS" value={ statusStr }/>; status = <EditionDetailProperty label="STATUS" value={ statusStr }/>;
if (this.props.edition.pending_new_owner && this.props.edition.acl.acl_withdraw_transfer){ if (this.props.edition.pending_new_owner && this.props.edition.acl.acl_withdraw_transfer){
status = ( status = (
<EditionDetailProperty label="STATUS" value={ statusStr } />
<EditionDetailProperty label="STATUS" value={ statusStr } />
); );
} }
} }
return status; return status;
}, },
getActions(){ getActions(){
let actions = null; let actions = null;
if (this.props.edition.request_action && this.props.edition.request_action.length > 0){ if (this.props.edition.request_action && this.props.edition.request_action.length > 0){
@ -227,6 +252,9 @@ let EditionSummary = React.createClass({
editions={[this.props.edition]} editions={[this.props.edition]}
handleSuccess={this.props.handleSuccess}> handleSuccess={this.props.handleSuccess}>
{withdrawButton} {withdrawButton}
<DeleteButton
handleSuccess={this.props.handleDeleteSuccess}
editions={[this.props.edition]}/>
{unconsignRequestButton} {unconsignRequestButton}
</AclButtonList> </AclButtonList>
</Col> </Col>

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
import React from 'react'; import React from 'react';
import Router from 'react-router';
import Row from 'react-bootstrap/lib/Row'; import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col'; import Col from 'react-bootstrap/lib/Col';
@ -14,6 +15,11 @@ import FurtherDetails from './further_details';
import UserActions from '../../actions/user_actions'; import UserActions from '../../actions/user_actions';
import UserStore from '../../stores/user_store'; import UserStore from '../../stores/user_store';
import PieceListActions from '../../actions/piece_list_actions';
import PieceListStore from '../../stores/piece_list_store';
import EditionListActions from '../../actions/edition_list_actions';
import PieceActions from '../../actions/piece_actions'; import PieceActions from '../../actions/piece_actions';
import MediaContainer from './media_container'; import MediaContainer from './media_container';
@ -23,6 +29,10 @@ import EditionDetailProperty from './detail_property';
import AclButtonList from './../ascribe_buttons/acl_button_list'; import AclButtonList from './../ascribe_buttons/acl_button_list';
import CreateEditionsForm from '../ascribe_forms/create_editions_form'; import CreateEditionsForm from '../ascribe_forms/create_editions_form';
import CreateEditionsButton from '../ascribe_buttons/create_editions_button'; import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
import DeleteButton from '../ascribe_buttons/delete_button';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
import { getLangText } from '../../utils/lang_utils'; import { getLangText } from '../../utils/lang_utils';
import { mergeOptions } from '../../utils/general_utils'; import { mergeOptions } from '../../utils/general_utils';
@ -36,9 +46,12 @@ let Piece = React.createClass({
loadPiece: React.PropTypes.func loadPiece: React.PropTypes.func
}, },
mixins: [Router.Navigation],
getInitialState() { getInitialState() {
return mergeOptions( return mergeOptions(
UserStore.getState(), UserStore.getState(),
PieceListStore.getState(),
{ {
showCreateEditionsDialog: false showCreateEditionsDialog: false
} }
@ -47,11 +60,13 @@ let Piece = React.createClass({
componentDidMount() { componentDidMount() {
UserStore.listen(this.onChange); UserStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserActions.fetchCurrentUser(); UserActions.fetchCurrentUser();
}, },
componentWillUnmount() { componentWillUnmount() {
UserStore.unlisten(this.onChange); UserStore.unlisten(this.onChange);
PieceListStore.unlisten(this.onChange);
}, },
onChange(state) { onChange(state) {
@ -69,6 +84,20 @@ let Piece = React.createClass({
this.toggleCreateEditionsDialog(); this.toggleCreateEditionsDialog();
}, },
handleDeleteSuccess(response) {
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
// since we're deleting a piece, we just need to close
// all editions dialogs and not reload them
EditionListActions.closeAllEditionLists();
EditionListActions.clearAllEditionSelections();
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
this.transitionTo('pieces');
},
getCreateEditionsDialog() { getCreateEditionsDialog() {
if(this.props.piece.num_editions < 1 && this.state.showCreateEditionsDialog) { if(this.props.piece.num_editions < 1 && this.state.showCreateEditionsDialog) {
return ( return (
@ -89,6 +118,9 @@ let Piece = React.createClass({
key: 'num_editions', key: 'num_editions',
value: numEditions value: numEditions
}); });
let notification = new GlobalNotificationModel('Editions successfully created', 'success', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
}, },
render() { render() {
@ -121,6 +153,9 @@ let Piece = React.createClass({
piece={this.props.piece} piece={this.props.piece}
toggleCreateEditionsDialog={this.toggleCreateEditionsDialog} toggleCreateEditionsDialog={this.toggleCreateEditionsDialog}
onPollingSuccess={this.handlePollingSuccess}/> onPollingSuccess={this.handlePollingSuccess}/>
<DeleteButton
handleSuccess={this.handleDeleteSuccess}
piece={this.props.piece}/>
</AclButtonList> </AclButtonList>
{this.getCreateEditionsDialog()} {this.getCreateEditionsDialog()}

View File

@ -59,7 +59,6 @@ let Form = React.createClass({
for (let ref in this.refs){ for (let ref in this.refs){
data[this.refs[ref].props.name] = this.refs[ref].state.value; data[this.refs[ref].props.name] = this.refs[ref].state.value;
} }
console.log(data);
if ('getFormData' in this.props){ if ('getFormData' in this.props){
data = mergeOptionsWithDuplicates(data, this.props.getFormData()); data = mergeOptionsWithDuplicates(data, this.props.getFormData());
} }

View File

@ -0,0 +1,41 @@
'use strict';
import React from 'react';
import requests from '../../utils/requests';
import ApiUrls from '../../constants/api_urls';
import FormMixin from '../../mixins/form_mixin';
import { getLangText } from '../../utils/lang_utils';
let PieceDeleteForm = React.createClass({
propTypes: {
pieceId: React.PropTypes.number
},
mixins: [FormMixin],
url() {
return requests.prepareUrl(ApiUrls.piece, {piece_id: this.props.pieceId});
},
httpVerb() {
return 'delete';
},
renderForm () {
return (
<div className="modal-body">
<p>{getLangText('Are you sure you would like to permanently delete this piece')}&#63;</p>
<p>{getLangText('This is an irrevocable action%s', '.')}</p>
<div className="modal-footer">
<button type="submit" className="btn btn-danger btn-delete btn-sm ascribe-margin-1px" onClick={this.submit}>{getLangText('YES, DELETE')}</button>
<button className="btn btn-default btn-sm ascribe-margin-1px" style={{marginLeft: '0'}}
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</button>
</div>
</div>
);
}
});
export default PieceDeleteForm;

View File

@ -12,13 +12,9 @@ let EditionRemoveFromCollectionForm = React.createClass({
mixins: [FormMixin], mixins: [FormMixin],
url() { url() {
if (this.props.editions.constructor === Array) { return requests.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()});
return requests.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()});
}
else {
return requests.prepareUrl(apiUrls.piece_remove_from_collection, {piece_id: this.props.editions.id});
}
}, },
httpVerb(){ httpVerb(){
return 'delete'; return 'delete';
}, },

View File

@ -0,0 +1,42 @@
'use strict';
import React from 'react';
import { getLangText } from '../../utils/lang_utils.js';
import requests from '../../utils/requests';
import apiUrls from '../../constants/api_urls';
import FormMixin from '../../mixins/form_mixin';
let PieceRemoveFromCollectionForm = React.createClass({
propTypes: {
pieceId: React.PropTypes.number
},
mixins: [FormMixin],
url() {
return requests.prepareUrl(apiUrls.piece_remove_from_collection, {piece_id: this.props.pieceId});
},
httpVerb(){
return 'delete';
},
renderForm () {
return (
<div className="modal-body">
<p>{getLangText('Are you sure you would like to remove this piece from your collection')}&#63;</p>
<p>{getLangText('This is an irrevocable action%s', '.')}</p>
<div className="modal-footer">
<button type="submit" className="btn btn-danger btn-delete btn-sm ascribe-margin-1px" onClick={this.submit}>{getLangText('YES, REMOVE')}</button>
<button className="btn btn-default btn-sm ascribe-margin-1px" style={{marginLeft: '0'}}
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</button>
</div>
</div>
);
}
});
export default PieceRemoveFromCollectionForm;

View File

@ -17,24 +17,41 @@ let ModalWrapper = React.createClass({
handleSuccess: React.PropTypes.func.isRequired, handleSuccess: React.PropTypes.func.isRequired,
button: React.PropTypes.object.isRequired, button: React.PropTypes.object.isRequired,
children: React.PropTypes.object, children: React.PropTypes.object,
tooltip: React.PropTypes.string.isRequired tooltip: React.PropTypes.string
},
getModalTrigger() {
return (
<ModalTrigger modal={
<ModalBody
title={this.props.title}
handleSuccess={this.props.handleSuccess}>
{this.props.children}
</ModalBody>
}>
{this.props.button}
</ModalTrigger>
);
}, },
render() { render() {
return ( if(this.props.tooltip) {
<OverlayTrigger delay={500} placement="left" return (
overlay={<Tooltip>{this.props.tooltip}</Tooltip>}> <OverlayTrigger
<ModalTrigger modal={ delay={500}
<ModalBody placement="left"
title={this.props.title} overlay={<Tooltip>{this.props.tooltip}</Tooltip>}>
handleSuccess={this.props.handleSuccess}> {this.getModalTrigger()}
{this.props.children} </OverlayTrigger>
</ModalBody> );
}> } else {
{this.props.button} return (
</ModalTrigger> <span>
</OverlayTrigger> {/* This needs to be some kind of inline-block */}
); {this.getModalTrigger()}
</span>
);
}
} }
}); });

View File

@ -10,9 +10,12 @@ import EditionListActions from '../../actions/edition_list_actions';
import UserStore from '../../stores/user_store'; import UserStore from '../../stores/user_store';
import UserActions from '../../actions/user_actions'; import UserActions from '../../actions/user_actions';
import PieceListStore from '../../stores/piece_list_store';
import PieceListActions from '../../actions/piece_list_actions';
import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget'; import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget';
import AclButtonList from '../ascribe_buttons/acl_button_list'; import AclButtonList from '../ascribe_buttons/acl_button_list';
import DeleteButton from '../ascribe_buttons/delete_button';
import { getAvailableAcls } from '../../utils/acl_utils'; import { getAvailableAcls } from '../../utils/acl_utils';
import { getLangText } from '../../utils/lang_utils.js'; import { getLangText } from '../../utils/lang_utils.js';
@ -23,7 +26,11 @@ let PieceListBulkModal = React.createClass({
}, },
getInitialState() { getInitialState() {
return mergeOptions(EditionListStore.getState(), UserStore.getState()); return mergeOptions(
EditionListStore.getState(),
UserStore.getState(),
PieceListStore.getState()
);
}, },
onChange(state) { onChange(state) {
@ -69,13 +76,11 @@ let PieceListBulkModal = React.createClass({
}, },
handleSuccess() { handleSuccess() {
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
this.fetchSelectedPieceEditionList() this.fetchSelectedPieceEditionList()
.forEach((pieceId) => { .forEach((pieceId) => {
let editionsForPiece = this.state.editionList[pieceId]; EditionListActions.refreshEditionList(pieceId);
for(let i = 1; i <= editionsForPiece.page; i++) {
EditionListActions.fetchEditionList(pieceId, i, editionsForPiece.pageSize, editionsForPiece.orderBy, editionsForPiece.orderAsc);
}
}); });
EditionListActions.clearAllEditionSelections(); EditionListActions.clearAllEditionSelections();
}, },
@ -106,7 +111,11 @@ let PieceListBulkModal = React.createClass({
availableAcls={availableAcls} availableAcls={availableAcls}
editions={selectedEditions} editions={selectedEditions}
handleSuccess={this.handleSuccess} handleSuccess={this.handleSuccess}
className="text-center ascribe-button-list collapse-group"/> className="text-center ascribe-button-list collapse-group">
<DeleteButton
handleSuccess={this.handleSuccess}
editions={selectedEditions}/>
</AclButtonList>
</div> </div>
</div> </div>
</div> </div>

View File

@ -10,6 +10,7 @@ let TableItemAclFiltered = React.createClass({
}, },
render() { render() {
var availableAcls = ['acl_consign', 'acl_loan', 'acl_transfer', 'acl_view', 'acl_share', 'acl_unshare', 'acl_delete'];
if (this.props.requestAction){ if (this.props.requestAction){
return ( return (
<span> <span>
@ -17,7 +18,6 @@ let TableItemAclFiltered = React.createClass({
</span> </span>
); );
} }
var availableAcls = ['acl_consign', 'acl_loan', 'acl_transfer', 'acl_view', 'acl_share', 'acl_unshare'];
let filteredAcls = Object.keys(this.props.content).filter((key) => { let filteredAcls = Object.keys(this.props.content).filter((key) => {
return availableAcls.indexOf(key) > -1 && this.props.content[key]; return availableAcls.indexOf(key) > -1 && this.props.content[key];

View File

@ -56,6 +56,31 @@ class EditionListStore {
this.editionList[pieceId].count = count; this.editionList[pieceId].count = count;
} }
/**
* We often just have to refresh the edition list for a certain pieceId,
* this method provides exactly that functionality without any side effects
*/
onRefreshEditionList(pieceId) {
const prevEditionListLength = this.editionList[pieceId].length;
const prevEditionListPage = this.editionList[pieceId].page;
const prevEditionListPageSize = this.editionList[pieceId].pageSize;
// to clear an array, david walsh recommends to just set it's length to zero
// http://davidwalsh.name/empty-array
this.editionList[pieceId].length = 0;
// refetch editions with adjusted page size
EditionsListActions.fetchEditionList(pieceId, 1, prevEditionListLength, this.editionList[pieceId].orderBy, this.editionList[pieceId].orderAsc)
.then(() => {
// reset back to the normal pageSize and page
this.editionList[pieceId].page = prevEditionListPage;
this.editionList[pieceId].pageSize = prevEditionListPageSize;
})
.catch((err) => {
console.error(err);
});
}
onSelectEdition({pieceId, editionId, toValue}) { onSelectEdition({pieceId, editionId, toValue}) {
this.editionList[pieceId].forEach((edition) => { this.editionList[pieceId].forEach((edition) => {

View File

@ -8,7 +8,7 @@ function intersectAcls(a, b) {
export function getAvailableAcls(editions, filterFn) { export function getAvailableAcls(editions, filterFn) {
let availableAcls = []; let availableAcls = [];
if (editions.constructor !== Array){ if (!editions || editions.constructor !== Array){
return []; return [];
} }
// if you copy a javascript array of objects using slice, then // if you copy a javascript array of objects using slice, then

View File

@ -54,6 +54,11 @@ class Requests {
} }
getUrl(url) { getUrl(url) {
// Handle case, that the url string is not defined at all
if (!url) {
throw new Error('Url was not defined and could therefore not be mapped.');
}
let name = url; let name = url;
if (!url.match(/^http/)) { if (!url.match(/^http/)) {
url = this.urlMap[url]; url = this.urlMap[url];
@ -66,9 +71,16 @@ class Requests {
} }
prepareUrl(url, params, attachParamsToQuery) { prepareUrl(url, params, attachParamsToQuery) {
let newUrl = this.getUrl(url); let newUrl;
let re = /\${(\w+)}/g; let re = /\${(\w+)}/g;
// catch errors and throw them to react
try {
newUrl = this.getUrl(url);
} catch(err) {
throw err;
}
newUrl = newUrl.replace(re, (match, key) => { newUrl = newUrl.replace(re, (match, key) => {
let val = params[key]; let val = params[key];
if (!val) { if (!val) {