mirror of
https://github.com/ascribe/onion.git
synced 2025-02-14 21:10:27 +01:00
Merge pull request #105 from ascribe/AD-1558-piece-and-edition-detail-show-stale-data
AD-1558 Piece and edition detail show stale data
This commit is contained in:
commit
821fe79461
@ -7,11 +7,11 @@ class EditionActions {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.generateActions(
|
this.generateActions(
|
||||||
'fetchEdition',
|
'fetchEdition',
|
||||||
'successFetchEdition',
|
|
||||||
'successFetchCoa',
|
'successFetchCoa',
|
||||||
'flushEdition',
|
'successFetchEdition',
|
||||||
'errorCoa',
|
'errorCoa',
|
||||||
'errorEdition'
|
'errorEdition',
|
||||||
|
'flushEdition'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { alt } from '../alt';
|
import { alt } from '../alt';
|
||||||
import PieceFetcher from '../fetchers/piece_fetcher';
|
|
||||||
|
|
||||||
|
|
||||||
class PieceActions {
|
class PieceActions {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.generateActions(
|
this.generateActions(
|
||||||
|
'fetchPiece',
|
||||||
|
'successFetchPiece',
|
||||||
|
'errorPiece',
|
||||||
|
'flushPiece',
|
||||||
'updatePiece',
|
'updatePiece',
|
||||||
'updateProperty',
|
'updateProperty'
|
||||||
'pieceFailed'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchOne(pieceId) {
|
|
||||||
PieceFetcher.fetchOne(pieceId)
|
|
||||||
.then((res) => {
|
|
||||||
this.actions.updatePiece(res.piece);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.logGlobal(err);
|
|
||||||
this.actions.pieceFailed(err.json);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default alt.createActions(PieceActions);
|
export default alt.createActions(PieceActions);
|
||||||
|
@ -35,7 +35,7 @@ let EditionContainer = React.createClass({
|
|||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
EditionStore.getState(),
|
EditionStore.getInitialState(),
|
||||||
UserStore.getState()
|
UserStore.getState()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -44,27 +44,23 @@ let EditionContainer = React.createClass({
|
|||||||
EditionStore.listen(this.onChange);
|
EditionStore.listen(this.onChange);
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
|
|
||||||
// Every time we're entering the edition detail page,
|
this.loadEdition();
|
||||||
// just reset the edition that is saved in the edition store
|
|
||||||
// as it will otherwise display wrong/old data once the user loads
|
|
||||||
// the edition detail a second time
|
|
||||||
EditionActions.flushEdition();
|
|
||||||
EditionActions.fetchEdition(this.props.params.editionId);
|
|
||||||
|
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
},
|
},
|
||||||
|
|
||||||
// This is done to update the container when the user clicks on the prev or next
|
// 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)
|
// button to update the URL parameter (and therefore to switch pieces)
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if(this.props.params.editionId !== nextProps.params.editionId) {
|
if (this.props.params.editionId !== nextProps.params.editionId) {
|
||||||
EditionActions.fetchEdition(this.props.params.editionId);
|
EditionActions.flushEdition();
|
||||||
|
this.loadEdition(nextProps.params.editionId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const { editionMeta } = this.state;
|
const { err: editionErr } = this.state.editionMeta;
|
||||||
if(editionMeta.err && editionMeta.err.json && editionMeta.err.json.status === 404) {
|
|
||||||
|
if (editionErr && editionErr.json && editionErr.json.status === 404) {
|
||||||
this.throws(new ResourceNotFoundError(getLangText("Oops, the edition you're looking for doesn't exist.")));
|
this.throws(new ResourceNotFoundError(getLangText("Oops, the edition you're looking for doesn't exist.")));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -81,18 +77,22 @@ let EditionContainer = React.createClass({
|
|||||||
if(state && state.edition && state.edition.digital_work) {
|
if(state && state.edition && state.edition.digital_work) {
|
||||||
let isEncoding = state.edition.digital_work.isEncoding;
|
let isEncoding = state.edition.digital_work.isEncoding;
|
||||||
if (state.edition.digital_work.mime === 'video' && typeof isEncoding === 'number' && isEncoding !== 100 && !this.state.timerId) {
|
if (state.edition.digital_work.mime === 'video' && typeof isEncoding === 'number' && isEncoding !== 100 && !this.state.timerId) {
|
||||||
let timerId = window.setInterval(() => EditionActions.fetchOne(this.props.params.editionId), 10000);
|
let timerId = window.setInterval(() => EditionActions.fetchEdition(this.props.params.editionId), 10000);
|
||||||
this.setState({timerId: timerId});
|
this.setState({timerId: timerId});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadEdition(editionId = this.props.params.editionId) {
|
||||||
|
EditionActions.fetchEdition(editionId);
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { edition, currentUser, coaMeta } = this.state;
|
const { edition, currentUser, coaMeta } = this.state;
|
||||||
const { actionPanelButtonListType, furtherDetailsType } = this.props;
|
const { actionPanelButtonListType, furtherDetailsType } = this.props;
|
||||||
|
|
||||||
if (Object.keys(edition).length && edition.id) {
|
if (edition.id) {
|
||||||
setDocumentTitle([edition.artist_name, edition.title].join(', '));
|
setDocumentTitle(`${edition.artist_name}, ${edition.title}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Edition
|
<Edition
|
||||||
@ -101,7 +101,7 @@ let EditionContainer = React.createClass({
|
|||||||
edition={edition}
|
edition={edition}
|
||||||
coaError={coaMeta.err}
|
coaError={coaMeta.err}
|
||||||
currentUser={currentUser}
|
currentUser={currentUser}
|
||||||
loadEdition={() => EditionActions.fetchEdition(this.props.params.editionId)} />
|
loadEdition={this.loadEdition} />
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
@ -5,25 +5,27 @@ import React from 'react';
|
|||||||
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';
|
||||||
|
|
||||||
import Form from './../ascribe_forms/form';
|
|
||||||
|
|
||||||
import PieceExtraDataForm from './../ascribe_forms/form_piece_extradata';
|
|
||||||
|
|
||||||
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';
|
||||||
|
|
||||||
import FurtherDetailsFileuploader from './further_details_fileuploader';
|
import FurtherDetailsFileuploader from './further_details_fileuploader';
|
||||||
|
|
||||||
|
import Form from './../ascribe_forms/form';
|
||||||
|
import PieceExtraDataForm from './../ascribe_forms/form_piece_extradata';
|
||||||
|
|
||||||
import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||||
|
|
||||||
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
let FurtherDetails = React.createClass({
|
let FurtherDetails = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
pieceId: React.PropTypes.number.isRequired,
|
||||||
|
|
||||||
editable: React.PropTypes.bool,
|
editable: React.PropTypes.bool,
|
||||||
pieceId: React.PropTypes.number,
|
|
||||||
extraData: React.PropTypes.object,
|
extraData: React.PropTypes.object,
|
||||||
|
handleSuccess: React.PropTypes.func,
|
||||||
otherData: React.PropTypes.arrayOf(React.PropTypes.object),
|
otherData: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||||
handleSuccess: React.PropTypes.func
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
@ -32,13 +34,18 @@ let FurtherDetails = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
showNotification(){
|
showNotification() {
|
||||||
this.props.handleSuccess();
|
const { handleSuccess } = this.props;
|
||||||
let notification = new GlobalNotificationModel('Details updated', 'success');
|
|
||||||
|
if (typeof handleSucess === 'function') {
|
||||||
|
handleSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
const notification = new GlobalNotificationModel(getLangText('Details updated'), 'success');
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
submitFile(file){
|
submitFile(file) {
|
||||||
this.setState({
|
this.setState({
|
||||||
otherDataKey: file.key
|
otherDataKey: file.key
|
||||||
});
|
});
|
||||||
@ -60,8 +67,7 @@ let FurtherDetails = React.createClass({
|
|||||||
handleSuccess={this.showNotification}
|
handleSuccess={this.showNotification}
|
||||||
editable={this.props.editable}
|
editable={this.props.editable}
|
||||||
pieceId={this.props.pieceId}
|
pieceId={this.props.pieceId}
|
||||||
extraData={this.props.extraData}
|
extraData={this.props.extraData} />
|
||||||
/>
|
|
||||||
<PieceExtraDataForm
|
<PieceExtraDataForm
|
||||||
name='display_instructions'
|
name='display_instructions'
|
||||||
title='Display Instructions'
|
title='Display Instructions'
|
||||||
|
@ -28,7 +28,7 @@ let Piece = React.createClass({
|
|||||||
|
|
||||||
|
|
||||||
updateObject() {
|
updateObject() {
|
||||||
return PieceActions.fetchOne(this.props.piece.id);
|
return PieceActions.fetchPiece(this.props.piece.id);
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -69,7 +69,7 @@ let PieceContainer = React.createClass({
|
|||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
UserStore.getState(),
|
UserStore.getState(),
|
||||||
PieceListStore.getState(),
|
PieceListStore.getState(),
|
||||||
PieceStore.getState(),
|
PieceStore.getInitialState(),
|
||||||
{
|
{
|
||||||
showCreateEditionsDialog: false
|
showCreateEditionsDialog: false
|
||||||
}
|
}
|
||||||
@ -81,19 +81,24 @@ let PieceContainer = React.createClass({
|
|||||||
PieceListStore.listen(this.onChange);
|
PieceListStore.listen(this.onChange);
|
||||||
PieceStore.listen(this.onChange);
|
PieceStore.listen(this.onChange);
|
||||||
|
|
||||||
// Every time we enter the piece detail page, just reset the piece
|
|
||||||
// store as it will otherwise display wrong/old data once the user loads
|
|
||||||
// the piece detail a second time
|
|
||||||
PieceActions.updatePiece({});
|
|
||||||
|
|
||||||
this.loadPiece();
|
this.loadPiece();
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate() {
|
// This is done to update the container when the user clicks on the prev or next
|
||||||
const { pieceError } = this.state;
|
// 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);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
if (pieceError && pieceError.status === 404) {
|
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.")));
|
this.throws(new ResourceNotFoundError(getLangText("Oops, the piece you're looking for doesn't exist.")));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -116,8 +121,7 @@ let PieceContainer = React.createClass({
|
|||||||
ALSO, WE ENABLED THE LOAN BUTTON FOR IKONOTV TO LET THEM LOAN ON A PIECE LEVEL
|
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') {
|
if (state && state.piece && state.piece.acl && typeof state.piece.acl.acl_loan !== 'undefined') {
|
||||||
|
|
||||||
let pieceState = mergeOptions({}, state.piece);
|
let pieceState = mergeOptions({}, state.piece);
|
||||||
pieceState.acl.acl_loan = false;
|
pieceState.acl.acl_loan = false;
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -129,11 +133,10 @@ let PieceContainer = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
loadPiece() {
|
loadPiece(pieceId = this.props.params.pieceId) {
|
||||||
PieceActions.fetchOne(this.props.params.pieceId);
|
PieceActions.fetchPiece(pieceId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
toggleCreateEditionsDialog() {
|
toggleCreateEditionsDialog() {
|
||||||
this.setState({
|
this.setState({
|
||||||
showCreateEditionsDialog: !this.state.showCreateEditionsDialog
|
showCreateEditionsDialog: !this.state.showCreateEditionsDialog
|
||||||
@ -143,8 +146,9 @@ let PieceContainer = React.createClass({
|
|||||||
handleEditionCreationSuccess() {
|
handleEditionCreationSuccess() {
|
||||||
const { filterBy, orderAsc, orderBy, page, pageSize, search } = this.state;
|
const { filterBy, orderAsc, orderBy, page, pageSize, search } = this.state;
|
||||||
|
|
||||||
PieceActions.updateProperty({key: 'num_editions', value: 0});
|
PieceActions.updateProperty({ key: 'num_editions', value: 0 });
|
||||||
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
|
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
|
||||||
|
|
||||||
this.toggleCreateEditionsDialog();
|
this.toggleCreateEditionsDialog();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -158,24 +162,24 @@ let PieceContainer = React.createClass({
|
|||||||
EditionListActions.closeAllEditionLists();
|
EditionListActions.closeAllEditionLists();
|
||||||
EditionListActions.clearAllEditionSelections();
|
EditionListActions.clearAllEditionSelections();
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
const notification = new GlobalNotificationModel(response.notification, 'success');
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
this.history.push('/collection');
|
this.history.push('/collection');
|
||||||
},
|
},
|
||||||
|
|
||||||
getCreateEditionsDialog() {
|
getCreateEditionsDialog() {
|
||||||
if(this.state.piece.num_editions < 1 && this.state.showCreateEditionsDialog) {
|
if (this.state.piece.num_editions < 1 && this.state.showCreateEditionsDialog) {
|
||||||
return (
|
return (
|
||||||
<div style={{marginTop: '1em'}}>
|
<div style={{marginTop: '1em'}}>
|
||||||
<CreateEditionsForm
|
<CreateEditionsForm
|
||||||
pieceId={this.state.piece.id}
|
pieceId={this.state.piece.id}
|
||||||
handleSuccess={this.handleEditionCreationSuccess} />
|
handleSuccess={this.handleEditionCreationSuccess} />
|
||||||
<hr/>
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (<hr/>);
|
return (<hr />);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -194,24 +198,24 @@ let PieceContainer = React.createClass({
|
|||||||
// Therefore we need to at least refetch the changed piece from the server or on our case simply all
|
// Therefore we need to at least refetch the changed piece from the server or on our case simply all
|
||||||
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
|
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel('Editions successfully created', 'success', 10000);
|
const notification = new GlobalNotificationModel(getLangText('Editions successfully created'), 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
getId() {
|
getId() {
|
||||||
return {'id': this.state.piece.id};
|
return { 'id': this.state.piece.id };
|
||||||
},
|
},
|
||||||
|
|
||||||
getActions() {
|
getActions() {
|
||||||
const { piece, currentUser } = this.state;
|
const { piece, currentUser } = this.state;
|
||||||
|
|
||||||
if (piece && piece.notifications && piece.notifications.length > 0) {
|
if (piece.notifications && piece.notifications.length > 0) {
|
||||||
return (
|
return (
|
||||||
<ListRequestActions
|
<ListRequestActions
|
||||||
pieceOrEditions={piece}
|
pieceOrEditions={piece}
|
||||||
currentUser={currentUser}
|
currentUser={currentUser}
|
||||||
handleSuccess={this.loadPiece}
|
handleSuccess={this.loadPiece}
|
||||||
notifications={piece.notifications}/>);
|
notifications={piece.notifications} />);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<AclProxy
|
<AclProxy
|
||||||
@ -237,12 +241,12 @@ let PieceContainer = React.createClass({
|
|||||||
onPollingSuccess={this.handlePollingSuccess}/>
|
onPollingSuccess={this.handlePollingSuccess}/>
|
||||||
<DeleteButton
|
<DeleteButton
|
||||||
handleSuccess={this.handleDeleteSuccess}
|
handleSuccess={this.handleDeleteSuccess}
|
||||||
piece={piece}/>
|
piece={piece} />
|
||||||
<AclInformation
|
<AclInformation
|
||||||
aim="button"
|
aim="button"
|
||||||
verbs={['acl_share', 'acl_transfer', 'acl_create_editions', 'acl_loan', 'acl_delete',
|
verbs={['acl_share', 'acl_transfer', 'acl_create_editions', 'acl_loan', 'acl_delete',
|
||||||
'acl_consign']}
|
'acl_consign']}
|
||||||
aclObject={piece.acl}/>
|
aclObject={piece.acl} />
|
||||||
</AclButtonList>
|
</AclButtonList>
|
||||||
</DetailProperty>
|
</DetailProperty>
|
||||||
</AclProxy>
|
</AclProxy>
|
||||||
@ -254,8 +258,8 @@ let PieceContainer = React.createClass({
|
|||||||
const { furtherDetailsType: FurtherDetailsType } = this.props;
|
const { furtherDetailsType: FurtherDetailsType } = this.props;
|
||||||
const { currentUser, piece } = this.state;
|
const { currentUser, piece } = this.state;
|
||||||
|
|
||||||
if (piece && piece.id) {
|
if (piece.id) {
|
||||||
setDocumentTitle([piece.artist_name, piece.title].join(', '));
|
setDocumentTitle(`${piece.artist_name}, ${piece.title}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Piece
|
<Piece
|
||||||
@ -298,7 +302,7 @@ let PieceContainer = React.createClass({
|
|||||||
editable={true}
|
editable={true}
|
||||||
successMessage={getLangText('Private note saved')}
|
successMessage={getLangText('Private note saved')}
|
||||||
url={ApiUrls.note_private_piece}
|
url={ApiUrls.note_private_piece}
|
||||||
currentUser={currentUser}/>
|
currentUser={currentUser} />
|
||||||
<Note
|
<Note
|
||||||
id={this.getId}
|
id={this.getId}
|
||||||
label={getLangText('Personal note (public)')}
|
label={getLangText('Personal note (public)')}
|
||||||
@ -308,7 +312,7 @@ let PieceContainer = React.createClass({
|
|||||||
show={!!(piece.public_note || piece.acl.acl_edit)}
|
show={!!(piece.public_note || piece.acl.acl_edit)}
|
||||||
successMessage={getLangText('Public note saved')}
|
successMessage={getLangText('Public note saved')}
|
||||||
url={ApiUrls.note_public_piece}
|
url={ApiUrls.note_public_piece}
|
||||||
currentUser={currentUser}/>
|
currentUser={currentUser} />
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('Further Details')}
|
title={getLangText('Further Details')}
|
||||||
|
@ -13,43 +13,46 @@ import InputTextAreaToggable from './input_textarea_toggable';
|
|||||||
|
|
||||||
let PieceExtraDataForm = React.createClass({
|
let PieceExtraDataForm = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
pieceId: React.PropTypes.number,
|
name: React.PropTypes.string.isRequired,
|
||||||
|
pieceId: React.PropTypes.number.isRequired,
|
||||||
|
|
||||||
|
editable: React.PropTypes.bool,
|
||||||
extraData: React.PropTypes.object,
|
extraData: React.PropTypes.object,
|
||||||
handleSuccess: React.PropTypes.func,
|
handleSuccess: React.PropTypes.func,
|
||||||
name: React.PropTypes.string,
|
title: React.PropTypes.string
|
||||||
title: React.PropTypes.string,
|
|
||||||
editable: React.PropTypes.bool
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData() {
|
||||||
let extradata = {};
|
|
||||||
extradata[this.props.name] = this.refs.form.refs[this.props.name].state.value;
|
|
||||||
return {
|
return {
|
||||||
extradata: extradata,
|
extradata: {
|
||||||
|
[this.props.name]: this.refs.form.refs[this.props.name].state.value
|
||||||
|
},
|
||||||
piece_id: this.props.pieceId
|
piece_id: this.props.pieceId
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let defaultValue = this.props.extraData[this.props.name] || '';
|
const { editable, extraData, handleSuccess, name, pieceId, title } = this.props;
|
||||||
if (defaultValue.length === 0 && !this.props.editable){
|
const defaultValue = (extraData && extraData[name]) || null;
|
||||||
|
|
||||||
|
if (!defaultValue && !editable) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let url = requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: this.props.pieceId});
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
ref='form'
|
ref='form'
|
||||||
url={url}
|
url={requests.prepareUrl(ApiUrls.piece_extradata, { piece_id: pieceId })}
|
||||||
handleSuccess={this.props.handleSuccess}
|
handleSuccess={handleSuccess}
|
||||||
getFormData={this.getFormData}
|
getFormData={this.getFormData}
|
||||||
disabled={!this.props.editable}>
|
disabled={!editable}>
|
||||||
<Property
|
<Property
|
||||||
name={this.props.name}
|
name={name}
|
||||||
label={this.props.title}>
|
label={title}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={defaultValue}
|
defaultValue={defaultValue}
|
||||||
placeholder={getLangText('Fill in%s', ' ') + this.props.title}
|
placeholder={getLangText('Fill in%s', ' ') + title}
|
||||||
required />
|
required />
|
||||||
</Property>
|
</Property>
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactAddons from 'react/addons';
|
|
||||||
|
|
||||||
import Modal from 'react-bootstrap/lib/Modal';
|
import Modal from 'react-bootstrap/lib/Modal';
|
||||||
|
|
||||||
let ModalWrapper = React.createClass({
|
let ModalWrapper = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
trigger: React.PropTypes.element,
|
|
||||||
title: React.PropTypes.oneOfType([
|
title: React.PropTypes.oneOfType([
|
||||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
React.PropTypes.element,
|
React.PropTypes.element,
|
||||||
React.PropTypes.string
|
React.PropTypes.string
|
||||||
]).isRequired,
|
]).isRequired,
|
||||||
handleSuccess: React.PropTypes.func.isRequired,
|
|
||||||
|
handleCancel: React.PropTypes.func,
|
||||||
|
handleSuccess: React.PropTypes.func,
|
||||||
|
trigger: React.PropTypes.element,
|
||||||
children: React.PropTypes.oneOfType([
|
children: React.PropTypes.oneOfType([
|
||||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
React.PropTypes.element
|
React.PropTypes.element
|
||||||
@ -38,14 +39,25 @@ let ModalWrapper = React.createClass({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleCancel() {
|
||||||
|
if (typeof this.props.handleCancel === 'function') {
|
||||||
|
this.props.handleCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hide();
|
||||||
|
},
|
||||||
|
|
||||||
handleSuccess(response) {
|
handleSuccess(response) {
|
||||||
this.props.handleSuccess(response);
|
if (typeof this.props.handleSuccess === 'function') {
|
||||||
|
this.props.handleSuccess(response);
|
||||||
|
}
|
||||||
|
|
||||||
this.hide();
|
this.hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
renderChildren() {
|
renderChildren() {
|
||||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
return React.Children.map(this.props.children, (child) => {
|
||||||
return ReactAddons.addons.cloneWithProps(child, {
|
return React.cloneElement(child, {
|
||||||
handleSuccess: (response) => {
|
handleSuccess: (response) => {
|
||||||
if (typeof child.props.handleSuccess === 'function') {
|
if (typeof child.props.handleSuccess === 'function') {
|
||||||
child.props.handleSuccess(response);
|
child.props.handleSuccess(response);
|
||||||
@ -60,14 +72,23 @@ let ModalWrapper = React.createClass({
|
|||||||
render() {
|
render() {
|
||||||
const { trigger, title } = this.props;
|
const { trigger, title } = this.props;
|
||||||
|
|
||||||
// If the trigger component exists, we add the ModalWrapper's show() as its onClick method.
|
// If the trigger component exists, we add the ModalWrapper's show() to its onClick method.
|
||||||
// The trigger component should, in most cases, be a button.
|
// The trigger component should, in most cases, be a button.
|
||||||
const clonedTrigger = React.isValidElement(trigger) ? React.cloneElement(trigger, {onClick: this.show})
|
const clonedTrigger = React.isValidElement(trigger) ?
|
||||||
: null;
|
React.cloneElement(trigger, {
|
||||||
|
onClick: (...params) => {
|
||||||
|
if (typeof trigger.props.onClick === 'function') {
|
||||||
|
trigger.props.onClick(...params);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.show();
|
||||||
|
}
|
||||||
|
}) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{clonedTrigger}
|
{clonedTrigger}
|
||||||
<Modal show={this.state.showModal} onHide={this.hide}>
|
<Modal show={this.state.showModal} onHide={this.handleCancel}>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
<Modal.Title>
|
<Modal.Title>
|
||||||
{title}
|
{title}
|
||||||
|
@ -36,17 +36,11 @@ const ReactS3FineUploader = React.createClass({
|
|||||||
keyRoutine: shape({
|
keyRoutine: shape({
|
||||||
url: string,
|
url: string,
|
||||||
fileClass: string,
|
fileClass: string,
|
||||||
pieceId: oneOfType([
|
pieceId: number
|
||||||
string,
|
|
||||||
number
|
|
||||||
])
|
|
||||||
}),
|
}),
|
||||||
createBlobRoutine: shape({
|
createBlobRoutine: shape({
|
||||||
url: string,
|
url: string,
|
||||||
pieceId: oneOfType([
|
pieceId: number
|
||||||
string,
|
|
||||||
number
|
|
||||||
])
|
|
||||||
}),
|
}),
|
||||||
handleChangedFile: func, // is for when a file is dropped or selected
|
handleChangedFile: func, // is for when a file is dropped or selected
|
||||||
submitFile: func, // is for when a file has been successfully uploaded, TODO: rename to handleSubmitFile
|
submitFile: func, // is for when a file has been successfully uploaded, TODO: rename to handleSubmitFile
|
||||||
|
@ -60,16 +60,10 @@ let PrizePieceContainer = React.createClass({
|
|||||||
mixins: [ReactError],
|
mixins: [ReactError],
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
//FIXME: this component uses the PieceStore, but we avoid using the getState() here since it may contain stale data
|
return mergeOptions(
|
||||||
// It should instead use something like getInitialState() where that call also resets the state.
|
PieceStore.getInitialState(),
|
||||||
return UserStore.getState();
|
UserStore.getState()
|
||||||
},
|
);
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
// Every time we enter the piece detail page, just reset the piece
|
|
||||||
// store as it will otherwise display wrong/old data once the user loads
|
|
||||||
// the piece detail a second time
|
|
||||||
PieceActions.updatePiece({});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -81,18 +75,19 @@ let PrizePieceContainer = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// This is done to update the container when the user clicks on the prev or next
|
// 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)
|
// 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) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (this.props.params.pieceId !== nextProps.params.pieceId) {
|
if (this.props.params.pieceId !== nextProps.params.pieceId) {
|
||||||
PieceActions.updatePiece({});
|
PieceActions.flushPiece();
|
||||||
this.loadPiece(nextProps.params.pieceId);
|
this.loadPiece(nextProps.params.pieceId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const { pieceError } = this.state;
|
const { pieceMeta: { err: pieceErr } } = this.state;
|
||||||
|
|
||||||
if (pieceError && pieceError.status === 404) {
|
if (pieceErr && pieceErr.status === 404) {
|
||||||
this.throws(new ResourceNotFoundError(getLangText("Oops, the piece you're looking for doesn't exist.")));
|
this.throws(new ResourceNotFoundError(getLangText("Oops, the piece you're looking for doesn't exist.")));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -109,25 +104,25 @@ let PrizePieceContainer = React.createClass({
|
|||||||
getActions() {
|
getActions() {
|
||||||
const { currentUser, piece } = this.state;
|
const { currentUser, piece } = this.state;
|
||||||
|
|
||||||
if (piece && piece.notifications && piece.notifications.length > 0) {
|
if (piece.notifications && piece.notifications.length > 0) {
|
||||||
return (
|
return (
|
||||||
<ListRequestActions
|
<ListRequestActions
|
||||||
pieceOrEditions={piece}
|
pieceOrEditions={piece}
|
||||||
currentUser={currentUser}
|
currentUser={currentUser}
|
||||||
handleSuccess={this.loadPiece}
|
handleSuccess={this.loadPiece}
|
||||||
notifications={piece.notifications}/>);
|
notifications={piece.notifications} />);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
loadPiece(pieceId = this.props.params.pieceId) {
|
loadPiece(pieceId = this.props.params.pieceId) {
|
||||||
PieceActions.fetchOne(pieceId);
|
PieceActions.fetchPiece(pieceId);
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { selectedPrizeActionButton } = this.props;
|
const { selectedPrizeActionButton } = this.props;
|
||||||
const { currentUser, piece } = this.state;
|
const { currentUser, piece } = this.state;
|
||||||
|
|
||||||
if (piece && piece.id) {
|
if (piece.id) {
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This really needs a refactor!
|
This really needs a refactor!
|
||||||
@ -138,16 +133,19 @@ let PrizePieceContainer = React.createClass({
|
|||||||
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
|
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
|
||||||
let artistName;
|
let artistName;
|
||||||
if ((currentUser.is_jury && !currentUser.is_judge) || (currentUser.is_judge && !piece.selected )) {
|
if ((currentUser.is_jury && !currentUser.is_judge) || (currentUser.is_judge && !piece.selected )) {
|
||||||
artistName = <span className="glyphicon glyphicon-eye-close" aria-hidden="true"/>;
|
artistName = <span className="glyphicon glyphicon-eye-close" aria-hidden="true" />;
|
||||||
setDocumentTitle(piece.title);
|
setDocumentTitle(piece.title);
|
||||||
} else {
|
} else {
|
||||||
artistName = piece.artist_name;
|
artistName = piece.artist_name;
|
||||||
setDocumentTitle([artistName, piece.title].join(', '));
|
setDocumentTitle(`${artistName}, ${piece.title}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only show the artist email if you are a judge and the piece is shortlisted
|
// Only show the artist email if you are a judge and the piece is shortlisted
|
||||||
const artistEmail = (currentUser.is_judge && piece.selected ) ?
|
const artistEmail = currentUser.is_judge && piece.selected ? (
|
||||||
<DetailProperty label={getLangText('REGISTREE')} value={ piece.user_registered } /> : null;
|
<DetailProperty
|
||||||
|
label={getLangText('REGISTREE')}
|
||||||
|
value={piece.user_registered} />
|
||||||
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Piece
|
<Piece
|
||||||
@ -157,16 +155,16 @@ let PrizePieceContainer = React.createClass({
|
|||||||
<div className="ascribe-detail-header">
|
<div className="ascribe-detail-header">
|
||||||
<NavigationHeader
|
<NavigationHeader
|
||||||
piece={piece}
|
piece={piece}
|
||||||
currentUser={currentUser}/>
|
currentUser={currentUser} />
|
||||||
|
|
||||||
<h1 className="ascribe-detail-title">{piece.title}</h1>
|
<h1 className="ascribe-detail-title">{piece.title}</h1>
|
||||||
<DetailProperty label={getLangText('BY')} value={artistName} />
|
<DetailProperty label={getLangText('BY')} value={artistName} />
|
||||||
<DetailProperty label={getLangText('DATE')} value={Moment(piece.date_created, 'YYYY-MM-DD').year()} />
|
<DetailProperty label={getLangText('DATE')} value={Moment(piece.date_created, 'YYYY-MM-DD').year()} />
|
||||||
{artistEmail}
|
{artistEmail}
|
||||||
{this.getActions()}
|
{this.getActions()}
|
||||||
<hr/>
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
subheader={
|
subheader={
|
||||||
<PrizePieceRatings
|
<PrizePieceRatings
|
||||||
loadPiece={this.loadPiece}
|
loadPiece={this.loadPiece}
|
||||||
@ -196,9 +194,8 @@ let NavigationHeader = React.createClass({
|
|||||||
render() {
|
render() {
|
||||||
const { currentUser, piece } = this.props;
|
const { currentUser, piece } = this.props;
|
||||||
|
|
||||||
if (currentUser && currentUser.email && currentUser.is_judge && currentUser.is_jury &&
|
if (currentUser.email && currentUser.is_judge && currentUser.is_jury && !currentUser.is_admin && piece.navigation) {
|
||||||
!currentUser.is_admin && piece && piece.navigation) {
|
const nav = piece.navigation;
|
||||||
let nav = piece.navigation;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{marginBottom: '1em'}}>
|
<div style={{marginBottom: '1em'}}>
|
||||||
@ -218,8 +215,9 @@ let NavigationHeader = React.createClass({
|
|||||||
<hr/>
|
<hr/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -323,7 +321,7 @@ let PrizePieceRatings = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.props.piece && this.props.currentUser && this.props.currentUser.is_judge && this.state.average) {
|
if (this.props.piece.id && this.props.currentUser.is_judge && this.state.average) {
|
||||||
// Judge sees shortlisting, average and per-jury notes
|
// Judge sees shortlisting, average and per-jury notes
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -355,7 +353,7 @@ let PrizePieceRatings = React.createClass({
|
|||||||
size='md'
|
size='md'
|
||||||
step={0.5}
|
step={0.5}
|
||||||
rating={this.state.average}
|
rating={this.state.average}
|
||||||
ratingAmount={5}/>
|
ratingAmount={5} />
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
{this.state.ratings.map((item, i) => {
|
{this.state.ratings.map((item, i) => {
|
||||||
@ -380,7 +378,7 @@ let PrizePieceRatings = React.createClass({
|
|||||||
size='sm'
|
size='sm'
|
||||||
step={0.5}
|
step={0.5}
|
||||||
rating={item.rating}
|
rating={item.rating}
|
||||||
ratingAmount={5}/>
|
ratingAmount={5} />
|
||||||
</span>
|
</span>
|
||||||
<span> {item.user}</span>
|
<span> {item.user}</span>
|
||||||
{note}
|
{note}
|
||||||
@ -391,7 +389,7 @@ let PrizePieceRatings = React.createClass({
|
|||||||
<hr />
|
<hr />
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
</div>);
|
</div>);
|
||||||
} else if (this.props.currentUser && this.props.currentUser.is_jury) {
|
} else if (this.props.currentUser.is_jury) {
|
||||||
// Jury can set rating and note
|
// Jury can set rating and note
|
||||||
return (
|
return (
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
@ -409,14 +407,14 @@ let PrizePieceRatings = React.createClass({
|
|||||||
ratingAmount={5} />
|
ratingAmount={5} />
|
||||||
</div>
|
</div>
|
||||||
<Note
|
<Note
|
||||||
id={() => {return {'piece_id': this.props.piece.id}; }}
|
id={() => ({ 'piece_id': this.props.piece.id })}
|
||||||
label={getLangText('Jury note')}
|
label={getLangText('Jury note')}
|
||||||
defaultValue={this.props.piece && this.props.piece.note_from_user ? this.props.piece.note_from_user.note : null}
|
defaultValue={this.props.piece.note_from_user || null}
|
||||||
placeholder={getLangText('Enter your comments ...')}
|
placeholder={getLangText('Enter your comments ...')}
|
||||||
editable={true}
|
editable={true}
|
||||||
successMessage={getLangText('Jury note saved')}
|
successMessage={getLangText('Jury note saved')}
|
||||||
url={ApiUrls.notes}
|
url={ApiUrls.notes}
|
||||||
currentUser={this.props.currentUser}/>
|
currentUser={this.props.currentUser} />
|
||||||
</CollapsibleParagraph>);
|
</CollapsibleParagraph>);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -433,33 +431,34 @@ let PrizePieceDetails = React.createClass({
|
|||||||
render() {
|
render() {
|
||||||
const { piece } = this.props;
|
const { piece } = this.props;
|
||||||
|
|
||||||
if (piece &&
|
if (piece.prize && piece.prize.name && Object.keys(piece.extra_data).length) {
|
||||||
piece.prize &&
|
|
||||||
piece.prize.name &&
|
|
||||||
Object.keys(piece.extra_data).length !== 0) {
|
|
||||||
return (
|
return (
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('Prize Details')}
|
title={getLangText('Prize Details')}
|
||||||
defaultExpanded={true}>
|
defaultExpanded={true}>
|
||||||
<Form ref='form'>
|
<Form>
|
||||||
{Object.keys(piece.extra_data).sort().map((data) => {
|
{Object
|
||||||
// Remove leading number (for sorting), if any, and underscores with spaces
|
.keys(piece.extra_data)
|
||||||
let label = data.replace(/^\d-/, '').replace(/_/g, ' ');
|
.sort()
|
||||||
const value = piece.extra_data[data] || 'N/A';
|
.map((data) => {
|
||||||
|
// Remove leading number (for sorting), if any, and underscores with spaces
|
||||||
|
const label = data.replace(/^\d-/, '').replace(/_/g, ' ');
|
||||||
|
const value = piece.extra_data[data] || 'N/A';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Property
|
<Property
|
||||||
key={label}
|
key={label}
|
||||||
name={data}
|
name={data}
|
||||||
label={label}
|
label={label}
|
||||||
editable={false}
|
editable={false}
|
||||||
overrideForm={true}>
|
overrideForm={true}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={value}/>
|
defaultValue={value} />
|
||||||
</Property>
|
</Property>
|
||||||
);
|
);
|
||||||
})}
|
})
|
||||||
|
}
|
||||||
<FurtherDetailsFileuploader
|
<FurtherDetailsFileuploader
|
||||||
submitFile={() => {}}
|
submitFile={() => {}}
|
||||||
setIsUploadReady={() => {}}
|
setIsUploadReady={() => {}}
|
||||||
@ -472,8 +471,9 @@ let PrizePieceDetails = React.createClass({
|
|||||||
</Form>
|
</Form>
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,6 +14,18 @@ class PrizeRatingStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
this.ratings = [];
|
||||||
|
this.currentRating = null;
|
||||||
|
this.average = null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
ratings: this.ratings,
|
||||||
|
currentRating: this.currentRating,
|
||||||
|
average: this.average
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
onUpdatePrizeRatings(ratings) {
|
onUpdatePrizeRatings(ratings) {
|
||||||
this.ratings = ratings;
|
this.ratings = ratings;
|
||||||
}
|
}
|
||||||
@ -30,18 +42,6 @@ class PrizeRatingStore {
|
|||||||
onResetPrizeRatings() {
|
onResetPrizeRatings() {
|
||||||
this.getInitialState();
|
this.getInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
getInitialState() {
|
|
||||||
this.ratings = [];
|
|
||||||
this.currentRating = null;
|
|
||||||
this.average = null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
ratings: this.ratings,
|
|
||||||
currentRating: this.currentRating,
|
|
||||||
average: this.average
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore');
|
export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore');
|
@ -40,7 +40,7 @@ let CylandPieceContainer = React.createClass({
|
|||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
PieceStore.getState(),
|
PieceStore.getInitialState(),
|
||||||
UserStore.getState(),
|
UserStore.getState(),
|
||||||
PieceListStore.getState()
|
PieceListStore.getState()
|
||||||
);
|
);
|
||||||
@ -51,14 +51,17 @@ let CylandPieceContainer = React.createClass({
|
|||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
PieceListStore.listen(this.onChange);
|
PieceListStore.listen(this.onChange);
|
||||||
|
|
||||||
// Every time we enter the piece detail page, just reset the piece
|
|
||||||
// store as it will otherwise display wrong/old data once the user loads
|
|
||||||
// the piece detail a second time
|
|
||||||
PieceActions.updatePiece({});
|
|
||||||
|
|
||||||
this.loadPiece();
|
this.loadPiece();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// We need this for 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();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
PieceStore.unlisten(this.onChange);
|
PieceStore.unlisten(this.onChange);
|
||||||
UserStore.unlisten(this.onChange);
|
UserStore.unlisten(this.onChange);
|
||||||
@ -70,7 +73,7 @@ let CylandPieceContainer = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
loadPiece() {
|
loadPiece() {
|
||||||
PieceActions.fetchOne(this.props.params.pieceId);
|
PieceActions.fetchPiece(this.props.params.pieceId);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDeleteSuccess(response) {
|
handleDeleteSuccess(response) {
|
||||||
@ -83,19 +86,21 @@ let CylandPieceContainer = React.createClass({
|
|||||||
EditionListActions.closeAllEditionLists();
|
EditionListActions.closeAllEditionLists();
|
||||||
EditionListActions.clearAllEditionSelections();
|
EditionListActions.clearAllEditionSelections();
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
const notification = new GlobalNotificationModel(response.notification, 'success');
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
this.history.push('/collection');
|
this.history.push('/collection');
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if(this.state.piece && this.state.piece.id) {
|
const { piece } = this.state;
|
||||||
setDocumentTitle([this.state.piece.artist_name, this.state.piece.title].join(', '));
|
|
||||||
|
if (piece.id) {
|
||||||
|
setDocumentTitle(`${piece.artist_name}, ${piece.title}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WalletPieceContainer
|
<WalletPieceContainer
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
currentUser={this.state.currentUser}
|
currentUser={this.state.currentUser}
|
||||||
loadPiece={this.loadPiece}
|
loadPiece={this.loadPiece}
|
||||||
handleDeleteSuccess={this.handleDeleteSuccess}
|
handleDeleteSuccess={this.handleDeleteSuccess}
|
||||||
@ -104,14 +109,13 @@ let CylandPieceContainer = React.createClass({
|
|||||||
title={getLangText('Further Details')}
|
title={getLangText('Further Details')}
|
||||||
defaultExpanded={true}>
|
defaultExpanded={true}>
|
||||||
<CylandAdditionalDataForm
|
<CylandAdditionalDataForm
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
disabled={!this.state.piece.acl.acl_edit}
|
disabled={!piece.acl.acl_edit}
|
||||||
isInline={true} />
|
isInline={true} />
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
</WalletPieceContainer>
|
</WalletPieceContainer>
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return (
|
return (
|
||||||
<div className="fullpage-spinner">
|
<div className="fullpage-spinner">
|
||||||
<AscribeSpinner color='dark-blue' size='lg' />
|
<AscribeSpinner color='dark-blue' size='lg' />
|
||||||
|
@ -23,9 +23,10 @@ import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_
|
|||||||
|
|
||||||
let CylandAdditionalDataForm = React.createClass({
|
let CylandAdditionalDataForm = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
handleSuccess: React.PropTypes.func,
|
|
||||||
piece: React.PropTypes.object.isRequired,
|
piece: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
|
handleSuccess: React.PropTypes.func,
|
||||||
isInline: React.PropTypes.bool
|
isInline: React.PropTypes.bool
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -42,13 +43,13 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleSuccess() {
|
handleSuccess() {
|
||||||
let notification = new GlobalNotificationModel(getLangText('Further details successfully updated'), 'success', 10000);
|
const notification = new GlobalNotificationModel(getLangText('Further details successfully updated'), 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData() {
|
||||||
let extradata = {};
|
const extradata = {};
|
||||||
let formRefs = this.refs.form.refs;
|
const formRefs = this.refs.form.refs;
|
||||||
|
|
||||||
// Put additional fields in extra data object
|
// Put additional fields in extra data object
|
||||||
Object
|
Object
|
||||||
@ -71,10 +72,13 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { piece, isInline, disabled, handleSuccess, location } = this.props;
|
const { disabled, handleSuccess, isInline, piece } = this.props;
|
||||||
let buttons, spinner, heading;
|
|
||||||
|
|
||||||
if(!isInline) {
|
let buttons;
|
||||||
|
let spinner;
|
||||||
|
let heading;
|
||||||
|
|
||||||
|
if (!isInline) {
|
||||||
buttons = (
|
buttons = (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
@ -87,7 +91,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
spinner = (
|
spinner = (
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
<p className="pull-right">
|
<p className="pull-right">
|
||||||
<AscribeSpinner color='dark-blue' size='md'/>
|
<AscribeSpinner color='dark-blue' size='md' />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -101,13 +105,15 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(piece && piece.id) {
|
if (piece.id) {
|
||||||
|
const { extra_data: extraData = {} } = piece;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className="ascribe-form-bordered"
|
className="ascribe-form-bordered"
|
||||||
ref='form'
|
ref='form'
|
||||||
url={requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: piece.id})}
|
url={requests.prepareUrl(ApiUrls.piece_extradata, { piece_id: piece.id })}
|
||||||
handleSuccess={handleSuccess || this.handleSuccess}
|
handleSuccess={handleSuccess || this.handleSuccess}
|
||||||
getFormData={this.getFormData}
|
getFormData={this.getFormData}
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
@ -116,65 +122,65 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='artist_bio'
|
name='artist_bio'
|
||||||
label={getLangText('Artist Biography')}
|
label={getLangText('Artist Biography')}
|
||||||
expanded={!disabled || !!piece.extra_data.artist_bio}>
|
expanded={!disabled || !!extraData.artist_bio}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.artist_bio}
|
defaultValue={extraData.artist_bio}
|
||||||
placeholder={getLangText('Enter the artist\'s biography...')}/>
|
placeholder={getLangText('Enter the artist\'s biography...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='artist_contact_information'
|
name='artist_contact_information'
|
||||||
label={getLangText('Artist Contact Information')}
|
label={getLangText('Artist Contact Information')}
|
||||||
expanded={!disabled || !!piece.extra_data.artist_contact_information}>
|
expanded={!disabled || !!extraData.artist_contact_information}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.artist_contact_information}
|
defaultValue={extraData.artist_contact_information}
|
||||||
placeholder={getLangText('Enter the artist\'s contact information...')}/>
|
placeholder={getLangText('Enter the artist\'s contact information...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='conceptual_overview'
|
name='conceptual_overview'
|
||||||
label={getLangText('Conceptual Overview')}
|
label={getLangText('Conceptual Overview')}
|
||||||
expanded={!disabled || !!piece.extra_data.conceptual_overview}>
|
expanded={!disabled || !!extraData.conceptual_overview}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.conceptual_overview}
|
defaultValue={extraData.conceptual_overview}
|
||||||
placeholder={getLangText('Enter a conceptual overview...')}/>
|
placeholder={getLangText('Enter a conceptual overview...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='medium'
|
name='medium'
|
||||||
label={getLangText('Medium (technical specifications)')}
|
label={getLangText('Medium (technical specifications)')}
|
||||||
expanded={!disabled || !!piece.extra_data.medium}>
|
expanded={!disabled || !!extraData.medium}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.medium}
|
defaultValue={extraData.medium}
|
||||||
placeholder={getLangText('Enter the medium (and other technical specifications)...')}/>
|
placeholder={getLangText('Enter the medium (and other technical specifications)...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='size_duration'
|
name='size_duration'
|
||||||
label={getLangText('Size / Duration')}
|
label={getLangText('Size / Duration')}
|
||||||
expanded={!disabled || !!piece.extra_data.size_duration}>
|
expanded={!disabled || !!extraData.size_duration}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.size_duration}
|
defaultValue={extraData.size_duration}
|
||||||
placeholder={getLangText('Enter the size / duration...')}/>
|
placeholder={getLangText('Enter the size / duration...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='display_instructions'
|
name='display_instructions'
|
||||||
label={getLangText('Display instructions')}
|
label={getLangText('Display instructions')}
|
||||||
expanded={!disabled || !!piece.extra_data.display_instructions}>
|
expanded={!disabled || !!extraData.display_instructions}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.display_instructions}
|
defaultValue={extraData.display_instructions}
|
||||||
placeholder={getLangText('Enter the display instructions...')}/>
|
placeholder={getLangText('Enter the display instructions...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='additional_details'
|
name='additional_details'
|
||||||
label={getLangText('Additional details')}
|
label={getLangText('Additional details')}
|
||||||
expanded={!disabled || !!piece.extra_data.additional_details}>
|
expanded={!disabled || !!extraData.additional_details}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.additional_details}
|
defaultValue={extraData.additional_details}
|
||||||
placeholder={getLangText('Enter additional details...')}/>
|
placeholder={getLangText('Enter additional details...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<FurtherDetailsFileuploader
|
<FurtherDetailsFileuploader
|
||||||
label={getLangText('Additional files (e.g. still images, pdf)')}
|
label={getLangText('Additional files (e.g. still images, pdf)')}
|
||||||
@ -189,7 +195,7 @@ let CylandAdditionalDataForm = React.createClass({
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className="ascribe-loading-position">
|
<div className="ascribe-loading-position">
|
||||||
<AscribeSpinner color='dark-blue' size='md'/>
|
<AscribeSpinner color='dark-blue' size='md' />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
UserStore.getState(),
|
UserStore.getState(),
|
||||||
PieceListStore.getState(),
|
PieceListStore.getState(),
|
||||||
PieceStore.getState(),
|
PieceStore.getInitialState(),
|
||||||
WhitelabelStore.getState(),
|
WhitelabelStore.getState(),
|
||||||
{
|
{
|
||||||
step: 0
|
step: 0
|
||||||
@ -67,7 +67,7 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
WhitelabelActions.fetchWhitelabel();
|
WhitelabelActions.fetchWhitelabel();
|
||||||
|
|
||||||
let queryParams = this.props.location.query;
|
const queryParams = this.props.location.query;
|
||||||
|
|
||||||
// Since every step of this register process is atomic,
|
// Since every step of this register process is atomic,
|
||||||
// we may need to enter the process at step 1 or 2.
|
// we may need to enter the process at step 1 or 2.
|
||||||
@ -76,8 +76,8 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
//
|
//
|
||||||
// We're using 'in' here as we want to know if 'piece_id' is present in the url,
|
// We're using 'in' here as we want to know if 'piece_id' is present in the url,
|
||||||
// we don't care about the value.
|
// we don't care about the value.
|
||||||
if(queryParams && 'piece_id' in queryParams) {
|
if ('piece_id' in queryParams) {
|
||||||
PieceActions.fetchOne(queryParams.piece_id);
|
PieceActions.fetchPiece(queryParams.piece_id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -92,53 +92,44 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
this.setState(state);
|
this.setState(state);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleRegisterSuccess(response){
|
handleRegisterSuccess(response) {
|
||||||
|
|
||||||
this.refreshPieceList();
|
this.refreshPieceList();
|
||||||
|
|
||||||
// also start loading the piece for the next step
|
// Also load the newly registered piece for the next step
|
||||||
if(response && response.piece) {
|
if (response && response.piece) {
|
||||||
PieceActions.updatePiece({});
|
|
||||||
PieceActions.updatePiece(response.piece);
|
PieceActions.updatePiece(response.piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.incrementStep();
|
this.nextSlide({ piece_id: response.piece.id });
|
||||||
|
|
||||||
this.refs.slidesContainer.nextSlide({ piece_id: response.piece.id });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleAdditionalDataSuccess() {
|
handleAdditionalDataSuccess() {
|
||||||
|
|
||||||
// We need to refetch the piece again after submitting the additional data
|
// We need to refetch the piece again after submitting the additional data
|
||||||
// since we want it's otherData to be displayed when the user choses to click
|
// since we want its otherData to be displayed when the user choses to click
|
||||||
// on the browsers back button.
|
// on the browsers back button.
|
||||||
PieceActions.fetchOne(this.state.piece.id);
|
PieceActions.fetchPiece(this.state.piece.id);
|
||||||
|
|
||||||
this.refreshPieceList();
|
this.refreshPieceList();
|
||||||
|
|
||||||
this.incrementStep();
|
this.nextSlide();
|
||||||
|
|
||||||
this.refs.slidesContainer.nextSlide();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleLoanSuccess(response) {
|
handleLoanSuccess(response) {
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
const notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
this.refreshPieceList();
|
this.refreshPieceList();
|
||||||
|
|
||||||
PieceActions.fetchOne(this.state.piece.id);
|
|
||||||
|
|
||||||
this.history.push(`/pieces/${this.state.piece.id}`);
|
this.history.push(`/pieces/${this.state.piece.id}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// We need to increase the step to lock the forms that are already filled out
|
nextSlide(queryParams) {
|
||||||
incrementStep() {
|
// We need to increase the step to lock the forms that are already filled out
|
||||||
// also increase step
|
|
||||||
let newStep = this.state.step + 1;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
step: newStep
|
step: this.state.step + 1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.refs.slidesContainer.nextSlide(queryParams);
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshPieceList() {
|
refreshPieceList() {
|
||||||
@ -152,8 +143,7 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
const { currentUser, piece, step, whitelabel } = this.state;
|
const { currentUser, piece, step, whitelabel } = this.state;
|
||||||
|
|
||||||
const today = new Moment();
|
const today = new Moment();
|
||||||
const datetimeWhenWeAllWillBeFlyingCoolHoverboardsAndDinosaursWillLiveAgain = new Moment();
|
const datetimeWhenWeAllWillBeFlyingCoolHoverboardsAndDinosaursWillLiveAgain = new Moment().add(1000, 'years');
|
||||||
datetimeWhenWeAllWillBeFlyingCoolHoverboardsAndDinosaursWillLiveAgain.add(1000, 'years');
|
|
||||||
|
|
||||||
const loanHeading = getLangText('Loan to Cyland archive');
|
const loanHeading = getLangText('Loan to Cyland archive');
|
||||||
const loanButtons = (
|
const loanButtons = (
|
||||||
@ -196,7 +186,7 @@ let CylandRegisterPiece = React.createClass({
|
|||||||
submitMessage={getLangText('Submit')}
|
submitMessage={getLangText('Submit')}
|
||||||
isFineUploaderActive={true}
|
isFineUploaderActive={true}
|
||||||
handleSuccess={this.handleRegisterSuccess}
|
handleSuccess={this.handleRegisterSuccess}
|
||||||
location={location}/>
|
location={location} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,7 +41,7 @@ let IkonotvPieceContainer = React.createClass({
|
|||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
PieceStore.getState(),
|
PieceStore.getInitialState(),
|
||||||
UserStore.getState(),
|
UserStore.getState(),
|
||||||
PieceListStore.getState()
|
PieceListStore.getState()
|
||||||
);
|
);
|
||||||
@ -52,19 +52,14 @@ let IkonotvPieceContainer = React.createClass({
|
|||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
PieceListStore.listen(this.onChange);
|
PieceListStore.listen(this.onChange);
|
||||||
|
|
||||||
// Every time we enter the piece detail page, just reset the piece
|
|
||||||
// store as it will otherwise display wrong/old data once the user loads
|
|
||||||
// the piece detail a second time
|
|
||||||
PieceActions.updatePiece({});
|
|
||||||
|
|
||||||
this.loadPiece();
|
this.loadPiece();
|
||||||
},
|
},
|
||||||
|
|
||||||
// We need this for when the user clicks on a notification while being in another piece view
|
// We need this for when the user clicks on a notification while being in another piece view
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if(this.props.params.pieceId !== nextProps.params.pieceId) {
|
if (this.props.params.pieceId !== nextProps.params.pieceId) {
|
||||||
PieceActions.updatePiece({});
|
PieceActions.flushPiece();
|
||||||
PieceActions.fetchOne(nextProps.params.pieceId);
|
this.loadPiece();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -79,7 +74,7 @@ let IkonotvPieceContainer = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
loadPiece() {
|
loadPiece() {
|
||||||
PieceActions.fetchOne(this.props.params.pieceId);
|
PieceActions.fetchPiece(this.props.params.pieceId);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDeleteSuccess(response) {
|
handleDeleteSuccess(response) {
|
||||||
@ -92,13 +87,15 @@ let IkonotvPieceContainer = React.createClass({
|
|||||||
EditionListActions.closeAllEditionLists();
|
EditionListActions.closeAllEditionLists();
|
||||||
EditionListActions.clearAllEditionSelections();
|
EditionListActions.clearAllEditionSelections();
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
const notification = new GlobalNotificationModel(response.notification, 'success');
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
this.history.push('/collection');
|
this.history.push('/collection');
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { piece } = this.state;
|
||||||
|
|
||||||
let furtherDetails = (
|
let furtherDetails = (
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('Further Details')}
|
title={getLangText('Further Details')}
|
||||||
@ -107,28 +104,29 @@ let IkonotvPieceContainer = React.createClass({
|
|||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
);
|
);
|
||||||
|
|
||||||
if(this.state.piece.extra_data && Object.keys(this.state.piece.extra_data).length > 0 && this.state.piece.acl) {
|
if (piece.extra_data && Object.keys(piece.extra_data).length && piece.acl) {
|
||||||
furtherDetails = (
|
furtherDetails = (
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('Further Details')}
|
title={getLangText('Further Details')}
|
||||||
defaultExpanded={true}>
|
defaultExpanded={true}>
|
||||||
<IkonotvArtistDetailsForm
|
<IkonotvArtistDetailsForm
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
isInline={true}
|
isInline={true}
|
||||||
disabled={!this.state.piece.acl.acl_edit} />
|
disabled={!piece.acl.acl_edit} />
|
||||||
<IkonotvArtworkDetailsForm
|
<IkonotvArtworkDetailsForm
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
isInline={true}
|
isInline={true}
|
||||||
disabled={!this.state.piece.acl.acl_edit} />
|
disabled={!piece.acl.acl_edit} />
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.state.piece && this.state.piece.id) {
|
if (piece.id) {
|
||||||
setDocumentTitle([this.state.piece.artist_name, this.state.piece.title].join(', '));
|
setDocumentTitle(`${piece.artist_name}, ${piece.title}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WalletPieceContainer
|
<WalletPieceContainer
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
currentUser={this.state.currentUser}
|
currentUser={this.state.currentUser}
|
||||||
loadPiece={this.loadPiece}
|
loadPiece={this.loadPiece}
|
||||||
handleDeleteSuccess={this.handleDeleteSuccess}
|
handleDeleteSuccess={this.handleDeleteSuccess}
|
||||||
@ -136,8 +134,7 @@ let IkonotvPieceContainer = React.createClass({
|
|||||||
{furtherDetails}
|
{furtherDetails}
|
||||||
</WalletPieceContainer>
|
</WalletPieceContainer>
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return (
|
return (
|
||||||
<div className="fullpage-spinner">
|
<div className="fullpage-spinner">
|
||||||
<AscribeSpinner color='dark-blue' size='lg' />
|
<AscribeSpinner color='dark-blue' size='lg' />
|
||||||
|
@ -20,11 +20,10 @@ import { getLangText } from '../../../../../../utils/lang_utils';
|
|||||||
|
|
||||||
let IkonotvArtistDetailsForm = React.createClass({
|
let IkonotvArtistDetailsForm = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
handleSuccess: React.PropTypes.func,
|
|
||||||
piece: React.PropTypes.object.isRequired,
|
piece: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
|
handleSuccess: React.PropTypes.func,
|
||||||
isInline: React.PropTypes.bool
|
isInline: React.PropTypes.bool
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -35,8 +34,8 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData() {
|
||||||
let extradata = {};
|
const extradata = {};
|
||||||
let formRefs = this.refs.form.refs;
|
const formRefs = this.refs.form.refs;
|
||||||
|
|
||||||
// Put additional fields in extra data object
|
// Put additional fields in extra data object
|
||||||
Object
|
Object
|
||||||
@ -53,20 +52,23 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleSuccess() {
|
handleSuccess() {
|
||||||
let notification = new GlobalNotificationModel('Artist details successfully updated', 'success', 10000);
|
const notification = new GlobalNotificationModel(getLangText('Artist details successfully updated'), 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let buttons, spinner, heading;
|
const { disabled, isInline, handleSuccess, piece } = this.props;
|
||||||
let { isInline, handleSuccess } = this.props;
|
|
||||||
|
let buttons;
|
||||||
|
let spinner;
|
||||||
|
let heading;
|
||||||
|
|
||||||
if (!isInline) {
|
if (!isInline) {
|
||||||
buttons = (
|
buttons = (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-default btn-wide"
|
className="btn btn-default btn-wide"
|
||||||
disabled={this.props.disabled}>
|
disabled={disabled}>
|
||||||
{getLangText('Proceed to loan')}
|
{getLangText('Proceed to loan')}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
@ -74,7 +76,7 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
spinner = (
|
spinner = (
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
<p className="pull-right">
|
<p className="pull-right">
|
||||||
<AscribeSpinner color='dark-blue' size='md'/>
|
<AscribeSpinner color='dark-blue' size='md' />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -88,13 +90,15 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.piece && this.props.piece.id && this.props.piece.extra_data) {
|
if (piece.id) {
|
||||||
|
const { extra_data: extraData = {} } = piece;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
disabled={this.props.disabled}
|
disabled={disabled}
|
||||||
className="ascribe-form-bordered"
|
className="ascribe-form-bordered"
|
||||||
ref='form'
|
ref='form'
|
||||||
url={requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: this.props.piece.id})}
|
url={requests.prepareUrl(ApiUrls.piece_extradata, { piece_id: piece.id })}
|
||||||
handleSuccess={handleSuccess || this.handleSuccess}
|
handleSuccess={handleSuccess || this.handleSuccess}
|
||||||
getFormData={this.getFormData}
|
getFormData={this.getFormData}
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
@ -103,39 +107,38 @@ let IkonotvArtistDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='artist_website'
|
name='artist_website'
|
||||||
label={getLangText('Artist Website')}
|
label={getLangText('Artist Website')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.artist_website}>
|
expanded={!disabled || !!extraData.artist_website}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.artist_website}
|
defaultValue={extraData.artist_website}
|
||||||
placeholder={getLangText('The artist\'s website if present...')}/>
|
placeholder={getLangText('The artist\'s website if present...')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='gallery_website'
|
name='gallery_website'
|
||||||
label={getLangText('Website of related Gallery, Museum, etc.')}
|
label={getLangText('Website of related Gallery, Museum, etc.')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.gallery_website}>
|
expanded={!disabled || !!extraData.gallery_website}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.gallery_website}
|
defaultValue={extraData.gallery_website}
|
||||||
placeholder={getLangText('The website of any related Gallery or Museum')}/>
|
placeholder={getLangText('The website of any related Gallery or Museum')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='additional_websites'
|
name='additional_websites'
|
||||||
label={getLangText('Additional Websites/Publications/Museums/Galleries')}
|
label={getLangText('Additional Websites/Publications/Museums/Galleries')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.additional_websites}>
|
expanded={!disabled || !!extraData.additional_websites}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.additional_websites}
|
defaultValue={extraData.additional_websites}
|
||||||
placeholder={getLangText('Enter additional Websites/Publications if any')}/>
|
placeholder={getLangText('Enter additional Websites/Publications if any')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='conceptual_overview'
|
name='conceptual_overview'
|
||||||
label={getLangText('Short text about the Artist')}
|
label={getLangText('Short text about the Artist')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.conceptual_overview}>
|
expanded={!disabled || !!extraData.conceptual_overview}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.conceptual_overview}
|
defaultValue={extraData.conceptual_overview}
|
||||||
placeholder={getLangText('Enter a short bio about the Artist')}
|
placeholder={getLangText('Enter a short bio about the Artist')} />
|
||||||
/>
|
|
||||||
</Property>
|
</Property>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
@ -20,11 +20,10 @@ import { getLangText } from '../../../../../../utils/lang_utils';
|
|||||||
|
|
||||||
let IkonotvArtworkDetailsForm = React.createClass({
|
let IkonotvArtworkDetailsForm = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
handleSuccess: React.PropTypes.func,
|
|
||||||
piece: React.PropTypes.object.isRequired,
|
piece: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
|
handleSuccess: React.PropTypes.func,
|
||||||
isInline: React.PropTypes.bool
|
isInline: React.PropTypes.bool
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -35,8 +34,8 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData() {
|
||||||
let extradata = {};
|
const extradata = {};
|
||||||
let formRefs = this.refs.form.refs;
|
const formRefs = this.refs.form.refs;
|
||||||
|
|
||||||
// Put additional fields in extra data object
|
// Put additional fields in extra data object
|
||||||
Object
|
Object
|
||||||
@ -53,20 +52,23 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleSuccess() {
|
handleSuccess() {
|
||||||
let notification = new GlobalNotificationModel('Artwork details successfully updated', 'success', 10000);
|
const notification = new GlobalNotificationModel(getLangText('Artwork details successfully updated'), 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let buttons, spinner, heading;
|
const { disabled, isInline, handleSuccess, piece } = this.props;
|
||||||
let { isInline, handleSuccess } = this.props;
|
|
||||||
|
let buttons;
|
||||||
|
let spinner;
|
||||||
|
let heading;
|
||||||
|
|
||||||
if (!isInline) {
|
if (!isInline) {
|
||||||
buttons = (
|
buttons = (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-default btn-wide"
|
className="btn btn-default btn-wide"
|
||||||
disabled={this.props.disabled}>
|
disabled={disabled}>
|
||||||
{getLangText('Proceed to artist details')}
|
{getLangText('Proceed to artist details')}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
@ -74,7 +76,7 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
spinner = (
|
spinner = (
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
<p className="pull-right">
|
<p className="pull-right">
|
||||||
<AscribeSpinner color='dark-blue' size='md'/>
|
<AscribeSpinner color='dark-blue' size='md' />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -88,13 +90,15 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.piece && this.props.piece.id && this.props.piece.extra_data) {
|
if (piece.id && piece.extra_data) {
|
||||||
|
const { extra_data: extraData = {} } = piece;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
disabled={this.props.disabled}
|
disabled={disabled}
|
||||||
className="ascribe-form-bordered"
|
className="ascribe-form-bordered"
|
||||||
ref='form'
|
ref='form'
|
||||||
url={requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: this.props.piece.id})}
|
url={requests.prepareUrl(ApiUrls.piece_extradata, { piece_id: piece.id })}
|
||||||
handleSuccess={handleSuccess || this.handleSuccess}
|
handleSuccess={handleSuccess || this.handleSuccess}
|
||||||
getFormData={this.getFormData}
|
getFormData={this.getFormData}
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
@ -103,56 +107,56 @@ let IkonotvArtworkDetailsForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name='medium'
|
name='medium'
|
||||||
label={getLangText('Medium')}
|
label={getLangText('Medium')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.medium}>
|
expanded={!disabled || !!extraData.medium}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.medium}
|
defaultValue={extraData.medium}
|
||||||
placeholder={getLangText('The medium of the file (i.e. photo, video, other, ...)')}/>
|
placeholder={getLangText('The medium of the file (i.e. photo, video, other, ...)')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='size_duration'
|
name='size_duration'
|
||||||
label={getLangText('Size/Duration')}
|
label={getLangText('Size/Duration')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.size_duration}>
|
expanded={!disabled || !!extraData.size_duration}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.size_duration}
|
defaultValue={extraData.size_duration}
|
||||||
placeholder={getLangText('Size in centimeters. Duration in minutes.')}/>
|
placeholder={getLangText('Size in centimeters. Duration in minutes.')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='copyright'
|
name='copyright'
|
||||||
label={getLangText('Copyright')}
|
label={getLangText('Copyright')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.copyright}>
|
expanded={!disabled || !!extraData.copyright}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.copyright}
|
defaultValue={extraData.copyright}
|
||||||
placeholder={getLangText('Which copyright is attached to this work?')}/>
|
placeholder={getLangText('Which copyright is attached to this work?')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='courtesy_of'
|
name='courtesy_of'
|
||||||
label={getLangText('Courtesy of')}
|
label={getLangText('Courtesy of')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.courtesy_of}>
|
expanded={!disabled || !!extraData.courtesy_of}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.courtesy_of}
|
defaultValue={extraData.courtesy_of}
|
||||||
placeholder={getLangText('The current owner of the artwork')}/>
|
placeholder={getLangText('The current owner of the artwork')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='copyright_of_photography'
|
name='copyright_of_photography'
|
||||||
label={getLangText('Copyright of Photography')}
|
label={getLangText('Copyright of Photography')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.copyright_of_photography}>
|
expanded={!disabled || !!extraData.copyright_of_photography}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.copyright_of_photography}
|
defaultValue={extraData.copyright_of_photography}
|
||||||
placeholder={getLangText('Who should be attributed for the photography?')}/>
|
placeholder={getLangText('Who should be attributed for the photography?')} />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='additional_details'
|
name='additional_details'
|
||||||
label={getLangText('Additional Details about the artwork')}
|
label={getLangText('Additional Details about the artwork')}
|
||||||
expanded={!this.props.disabled || !!this.props.piece.extra_data.additional_details}>
|
expanded={!disabled || !!extraData.additional_details}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={this.props.piece.extra_data.additional_details}
|
defaultValue={extraData.additional_details}
|
||||||
placeholder={getLangText('Insert artwork overview')}/>
|
placeholder={getLangText('Insert artwork overview')} />
|
||||||
</Property>
|
</Property>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
@ -49,7 +49,7 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
UserStore.getState(),
|
UserStore.getState(),
|
||||||
PieceListStore.getState(),
|
PieceListStore.getState(),
|
||||||
PieceStore.getState(),
|
PieceStore.getInitialState(),
|
||||||
WhitelabelStore.getState(),
|
WhitelabelStore.getState(),
|
||||||
{
|
{
|
||||||
step: 0,
|
step: 0,
|
||||||
@ -65,11 +65,7 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
WhitelabelActions.fetchWhitelabel();
|
WhitelabelActions.fetchWhitelabel();
|
||||||
|
|
||||||
// Before we load the new piece, we reset the piece store to delete old data that we do
|
const queryParams = this.props.location.query;
|
||||||
// not want to display to the user.
|
|
||||||
PieceActions.updatePiece({});
|
|
||||||
|
|
||||||
let queryParams = this.props.location.query;
|
|
||||||
|
|
||||||
// Since every step of this register process is atomic,
|
// Since every step of this register process is atomic,
|
||||||
// we may need to enter the process at step 1 or 2.
|
// we may need to enter the process at step 1 or 2.
|
||||||
@ -78,8 +74,8 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
//
|
//
|
||||||
// We're using 'in' here as we want to know if 'piece_id' is present in the url,
|
// We're using 'in' here as we want to know if 'piece_id' is present in the url,
|
||||||
// we don't care about the value.
|
// we don't care about the value.
|
||||||
if (queryParams && 'piece_id' in queryParams) {
|
if ('piece_id' in queryParams) {
|
||||||
PieceActions.fetchOne(queryParams.piece_id);
|
PieceActions.fetchPiece(queryParams.piece_id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -95,55 +91,50 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
handleRegisterSuccess(response){
|
handleRegisterSuccess(response) {
|
||||||
this.refreshPieceList();
|
this.refreshPieceList();
|
||||||
|
|
||||||
// also start loading the piece for the next step
|
// Also load the newly registered piece for the next step
|
||||||
if(response && response.piece) {
|
if (response && response.piece) {
|
||||||
PieceActions.updatePiece(response.piece);
|
PieceActions.updatePiece(response.piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.canSubmit()) {
|
if (!this.canSubmit()) {
|
||||||
this.history.push('/collection');
|
this.history.push('/collection');
|
||||||
}
|
} else {
|
||||||
else {
|
this.nextSlide({ piece_id: response.piece.id });
|
||||||
this.incrementStep();
|
|
||||||
this.refs.slidesContainer.nextSlide();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleAdditionalDataSuccess() {
|
handleAdditionalDataSuccess() {
|
||||||
|
|
||||||
// We need to refetch the piece again after submitting the additional data
|
// We need to refetch the piece again after submitting the additional data
|
||||||
// since we want it's otherData to be displayed when the user choses to click
|
// since we want it's otherData to be displayed when the user choses to click
|
||||||
// on the browsers back button.
|
// on the browsers back button.
|
||||||
PieceActions.fetchOne(this.state.piece.id);
|
PieceActions.fetchPiece(this.state.piece.id);
|
||||||
|
|
||||||
this.refreshPieceList();
|
this.refreshPieceList();
|
||||||
|
|
||||||
this.incrementStep();
|
this.nextSlide();
|
||||||
|
|
||||||
this.refs.slidesContainer.nextSlide();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleLoanSuccess(response) {
|
handleLoanSuccess(response) {
|
||||||
this.setState({ pageExitWarning: null });
|
this.setState({ pageExitWarning: null });
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
const notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
this.refreshPieceList();
|
this.refreshPieceList();
|
||||||
|
|
||||||
PieceActions.fetchOne(this.state.piece.id);
|
|
||||||
this.history.push(`/pieces/${this.state.piece.id}`);
|
this.history.push(`/pieces/${this.state.piece.id}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// We need to increase the step to lock the forms that are already filled out
|
nextSlide(queryParams) {
|
||||||
incrementStep() {
|
// We need to increase the step to lock the forms that are already filled out
|
||||||
// also increase step
|
|
||||||
let newStep = this.state.step + 1;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
step: newStep
|
step: this.state.step + 1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.refs.slidesContainer.nextSlide(queryParams);
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshPieceList() {
|
refreshPieceList() {
|
||||||
@ -155,7 +146,7 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
canSubmit() {
|
canSubmit() {
|
||||||
let currentUser = this.state.currentUser;
|
let currentUser = this.state.currentUser;
|
||||||
let whitelabel = this.state.whitelabel;
|
let whitelabel = this.state.whitelabel;
|
||||||
return currentUser && currentUser.acl && currentUser.acl.acl_wallet_submit && whitelabel && whitelabel.user;
|
return currentUser.acl && currentUser.acl.acl_wallet_submit && whitelabel.user;
|
||||||
},
|
},
|
||||||
|
|
||||||
getSlideArtistDetails() {
|
getSlideArtistDetails() {
|
||||||
@ -166,13 +157,14 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||||
<IkonotvArtistDetailsForm
|
<IkonotvArtistDetailsForm
|
||||||
handleSuccess={this.handleAdditionalDataSuccess}
|
handleSuccess={this.handleAdditionalDataSuccess}
|
||||||
piece={this.state.piece}/>
|
piece={this.state.piece} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getSlideArtworkDetails() {
|
getSlideArtworkDetails() {
|
||||||
@ -183,21 +175,21 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||||
<IkonotvArtworkDetailsForm
|
<IkonotvArtworkDetailsForm
|
||||||
handleSuccess={this.handleAdditionalDataSuccess}
|
handleSuccess={this.handleAdditionalDataSuccess}
|
||||||
piece={this.state.piece}/>
|
piece={this.state.piece} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getSlideLoan() {
|
getSlideLoan() {
|
||||||
if (this.canSubmit()) {
|
if (this.canSubmit()) {
|
||||||
const { piece, whitelabel } = this.state;
|
const { piece, whitelabel } = this.state;
|
||||||
let today = new Moment();
|
const today = new Moment();
|
||||||
let endDate = new Moment();
|
const endDate = new Moment().add(2, 'years');
|
||||||
endDate.add(2, 'years');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-slide-title={getLangText('Loan')}>
|
<div data-slide-title={getLangText('Loan')}>
|
||||||
@ -220,8 +212,9 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -247,7 +240,7 @@ let IkonotvRegisterPiece = React.createClass({
|
|||||||
submitMessage={getLangText('Register')}
|
submitMessage={getLangText('Register')}
|
||||||
isFineUploaderActive={true}
|
isFineUploaderActive={true}
|
||||||
handleSuccess={this.handleRegisterSuccess}
|
handleSuccess={this.handleRegisterSuccess}
|
||||||
location={this.props.location}/>
|
location={this.props.location} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,7 @@ let MarketAclButtonList = React.createClass({
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser.defer();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import EditionActions from '../../../../../../actions/edition_actions';
|
||||||
|
|
||||||
|
import WhitelabelActions from '../../../../../../actions/whitelabel_actions';
|
||||||
|
import WhitelabelStore from '../../../../../../stores/whitelabel_store';
|
||||||
|
|
||||||
import MarketAdditionalDataForm from '../market_forms/market_additional_data_form';
|
import MarketAdditionalDataForm from '../market_forms/market_additional_data_form';
|
||||||
|
|
||||||
import AclFormFactory from '../../../../../ascribe_forms/acl_form_factory';
|
import AclFormFactory from '../../../../../ascribe_forms/acl_form_factory';
|
||||||
@ -11,10 +16,7 @@ import ConsignForm from '../../../../../ascribe_forms/form_consign';
|
|||||||
import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
|
import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
|
||||||
|
|
||||||
import AclProxy from '../../../../../acl_proxy';
|
import AclProxy from '../../../../../acl_proxy';
|
||||||
|
import AscribeSpinner from '../../../../../ascribe_spinner';
|
||||||
import PieceActions from '../../../../../../actions/piece_actions';
|
|
||||||
import WhitelabelActions from '../../../../../../actions/whitelabel_actions';
|
|
||||||
import WhitelabelStore from '../../../../../../stores/whitelabel_store';
|
|
||||||
|
|
||||||
import ApiUrls from '../../../../../../constants/api_urls';
|
import ApiUrls from '../../../../../../constants/api_urls';
|
||||||
|
|
||||||
@ -26,8 +28,9 @@ let MarketSubmitButton = React.createClass({
|
|||||||
availableAcls: React.PropTypes.object.isRequired,
|
availableAcls: React.PropTypes.object.isRequired,
|
||||||
currentUser: React.PropTypes.object,
|
currentUser: React.PropTypes.object,
|
||||||
editions: React.PropTypes.array.isRequired,
|
editions: React.PropTypes.array.isRequired,
|
||||||
handleSuccess: React.PropTypes.func.isRequired,
|
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
@ -50,22 +53,21 @@ let MarketSubmitButton = React.createClass({
|
|||||||
|
|
||||||
canEditionBeSubmitted(edition) {
|
canEditionBeSubmitted(edition) {
|
||||||
if (edition && edition.extra_data && edition.other_data) {
|
if (edition && edition.extra_data && edition.other_data) {
|
||||||
const { extra_data, other_data } = edition;
|
const {
|
||||||
|
extra_data: {
|
||||||
|
artist_bio: artistBio,
|
||||||
|
display_instructions: displayInstructions,
|
||||||
|
technology_details: technologyDetails,
|
||||||
|
work_description: workDescription
|
||||||
|
},
|
||||||
|
other_data: otherData } = edition;
|
||||||
|
|
||||||
if (extra_data.artist_bio && extra_data.work_description &&
|
return artistBio && displayInstructions && technologyDetails && workDescription && otherData.length;
|
||||||
extra_data.technology_details && extra_data.display_instructions &&
|
|
||||||
other_data.length > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormDataId() {
|
|
||||||
return getAclFormDataId(false, this.props.editions);
|
|
||||||
},
|
|
||||||
|
|
||||||
getAggregateEditionDetails() {
|
getAggregateEditionDetails() {
|
||||||
const { editions } = this.props;
|
const { editions } = this.props;
|
||||||
|
|
||||||
@ -82,13 +84,20 @@ let MarketSubmitButton = React.createClass({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleAdditionalDataSuccess(pieceId) {
|
getFormDataId() {
|
||||||
// Fetch newly updated piece to update the views
|
return getAclFormDataId(false, this.props.editions);
|
||||||
PieceActions.fetchOne(pieceId);
|
},
|
||||||
|
|
||||||
|
handleAdditionalDataSuccess() {
|
||||||
this.refs.consignModal.show();
|
this.refs.consignModal.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
refreshEdition() {
|
||||||
|
if (this.props.editions.length === 1) {
|
||||||
|
EditionActions.fetchEdition(this.props.editions[0].bitcoin_id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { availableAcls, currentUser, className, editions, handleSuccess } = this.props;
|
const { availableAcls, currentUser, className, editions, handleSuccess } = this.props;
|
||||||
const { whitelabel: { name: whitelabelName = 'Market', user: whitelabelAdminEmail } } = this.state;
|
const { whitelabel: { name: whitelabelName = 'Market', user: whitelabelAdminEmail } } = this.state;
|
||||||
@ -101,6 +110,10 @@ let MarketSubmitButton = React.createClass({
|
|||||||
senderName: currentUser.username
|
senderName: currentUser.username
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If only a single piece is selected, all the edition's extra_data and other_data will
|
||||||
|
// be the same, so we just take the first edition's
|
||||||
|
const { extra_data: extraData, other_data: otherData } = solePieceId ? editions[0] : {};
|
||||||
|
|
||||||
const triggerButton = (
|
const triggerButton = (
|
||||||
<button className={classNames('btn', 'btn-default', 'btn-sm', className)}>
|
<button className={classNames('btn', 'btn-default', 'btn-sm', className)}>
|
||||||
{getLangText('CONSIGN TO %s', whitelabelName.toUpperCase())}
|
{getLangText('CONSIGN TO %s', whitelabelName.toUpperCase())}
|
||||||
@ -126,16 +139,25 @@ let MarketSubmitButton = React.createClass({
|
|||||||
aclName='acl_consign'>
|
aclName='acl_consign'>
|
||||||
<ModalWrapper
|
<ModalWrapper
|
||||||
trigger={triggerButton}
|
trigger={triggerButton}
|
||||||
handleSuccess={this.handleAdditionalDataSuccess.bind(this, solePieceId)}
|
handleSuccess={this.handleAdditionalDataSuccess}
|
||||||
title={getLangText('Add additional information')}>
|
title={getLangText('Add additional information')}>
|
||||||
<MarketAdditionalDataForm
|
<MarketAdditionalDataForm
|
||||||
|
extraData={extraData}
|
||||||
|
otherData={otherData}
|
||||||
pieceId={solePieceId}
|
pieceId={solePieceId}
|
||||||
submitLabel={getLangText('Continue to consignment')} />
|
submitLabel={getLangText('Continue to consignment')} />
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
|
|
||||||
<ModalWrapper
|
<ModalWrapper
|
||||||
ref="consignModal"
|
ref="consignModal"
|
||||||
handleSuccess={handleSuccess}
|
handleCancel={this.refreshEdition}
|
||||||
|
handleSuccess={(...params) => {
|
||||||
|
if (typeof handleSuccess === 'function') {
|
||||||
|
handleSuccess(...params);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshEdition();
|
||||||
|
}}
|
||||||
title={getLangText('Consign artwork')}>
|
title={getLangText('Consign artwork')}>
|
||||||
{consignForm}
|
{consignForm}
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
|
@ -6,8 +6,12 @@ import MarketAdditionalDataForm from '../market_forms/market_additional_data_for
|
|||||||
|
|
||||||
let MarketFurtherDetails = React.createClass({
|
let MarketFurtherDetails = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
pieceId: React.PropTypes.number,
|
pieceId: React.PropTypes.number.isRequired,
|
||||||
|
|
||||||
|
editable: React.PropTypes.bool,
|
||||||
|
extraData: React.PropTypes.object,
|
||||||
handleSuccess: React.PropTypes.func,
|
handleSuccess: React.PropTypes.func,
|
||||||
|
otherData: React.PropTypes.arrayOf(React.PropTypes.object)
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -2,21 +2,18 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Form from '../../../../../ascribe_forms/form';
|
|
||||||
import Property from '../../../../../ascribe_forms/property';
|
|
||||||
|
|
||||||
import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable';
|
|
||||||
|
|
||||||
import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader';
|
|
||||||
import AscribeSpinner from '../../../../../ascribe_spinner';
|
|
||||||
|
|
||||||
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';
|
||||||
|
|
||||||
|
import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader';
|
||||||
|
|
||||||
|
import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable';
|
||||||
|
import Form from '../../../../../ascribe_forms/form';
|
||||||
|
import Property from '../../../../../ascribe_forms/property';
|
||||||
|
|
||||||
import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils';
|
import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||||
|
|
||||||
import PieceActions from '../../../../../../actions/piece_actions';
|
import AscribeSpinner from '../../../../../ascribe_spinner';
|
||||||
import PieceStore from '../../../../../../stores/piece_store';
|
|
||||||
|
|
||||||
import ApiUrls from '../../../../../../constants/api_urls';
|
import ApiUrls from '../../../../../../constants/api_urls';
|
||||||
import AppConstants from '../../../../../../constants/application_constants';
|
import AppConstants from '../../../../../../constants/application_constants';
|
||||||
@ -28,16 +25,16 @@ import { getLangText } from '../../../../../../utils/lang_utils';
|
|||||||
|
|
||||||
let MarketAdditionalDataForm = React.createClass({
|
let MarketAdditionalDataForm = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
pieceId: React.PropTypes.oneOfType([
|
pieceId: React.PropTypes.number.isRequired,
|
||||||
React.PropTypes.number,
|
|
||||||
React.PropTypes.string
|
|
||||||
]),
|
|
||||||
editable: React.PropTypes.bool,
|
editable: React.PropTypes.bool,
|
||||||
|
extraData: React.PropTypes.object,
|
||||||
|
handleSuccess: React.PropTypes.func,
|
||||||
isInline: React.PropTypes.bool,
|
isInline: React.PropTypes.bool,
|
||||||
|
otherData: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||||
showHeading: React.PropTypes.bool,
|
showHeading: React.PropTypes.bool,
|
||||||
showNotification: React.PropTypes.bool,
|
showNotification: React.PropTypes.bool,
|
||||||
submitLabel: React.PropTypes.string,
|
submitLabel: React.PropTypes.string
|
||||||
handleSuccess: React.PropTypes.func
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -48,50 +45,34 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
const pieceStore = PieceStore.getState();
|
return {
|
||||||
|
// Allow the form to be submitted if there's already an additional image uploaded
|
||||||
return mergeOptions(
|
isUploadReady: this.isUploadReadyOnChange(),
|
||||||
pieceStore,
|
forceUpdateKey: 0
|
||||||
{
|
|
||||||
// Allow the form to be submitted if there's already an additional image uploaded
|
|
||||||
isUploadReady: this.isUploadReadyOnChange(pieceStore.piece),
|
|
||||||
forceUpdateKey: 0
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
PieceStore.listen(this.onChange);
|
|
||||||
|
|
||||||
if (this.props.pieceId) {
|
|
||||||
PieceActions.fetchOne(this.props.pieceId);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillReceiveProps(nextProps) {
|
||||||
PieceStore.unlisten(this.onChange);
|
if (this.props.extraData !== nextProps.extraData || this.props.otherData !== nextProps.otherData) {
|
||||||
},
|
this.setState({
|
||||||
|
// Allow the form to be submitted if the updated piece has an additional image uploaded
|
||||||
|
isUploadReady: this.isUploadReadyOnChange(),
|
||||||
|
|
||||||
onChange(state) {
|
/**
|
||||||
Object.assign({}, state, {
|
* Increment the forceUpdateKey to force the form to rerender on each change
|
||||||
// Allow the form to be submitted if the updated piece already has an additional image uploaded
|
*
|
||||||
isUploadReady: this.isUploadReadyOnChange(state.piece),
|
* THIS IS A HACK TO MAKE SURE THE FORM ALWAYS DISPLAYS THE MOST RECENT STATE
|
||||||
|
* BECAUSE SOME OF OUR FORM ELEMENTS DON'T UPDATE FROM PROP CHANGES (ie.
|
||||||
/**
|
* InputTextAreaToggable).
|
||||||
* Increment the forceUpdateKey to force the form to rerender on each change
|
*/
|
||||||
*
|
forceUpdateKey: this.state.forceUpdateKey + 1
|
||||||
* THIS IS A HACK TO MAKE SURE THE FORM ALWAYS DISPLAYS THE MOST RECENT STATE
|
});
|
||||||
* BECAUSE SOME OF OUR FORM ELEMENTS DON'T UPDATE FROM PROP CHANGES (ie.
|
}
|
||||||
* InputTextAreaToggable).
|
|
||||||
*/
|
|
||||||
forceUpdateKey: this.state.forceUpdateKey + 1
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState(state);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData() {
|
||||||
let extradata = {};
|
const extradata = {};
|
||||||
let formRefs = this.refs.form.refs;
|
const formRefs = this.refs.form.refs;
|
||||||
|
|
||||||
// Put additional fields in extra data object
|
// Put additional fields in extra data object
|
||||||
Object
|
Object
|
||||||
@ -102,12 +83,12 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
extradata: extradata,
|
extradata: extradata,
|
||||||
piece_id: this.state.piece.id
|
piece_id: this.props.pieceId
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
isUploadReadyOnChange(piece) {
|
isUploadReadyOnChange() {
|
||||||
return piece && piece.other_data && piece.other_data.length > 0;
|
return this.props.otherData && this.props.otherData.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSuccessWithNotification() {
|
handleSuccessWithNotification() {
|
||||||
@ -115,7 +96,7 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
this.props.handleSuccess();
|
this.props.handleSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel(getLangText('Further details successfully updated'), 'success', 10000);
|
const notification = new GlobalNotificationModel(getLangText('Further details successfully updated'), 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -126,11 +107,20 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { editable, isInline, handleSuccess, showHeading, showNotification, submitLabel } = this.props;
|
const {
|
||||||
const { piece } = this.state;
|
editable,
|
||||||
let buttons, heading;
|
extraData = {},
|
||||||
|
isInline,
|
||||||
|
handleSuccess,
|
||||||
|
otherData,
|
||||||
|
pieceId,
|
||||||
|
showHeading,
|
||||||
|
showNotification,
|
||||||
|
submitLabel } = this.props;
|
||||||
|
|
||||||
let spinner = <AscribeSpinner color='dark-blue' size='lg' />;
|
let buttons;
|
||||||
|
let heading;
|
||||||
|
let spinner;
|
||||||
|
|
||||||
if (!isInline) {
|
if (!isInline) {
|
||||||
buttons = (
|
buttons = (
|
||||||
@ -145,7 +135,7 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
spinner = (
|
spinner = (
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
<p className="pull-right">
|
<p className="pull-right">
|
||||||
{spinner}
|
<AscribeSpinner color='dark-blue' size='md' />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -159,64 +149,64 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
) : null;
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (piece && piece.id) {
|
if (pieceId) {
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
className="ascribe-form-bordered"
|
className="ascribe-form-bordered"
|
||||||
ref='form'
|
ref='form'
|
||||||
key={this.state.forceUpdateKey}
|
key={this.state.forceUpdateKey}
|
||||||
url={requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: piece.id})}
|
url={requests.prepareUrl(ApiUrls.piece_extradata, { piece_id: pieceId })}
|
||||||
handleSuccess={showNotification ? this.handleSuccessWithNotification : handleSuccess}
|
handleSuccess={showNotification ? this.handleSuccessWithNotification : handleSuccess}
|
||||||
getFormData={this.getFormData}
|
getFormData={this.getFormData}
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
spinner={spinner}
|
spinner={spinner}
|
||||||
disabled={!this.props.editable || !piece.acl.acl_edit}>
|
disabled={!this.props.editable}>
|
||||||
{heading}
|
{heading}
|
||||||
<FurtherDetailsFileuploader
|
<FurtherDetailsFileuploader
|
||||||
label={getLangText('Marketplace Thumbnail Image')}
|
label={getLangText('Marketplace Thumbnail Image')}
|
||||||
submitFile={function () {}}
|
submitFile={function () {}}
|
||||||
setIsUploadReady={this.setIsUploadReady}
|
setIsUploadReady={this.setIsUploadReady}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
pieceId={piece.id}
|
pieceId={pieceId}
|
||||||
otherData={piece.other_data}
|
otherData={otherData}
|
||||||
editable={editable} />
|
editable={editable} />
|
||||||
<Property
|
<Property
|
||||||
name='artist_bio'
|
name='artist_bio'
|
||||||
label={getLangText('Artist Bio')}
|
label={getLangText('Artist Bio')}
|
||||||
expanded={editable || !!piece.extra_data.artist_bio}>
|
expanded={editable || !!extraData.artist_bio}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.artist_bio}
|
defaultValue={extraData.artist_bio}
|
||||||
placeholder={getLangText('Enter a biography of the artist...')}
|
placeholder={getLangText('Enter a biography of the artist...')}
|
||||||
required />
|
required />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='work_description'
|
name='work_description'
|
||||||
label={getLangText('Work Description')}
|
label={getLangText('Work Description')}
|
||||||
expanded={editable || !!piece.extra_data.work_description}>
|
expanded={editable || !!extraData.work_description}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.work_description}
|
defaultValue={extraData.work_description}
|
||||||
placeholder={getLangText('Enter a description of the work...')}
|
placeholder={getLangText('Enter a description of the work...')}
|
||||||
required />
|
required />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='technology_details'
|
name='technology_details'
|
||||||
label={getLangText('Technology Details')}
|
label={getLangText('Technology Details')}
|
||||||
expanded={editable || !!piece.extra_data.technology_details}>
|
expanded={editable || !!extraData.technology_details}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.technology_details}
|
defaultValue={extraData.technology_details}
|
||||||
placeholder={getLangText('Enter technological details about the work...')}
|
placeholder={getLangText('Enter technological details about the work...')}
|
||||||
required />
|
required />
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='display_instructions'
|
name='display_instructions'
|
||||||
label={getLangText('Display Instructions')}
|
label={getLangText('Display Instructions')}
|
||||||
expanded={editable || !!piece.extra_data.display_instructions}>
|
expanded={editable || !!extraData.display_instructions}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
defaultValue={piece.extra_data.display_instructions}
|
defaultValue={extraData.display_instructions}
|
||||||
placeholder={getLangText('Enter instructions on how to best display the work...')}
|
placeholder={getLangText('Enter instructions on how to best display the work...')}
|
||||||
required />
|
required />
|
||||||
</Property>
|
</Property>
|
||||||
@ -225,7 +215,7 @@ let MarketAdditionalDataForm = React.createClass({
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className="ascribe-loading-position">
|
<div className="ascribe-loading-position">
|
||||||
{spinner}
|
<AscribeSpinner color='dark-blue' size='lg' />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,23 @@ import { History } from 'react-router';
|
|||||||
import Col from 'react-bootstrap/lib/Col';
|
import Col from 'react-bootstrap/lib/Col';
|
||||||
import Row from 'react-bootstrap/lib/Row';
|
import Row from 'react-bootstrap/lib/Row';
|
||||||
|
|
||||||
|
import PieceStore from '../../../../../stores/piece_store';
|
||||||
|
import PieceActions from '../../../../../actions/piece_actions';
|
||||||
|
|
||||||
|
import PieceListStore from '../../../../../stores/piece_list_store';
|
||||||
|
import PieceListActions from '../../../../../actions/piece_list_actions';
|
||||||
|
|
||||||
|
import UserStore from '../../../../../stores/user_store';
|
||||||
|
import UserActions from '../../../../../actions/user_actions';
|
||||||
|
|
||||||
|
import WhitelabelActions from '../../../../../actions/whitelabel_actions';
|
||||||
|
import WhitelabelStore from '../../../../../stores/whitelabel_store';
|
||||||
|
|
||||||
import MarketAdditionalDataForm from './market_forms/market_additional_data_form';
|
import MarketAdditionalDataForm from './market_forms/market_additional_data_form';
|
||||||
|
|
||||||
import Property from '../../../../ascribe_forms/property';
|
import Property from '../../../../ascribe_forms/property';
|
||||||
import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
|
import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
|
||||||
|
|
||||||
import PieceActions from '../../../../../actions/piece_actions';
|
|
||||||
import PieceListStore from '../../../../../stores/piece_list_store';
|
|
||||||
import PieceListActions from '../../../../../actions/piece_list_actions';
|
|
||||||
import UserStore from '../../../../../stores/user_store';
|
|
||||||
import UserActions from '../../../../../actions/user_actions';
|
|
||||||
import WhitelabelActions from '../../../../../actions/whitelabel_actions';
|
|
||||||
import WhitelabelStore from '../../../../../stores/whitelabel_store';
|
|
||||||
|
|
||||||
import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
|
import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
|
||||||
|
|
||||||
import { getLangText } from '../../../../../utils/lang_utils';
|
import { getLangText } from '../../../../../utils/lang_utils';
|
||||||
@ -35,6 +39,7 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
getInitialState(){
|
getInitialState(){
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
PieceListStore.getState(),
|
PieceListStore.getState(),
|
||||||
|
PieceStore.getInitialState(),
|
||||||
UserStore.getState(),
|
UserStore.getState(),
|
||||||
WhitelabelStore.getState(),
|
WhitelabelStore.getState(),
|
||||||
{
|
{
|
||||||
@ -44,19 +49,27 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
PieceListStore.listen(this.onChange);
|
PieceListStore.listen(this.onChange);
|
||||||
|
PieceStore.listen(this.onChange);
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
WhitelabelStore.listen(this.onChange);
|
WhitelabelStore.listen(this.onChange);
|
||||||
|
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
WhitelabelActions.fetchWhitelabel();
|
WhitelabelActions.fetchWhitelabel();
|
||||||
|
|
||||||
// Reset the piece store to make sure that we don't display old data
|
const queryParams = this.props.location.query;
|
||||||
// if the user repeatedly registers works
|
|
||||||
PieceActions.updatePiece({});
|
// Load the correct piece if the user loads the second step directly
|
||||||
|
// by pressing on the back button or using the url
|
||||||
|
// We're using 'in' here as we want to know if 'piece_id' is present in the url,
|
||||||
|
// we don't care about the value.
|
||||||
|
if ('piece_id' in queryParams) {
|
||||||
|
PieceActions.fetchPiece(queryParams.piece_id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
PieceListStore.unlisten(this.onChange);
|
PieceListStore.unlisten(this.onChange);
|
||||||
|
PieceStore.unlisten(this.onChange);
|
||||||
UserStore.unlisten(this.onChange);
|
UserStore.unlisten(this.onChange);
|
||||||
WhitelabelStore.unlisten(this.onChange);
|
WhitelabelStore.unlisten(this.onChange);
|
||||||
},
|
},
|
||||||
@ -68,15 +81,12 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
handleRegisterSuccess(response) {
|
handleRegisterSuccess(response) {
|
||||||
this.refreshPieceList();
|
this.refreshPieceList();
|
||||||
|
|
||||||
// Use the response's piece for the next step if available
|
// Also load the newly registered piece for the next step
|
||||||
let pieceId = null;
|
|
||||||
if (response && response.piece) {
|
if (response && response.piece) {
|
||||||
pieceId = response.piece.id;
|
|
||||||
PieceActions.updatePiece(response.piece);
|
PieceActions.updatePiece(response.piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.incrementStep();
|
this.nextSlide({ piece_id: response.piece.id });
|
||||||
this.refs.slidesContainer.nextSlide({ piece_id: pieceId });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleAdditionalDataSuccess() {
|
handleAdditionalDataSuccess() {
|
||||||
@ -85,21 +95,13 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
this.history.push('/collection');
|
this.history.push('/collection');
|
||||||
},
|
},
|
||||||
|
|
||||||
// We need to increase the step to lock the forms that are already filled out
|
nextSlide(queryParams) {
|
||||||
incrementStep() {
|
// We need to increase the step to lock the forms that are already filled out
|
||||||
this.setState({
|
this.setState({
|
||||||
step: this.state.step + 1
|
step: this.state.step + 1
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
getPieceFromQueryParam() {
|
this.refs.slidesContainer.nextSlide(queryParams);
|
||||||
const queryParams = this.props.location.query;
|
|
||||||
|
|
||||||
// Since every step of this register process is atomic,
|
|
||||||
// we may need to enter the process at step 1 or 2.
|
|
||||||
// If this is the case, we'll need the piece number to complete submission.
|
|
||||||
// It is encoded in the URL as a queryParam and we're checking for it here.
|
|
||||||
return queryParams && queryParams.piece_id;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshPieceList() {
|
refreshPieceList() {
|
||||||
@ -109,7 +111,9 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { location } = this.props;
|
||||||
const {
|
const {
|
||||||
|
piece,
|
||||||
step,
|
step,
|
||||||
whitelabel: {
|
whitelabel: {
|
||||||
name: whitelabelName = 'Market'
|
name: whitelabelName = 'Market'
|
||||||
@ -125,7 +129,7 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
pending: 'glyphicon glyphicon-chevron-right',
|
pending: 'glyphicon glyphicon-chevron-right',
|
||||||
completed: 'glyphicon glyphicon-lock'
|
completed: 'glyphicon glyphicon-lock'
|
||||||
}}
|
}}
|
||||||
location={this.props.location}>
|
location={location}>
|
||||||
<div data-slide-title={getLangText('Register work')}>
|
<div data-slide-title={getLangText('Register work')}>
|
||||||
<Row className="no-margin">
|
<Row className="no-margin">
|
||||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||||
@ -137,7 +141,7 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
isFineUploaderActive={true}
|
isFineUploaderActive={true}
|
||||||
enableSeparateThumbnail={false}
|
enableSeparateThumbnail={false}
|
||||||
handleSuccess={this.handleRegisterSuccess}
|
handleSuccess={this.handleRegisterSuccess}
|
||||||
location={this.props.location}>
|
location={location}>
|
||||||
<Property
|
<Property
|
||||||
name="num_editions"
|
name="num_editions"
|
||||||
label={getLangText('Specify editions')}>
|
label={getLangText('Specify editions')}>
|
||||||
@ -155,8 +159,10 @@ let MarketRegisterPiece = React.createClass({
|
|||||||
<Row className="no-margin">
|
<Row className="no-margin">
|
||||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||||
<MarketAdditionalDataForm
|
<MarketAdditionalDataForm
|
||||||
|
extraData={piece.extra_data}
|
||||||
handleSuccess={this.handleAdditionalDataSuccess}
|
handleSuccess={this.handleAdditionalDataSuccess}
|
||||||
pieceId={this.getPieceFromQueryParam()}
|
otherData={piece.other_data}
|
||||||
|
pieceId={piece.id}
|
||||||
showHeading />
|
showHeading />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
import requests from '../utils/requests';
|
|
||||||
|
|
||||||
|
|
||||||
let PieceFetcher = {
|
|
||||||
/**
|
|
||||||
* Fetch a piece from the API.
|
|
||||||
*/
|
|
||||||
fetchOne(id) {
|
|
||||||
return requests.get('piece', {'piece_id': id});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PieceFetcher;
|
|
19
js/sources/piece_source.js
Normal file
19
js/sources/piece_source.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import requests from '../utils/requests';
|
||||||
|
|
||||||
|
import PieceActions from '../actions/piece_actions';
|
||||||
|
|
||||||
|
|
||||||
|
const PieceSource = {
|
||||||
|
lookupPiece: {
|
||||||
|
remote(state, pieceId) {
|
||||||
|
return requests.get('piece', { piece_id: pieceId });
|
||||||
|
},
|
||||||
|
|
||||||
|
success: PieceActions.successFetchPiece,
|
||||||
|
error: PieceActions.errorPiece
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PieceSource;
|
@ -120,7 +120,7 @@ class EditionListStore {
|
|||||||
.catch(console.logGlobal);
|
.catch(console.logGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelectEdition({pieceId, editionId, toValue}) {
|
onSelectEdition({ pieceId, editionId, toValue }) {
|
||||||
this.editionList[pieceId].forEach((edition) => {
|
this.editionList[pieceId].forEach((edition) => {
|
||||||
|
|
||||||
// Taken from: http://stackoverflow.com/a/519157/1263876
|
// Taken from: http://stackoverflow.com/a/519157/1263876
|
||||||
|
@ -12,6 +12,16 @@ import { mergeOptions } from '../utils/general_utils';
|
|||||||
|
|
||||||
class EditionStore {
|
class EditionStore {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.getInitialState();
|
||||||
|
|
||||||
|
this.bindActions(EditionActions);
|
||||||
|
this.registerAsync(mergeOptions(EditionSource, CoaSource));
|
||||||
|
this.exportPublicMethods({
|
||||||
|
getInitialState: this.getInitialState.bind(this)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
this.edition = {};
|
this.edition = {};
|
||||||
this.editionMeta = {
|
this.editionMeta = {
|
||||||
err: null
|
err: null
|
||||||
@ -20,8 +30,11 @@ class EditionStore {
|
|||||||
err: null
|
err: null
|
||||||
};
|
};
|
||||||
|
|
||||||
this.bindActions(EditionActions);
|
return {
|
||||||
this.registerAsync(mergeOptions(EditionSource, CoaSource));
|
edition: this.edition,
|
||||||
|
editionMeta: this.editionMeta,
|
||||||
|
coaMeta: this.coaMeta
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onFetchEdition(editionId) {
|
onFetchEdition(editionId) {
|
||||||
@ -61,17 +74,6 @@ class EditionStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onFlushEdition() {
|
|
||||||
this.edition = {};
|
|
||||||
this.editionMeta = {
|
|
||||||
err: null,
|
|
||||||
idToFetch: null
|
|
||||||
};
|
|
||||||
this.coaMeta = {
|
|
||||||
err: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onErrorEdition(err) {
|
onErrorEdition(err) {
|
||||||
console.logGlobal(err);
|
console.logGlobal(err);
|
||||||
this.editionMeta.err = err;
|
this.editionMeta.err = err;
|
||||||
@ -86,6 +88,10 @@ class EditionStore {
|
|||||||
this.coaMeta.err = err;
|
this.coaMeta.err = err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFlushEdition() {
|
||||||
|
this.getInitialState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default alt.createStore(EditionStore, 'EditionStore');
|
export default alt.createStore(EditionStore, 'EditionStore');
|
||||||
|
@ -60,8 +60,8 @@ class PieceListStore {
|
|||||||
* point anyway. Then, this problem is automatically resolved.
|
* point anyway. Then, this problem is automatically resolved.
|
||||||
*/
|
*/
|
||||||
pieceList.forEach((piece, i) => {
|
pieceList.forEach((piece, i) => {
|
||||||
let oldPiece = this.pieceList[i];
|
const oldPiece = this.pieceList[i];
|
||||||
if(oldPiece) {
|
if (oldPiece) {
|
||||||
piece = React.addons.update(piece, {
|
piece = React.addons.update(piece, {
|
||||||
show: { $set: oldPiece.show }
|
show: { $set: oldPiece.show }
|
||||||
});
|
});
|
||||||
@ -76,12 +76,11 @@ class PieceListStore {
|
|||||||
this.requestActions = res.actions;
|
this.requestActions = res.actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdatePropertyForPiece({pieceId, key, value}) {
|
onUpdatePropertyForPiece({ pieceId, key, value }) {
|
||||||
let filteredPieceList = this.pieceList.filter((piece) => piece.id === pieceId);
|
const filteredPieceList = this.pieceList.filter((piece) => piece.id === pieceId);
|
||||||
|
|
||||||
if(filteredPieceList.length === 1) {
|
if (filteredPieceList.length === 1) {
|
||||||
|
const piece = filteredPieceList[0];
|
||||||
let piece = filteredPieceList[0];
|
|
||||||
piece[key] = value;
|
piece[key] = value;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Could not find a matching piece in piece list since its either not there or piecelist contains duplicates.');
|
throw new Error('Could not find a matching piece in piece list since its either not there or piecelist contains duplicates.');
|
||||||
|
@ -1,32 +1,73 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { alt } from '../alt';
|
import { alt } from '../alt';
|
||||||
|
|
||||||
import PieceActions from '../actions/piece_actions';
|
import PieceActions from '../actions/piece_actions';
|
||||||
|
|
||||||
|
import PieceSource from '../sources/piece_source';
|
||||||
|
|
||||||
|
|
||||||
class PieceStore {
|
class PieceStore {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.piece = {};
|
this.getInitialState();
|
||||||
this.pieceError = null;
|
|
||||||
this.bindActions(PieceActions);
|
this.bindActions(PieceActions);
|
||||||
|
this.registerAsync(PieceSource);
|
||||||
|
this.exportPublicMethods({
|
||||||
|
getInitialState: this.getInitialState.bind(this)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
this.piece = {};
|
||||||
|
this.pieceMeta = {
|
||||||
|
err: null
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
piece: this.piece,
|
||||||
|
pieceMeta: this.pieceMeta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onFetchPiece(pieceId) {
|
||||||
|
this.getInstance().lookupPiece(pieceId);
|
||||||
|
|
||||||
|
// Prevent alt from sending an empty change event when a request is sent
|
||||||
|
// off to the source
|
||||||
|
this.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSuccessFetchPiece({ piece }) {
|
||||||
|
if (piece) {
|
||||||
|
this.onUpdatePiece(piece);
|
||||||
|
} else {
|
||||||
|
this.pieceMeta.err = new Error('Problem fetching the piece');
|
||||||
|
console.logGlobal(this.pieceMeta.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onErrorPiece(err) {
|
||||||
|
console.logGlobal(err);
|
||||||
|
this.pieceMeta.err = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFlushPiece() {
|
||||||
|
this.getInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdatePiece(piece) {
|
onUpdatePiece(piece) {
|
||||||
this.piece = piece;
|
this.piece = piece;
|
||||||
this.pieceError = null;
|
this.pieceMeta.err = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdateProperty({key, value}) {
|
onUpdateProperty({ key, value }) {
|
||||||
if(this.piece && key in this.piece) {
|
if (this.piece && key in this.piece) {
|
||||||
this.piece[key] = value;
|
this.piece[key] = value;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('There is no piece defined in PieceStore or the piece object does not have the property you\'re looking for.');
|
throw new Error('There is no piece defined in PieceStore or the piece object does not have the property you\'re looking for.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPieceFailed(err) {
|
|
||||||
this.pieceError = err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default alt.createStore(PieceStore, 'PieceStore');
|
export default alt.createStore(PieceStore, 'PieceStore');
|
||||||
|
@ -238,7 +238,7 @@ $vivi23--highlight-color: #de2600;
|
|||||||
&.active:hover{
|
&.active:hover{
|
||||||
background-color: $vivi23--highlight-color;
|
background-color: $vivi23--highlight-color;
|
||||||
border-color: $vivi23--highlight-color;
|
border-color: $vivi23--highlight-color;
|
||||||
color: $vivi23--highlight-color;
|
color: $vivi23--bg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user