'use strict'; import React from 'react'; import { History } from 'react-router'; import Moment from 'moment'; import ReactError from '../../mixins/react_error'; import { ResourceNotFoundError } from '../../models/errors'; import EditionListActions from '../../actions/edition_list_actions'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; import PieceActions from '../../actions/piece_actions'; import PieceStore from '../../stores/piece_store'; import PieceListActions from '../../actions/piece_list_actions'; import PieceListStore from '../../stores/piece_list_store'; import FurtherDetails from './further_details'; import DetailProperty from './detail_property'; import HistoryIterator from './history_iterator'; import LicenseDetail from './license_detail'; import Note from './note'; import Piece from './piece'; import AclButtonList from './../ascribe_buttons/acl_button_list'; import AclInformation from '../ascribe_buttons/acl_information'; import CreateEditionsButton from '../ascribe_buttons/create_editions_button'; import DeleteButton from '../ascribe_buttons/delete_button'; import CollapsibleParagraph from './../ascribe_collapsible/collapsible_paragraph'; import CreateEditionsForm from '../ascribe_forms/create_editions_form'; import ListRequestActions from '../ascribe_forms/list_form_request_actions'; import AclProxy from '../acl_proxy'; import ApiUrls from '../../constants/api_urls'; import AscribeSpinner from '../ascribe_spinner'; import { mergeOptions } from '../../utils/general_utils'; import { getLangText } from '../../utils/lang_utils'; import { setDocumentTitle } from '../../utils/dom_utils'; /** * This is the component that implements resource/data specific functionality */ let PieceContainer = React.createClass({ propTypes: { furtherDetailsType: React.PropTypes.func, // Provided from AscribeApp currentUser: React.PropTypes.object.isRequired, whitelabel: React.PropTypes.object, // Provided from router location: React.PropTypes.object, params: React.PropTypes.object }, mixins: [History, ReactError], getDefaultProps() { return { furtherDetailsType: FurtherDetails }; }, getInitialState() { return mergeOptions( PieceListStore.getState(), PieceStore.getInitialState(), { showCreateEditionsDialog: false } ); }, componentDidMount() { PieceListStore.listen(this.onChange); PieceStore.listen(this.onChange); this.loadPiece(); }, // This is done to update the container when the user clicks on the prev or next // button to update the URL parameter (and therefore to switch pieces) or // when the user clicks on a notification while being in another piece view componentWillReceiveProps(nextProps) { if (this.props.params.pieceId !== nextProps.params.pieceId) { PieceActions.flushPiece(); this.loadPiece(nextProps.params.pieceId); } }, componentDidUpdate() { const { err: pieceErr } = this.state.pieceMeta; if (pieceErr && pieceErr.json && pieceErr.json.status === 404) { this.throws(new ResourceNotFoundError(getLangText("Oops, the piece you're looking for doesn't exist."))); } }, componentWillUnmount() { PieceStore.unlisten(this.onChange); PieceListStore.unlisten(this.onChange); }, onChange(state) { /* ATTENTION: THIS IS JUST A TEMPORARY USABILITY FIX THAT ESSENTIALLY REMOVES THE LOAN BUTTON FROM THE PIECE DETAIL PAGE SO THAT USERS DO NOT CONFUSE A PIECE WITH AN EDITION. IT SHOULD BE REMOVED AND REPLACED WITH A BETTER SOLUTION ASAP! ALSO, WE ENABLED THE LOAN BUTTON FOR IKONOTV TO LET THEM LOAN ON A PIECE LEVEL */ if (state && state.piece && state.piece.acl && typeof state.piece.acl.acl_loan !== 'undefined') { let pieceState = mergeOptions({}, state.piece); pieceState.acl.acl_loan = false; this.setState({ piece: pieceState }); } else { this.setState(state); } }, loadPiece(pieceId = this.props.params.pieceId) { PieceActions.fetchPiece(pieceId); }, toggleCreateEditionsDialog() { this.setState({ showCreateEditionsDialog: !this.state.showCreateEditionsDialog }); }, handleEditionCreationSuccess() { const { filterBy, orderAsc, orderBy, page, pageSize, search } = this.state; PieceActions.updateProperty({ key: 'num_editions', value: 0 }); PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy }); this.toggleCreateEditionsDialog(); }, handleDeleteSuccess(response) { const { filterBy, orderAsc, orderBy, page, pageSize, search } = this.state; PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy }); // since we're deleting a piece, we just need to close // all editions dialogs and not reload them EditionListActions.closeAllEditionLists(); EditionListActions.clearAllEditionSelections(); const notification = new GlobalNotificationModel(response.notification, 'success'); GlobalNotificationActions.appendGlobalNotification(notification); this.history.push('/collection'); }, getCreateEditionsDialog() { if (this.state.piece.num_editions < 1 && this.state.showCreateEditionsDialog) { return (