mirror of
https://github.com/ascribe/onion.git
synced 2025-01-03 10:25:08 +01:00
commit
8aae923388
@ -85,6 +85,7 @@ let PieceContainer = React.createClass({
|
|||||||
// store as it will otherwise display wrong/old data once the user loads
|
// store as it will otherwise display wrong/old data once the user loads
|
||||||
// the piece detail a second time
|
// the piece detail a second time
|
||||||
PieceActions.updatePiece({});
|
PieceActions.updatePiece({});
|
||||||
|
|
||||||
this.loadPiece();
|
this.loadPiece();
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
},
|
},
|
||||||
@ -92,7 +93,7 @@ let PieceContainer = React.createClass({
|
|||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const { pieceError } = this.state;
|
const { pieceError } = this.state;
|
||||||
|
|
||||||
if(pieceError && pieceError.status === 404) {
|
if (pieceError && pieceError.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.")));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -182,7 +182,7 @@ let Form = React.createClass({
|
|||||||
delete formData.password;
|
delete formData.password;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.logGlobal(err, false, formData);
|
console.logGlobal(err, formData);
|
||||||
|
|
||||||
if(this.props.isInline) {
|
if(this.props.isInline) {
|
||||||
let notification = new GlobalNotificationModel(getLangText('Something went wrong, please try again later'), 'danger');
|
let notification = new GlobalNotificationModel(getLangText('Something went wrong, please try again later'), 'danger');
|
||||||
|
@ -93,7 +93,6 @@ let LoginForm = React.createClass({
|
|||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder={getLangText('Enter your email')}
|
placeholder={getLangText('Enter your email')}
|
||||||
name="email"
|
|
||||||
defaultValue={email}
|
defaultValue={email}
|
||||||
required/>
|
required/>
|
||||||
</Property>
|
</Property>
|
||||||
@ -103,7 +102,6 @@ let LoginForm = React.createClass({
|
|||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
placeholder={getLangText('Enter your password')}
|
placeholder={getLangText('Enter your password')}
|
||||||
name="password"
|
|
||||||
required/>
|
required/>
|
||||||
</Property>
|
</Property>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -71,17 +71,9 @@ export default function UploadButton({ className = 'btn btn-default btn-sm' } =
|
|||||||
handleOnClick() {
|
handleOnClick() {
|
||||||
if(!this.state.disabled) {
|
if(!this.state.disabled) {
|
||||||
let evt;
|
let evt;
|
||||||
const uploadingFiles = this.getUploadingFiles();
|
|
||||||
const uploadedFile = this.getUploadedFile();
|
|
||||||
|
|
||||||
this.clearSelection();
|
// First, remove any currently uploading or uploaded items
|
||||||
if(uploadingFiles.length) {
|
this.onClickRemove();
|
||||||
this.props.handleCancelFile(uploadingFiles[0].id);
|
|
||||||
} else if(uploadedFile && !uploadedFile.s3UrlSafe) {
|
|
||||||
this.props.handleCancelFile(uploadedFile.id);
|
|
||||||
} else if(uploadedFile && uploadedFile.s3UrlSafe) {
|
|
||||||
this.props.handleDeleteFile(uploadedFile.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
evt = new MouseEvent('click', {
|
evt = new MouseEvent('click', {
|
||||||
@ -99,18 +91,19 @@ export default function UploadButton({ className = 'btn btn-default btn-sm' } =
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onClickCancel() {
|
|
||||||
this.clearSelection();
|
|
||||||
const uploadingFile = this.getUploadingFiles()[0];
|
|
||||||
this.props.handleCancelFile(uploadingFile.id);
|
|
||||||
},
|
|
||||||
|
|
||||||
onClickRemove() {
|
onClickRemove() {
|
||||||
this.clearSelection();
|
const uploadingFiles = this.getUploadingFiles();
|
||||||
const uploadedFile = this.getUploadedFile();
|
const uploadedFile = this.getUploadedFile();
|
||||||
this.props.handleDeleteFile(uploadedFile.id);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
this.clearSelection();
|
||||||
|
if(uploadingFiles.length) {
|
||||||
|
this.props.handleCancelFile(uploadingFiles[0].id);
|
||||||
|
} else if(uploadedFile && !uploadedFile.s3UrlSafe) {
|
||||||
|
this.props.handleCancelFile(uploadedFile.id);
|
||||||
|
} else if(uploadedFile && uploadedFile.s3UrlSafe) {
|
||||||
|
this.props.handleDeleteFile(uploadedFile.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getButtonLabel() {
|
getButtonLabel() {
|
||||||
let { filesToUpload, fileClassToUpload } = this.props;
|
let { filesToUpload, fileClassToUpload } = this.props;
|
||||||
@ -133,7 +126,7 @@ export default function UploadButton({ className = 'btn btn-default btn-sm' } =
|
|||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{' ' + truncateTextAtCharIndex(uploadingFiles[0].name, 40) + ' '}
|
{' ' + truncateTextAtCharIndex(uploadingFiles[0].name, 40) + ' '}
|
||||||
[<a onClick={this.onClickCancel}>{getLangText('cancel upload')}</a>]
|
[<a onClick={this.onClickRemove}>{getLangText('cancel upload')}</a>]
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else if(uploadedFile) {
|
} else if(uploadedFile) {
|
||||||
@ -193,4 +186,4 @@ export default function UploadButton({ className = 'btn btn-default btn-sm' } =
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -344,6 +344,7 @@ const ReactS3FineUploader = React.createClass({
|
|||||||
// still we warn the user of this component
|
// still we warn the user of this component
|
||||||
console.warn('createBlobRoutine was not defined for ReactS3FineUploader. Continuing without creating the blob on the server.');
|
console.warn('createBlobRoutine was not defined for ReactS3FineUploader. Continuing without creating the blob on the server.');
|
||||||
resolve();
|
resolve();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.fetch(createBlobRoutine.url, {
|
window.fetch(createBlobRoutine.url, {
|
||||||
@ -439,7 +440,7 @@ const ReactS3FineUploader = React.createClass({
|
|||||||
onComplete(id, name, res, xhr) {
|
onComplete(id, name, res, xhr) {
|
||||||
// There has been an issue with the server's connection
|
// There has been an issue with the server's connection
|
||||||
if (xhr && xhr.status === 0 && res.success) {
|
if (xhr && xhr.status === 0 && res.success) {
|
||||||
console.logGlobal(new Error('Upload succeeded with a status code 0'), false, {
|
console.logGlobal(new Error('Upload succeeded with a status code 0'), {
|
||||||
files: this.state.filesToUpload,
|
files: this.state.filesToUpload,
|
||||||
chunks: this.state.chunks,
|
chunks: this.state.chunks,
|
||||||
xhr: this.getXhrErrorComment(xhr)
|
xhr: this.getXhrErrorComment(xhr)
|
||||||
@ -497,7 +498,7 @@ const ReactS3FineUploader = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onError(id, name, errorReason, xhr) {
|
onError(id, name, errorReason, xhr) {
|
||||||
console.logGlobal(errorReason, false, {
|
console.logGlobal(errorReason, {
|
||||||
files: this.state.filesToUpload,
|
files: this.state.filesToUpload,
|
||||||
chunks: this.state.chunks,
|
chunks: this.state.chunks,
|
||||||
xhr: this.getXhrErrorComment(xhr)
|
xhr: this.getXhrErrorComment(xhr)
|
||||||
|
@ -16,12 +16,13 @@ import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
|||||||
|
|
||||||
import AclProxy from './acl_proxy';
|
import AclProxy from './acl_proxy';
|
||||||
|
|
||||||
|
import EventActions from '../actions/event_actions';
|
||||||
|
|
||||||
import UserActions from '../actions/user_actions';
|
import UserActions from '../actions/user_actions';
|
||||||
import UserStore from '../stores/user_store';
|
import UserStore from '../stores/user_store';
|
||||||
|
|
||||||
import WhitelabelActions from '../actions/whitelabel_actions';
|
import WhitelabelActions from '../actions/whitelabel_actions';
|
||||||
import WhitelabelStore from '../stores/whitelabel_store';
|
import WhitelabelStore from '../stores/whitelabel_store';
|
||||||
import EventActions from '../actions/event_actions';
|
|
||||||
|
|
||||||
import HeaderNotifications from './header_notification';
|
import HeaderNotifications from './header_notification';
|
||||||
|
|
||||||
@ -58,6 +59,19 @@ let Header = React.createClass({
|
|||||||
// close the mobile expanded navigation after a click by itself.
|
// close the mobile expanded navigation after a click by itself.
|
||||||
// To get rid of this, we set the state of the component ourselves.
|
// To get rid of this, we set the state of the component ourselves.
|
||||||
history.listen(this.onRouteChange);
|
history.listen(this.onRouteChange);
|
||||||
|
|
||||||
|
if (this.state.currentUser && this.state.currentUser.email) {
|
||||||
|
EventActions.profileDidLoad.defer(this.state.currentUser);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillUpdate(nextProps, nextState) {
|
||||||
|
const { currentUser: { email: curEmail } = {} } = this.state;
|
||||||
|
const { currentUser: { email: nextEmail } = {} } = nextState;
|
||||||
|
|
||||||
|
if (nextEmail && curEmail !== nextEmail) {
|
||||||
|
EventActions.profileDidLoad.defer(nextState.currentUser);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@ -105,10 +119,6 @@ let Header = React.createClass({
|
|||||||
|
|
||||||
onChange(state) {
|
onChange(state) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
|
|
||||||
if(this.state.currentUser && this.state.currentUser.email) {
|
|
||||||
EventActions.profileDidLoad.defer(this.state.currentUser);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onMenuItemClick() {
|
onMenuItemClick() {
|
||||||
|
@ -75,7 +75,7 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
const additionalDataFormData = additionalDataForm.getFormData();
|
const additionalDataFormData = additionalDataForm.getFormData();
|
||||||
|
|
||||||
// composing data for piece registration
|
// composing data for piece registration
|
||||||
let registerPieceFormData = registerPieceForm.getFormData();
|
const registerPieceFormData = registerPieceForm.getFormData();
|
||||||
registerPieceFormData.digital_work_key = digitalWorkKey.state.value;
|
registerPieceFormData.digital_work_key = digitalWorkKey.state.value;
|
||||||
registerPieceFormData.thumbnail_file = thumbnailKey.state.value;
|
registerPieceFormData.thumbnail_file = thumbnailKey.state.value;
|
||||||
registerPieceFormData.terms = true;
|
registerPieceFormData.terms = true;
|
||||||
@ -83,33 +83,33 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
// submitting the piece
|
// submitting the piece
|
||||||
requests
|
requests
|
||||||
.post(ApiUrls.pieces_list, { body: registerPieceFormData })
|
.post(ApiUrls.pieces_list, { body: registerPieceFormData })
|
||||||
.then(({ success, piece, notification }) => {
|
.then(({ piece, notification }) => {
|
||||||
if(success) {
|
this.setState({piece}, () => {
|
||||||
this.setState({
|
supportingMaterials.refs.input.createBlobRoutine();
|
||||||
piece
|
proofOfPayment.refs.input.createBlobRoutine();
|
||||||
}, () => {
|
});
|
||||||
supportingMaterials.refs.input.createBlobRoutine();
|
|
||||||
proofOfPayment.refs.input.createBlobRoutine();
|
|
||||||
});
|
|
||||||
|
|
||||||
setCookie(currentUser.email, piece.id);
|
setCookie(currentUser.email, piece.id);
|
||||||
|
|
||||||
return requests.post(ApiUrls.piece_extradata, {
|
return requests
|
||||||
|
.post(ApiUrls.piece_extradata, {
|
||||||
body: {
|
body: {
|
||||||
extradata: additionalDataFormData,
|
extradata: additionalDataFormData,
|
||||||
piece_id: piece.id
|
piece_id: piece.id
|
||||||
},
|
},
|
||||||
piece_id: piece.id
|
piece_id: piece.id
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
const notificationMessage = new GlobalNotificationModel(notification || getLangText('You have successfully submitted "%s" to Portfolio Review 2015', piece.title), 'success', 5000);
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notificationMessage);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
const notificationMessage = new GlobalNotificationModel(notification, 'danger', 5000);
|
|
||||||
GlobalNotificationActions.appendGlobalNotification(notificationMessage);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.then(() => this.history.pushState(null, `/pieces/${this.state.piece.id}`))
|
.then(() => this.history.pushState(null, `/pieces/${this.state.piece.id}`))
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
const notificationMessage = new GlobalNotificationModel(getLangText("Ups! We weren't able to send your submission. Contact: support@ascribe.io"), 'danger', 5000);
|
const notificationMessage = new GlobalNotificationModel(getLangText("Oops! We weren't able to send your submission. Contact: support@ascribe.io"), 'danger', 5000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notificationMessage);
|
GlobalNotificationActions.appendGlobalNotification(notificationMessage);
|
||||||
|
|
||||||
|
console.logGlobal(new Error('Portfolio Review piece registration failed'), err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="button"
|
||||||
className="btn btn-default btn-wide"
|
className="btn btn-default btn-wide"
|
||||||
disabled={!(digitalWorkKeyReady && thumbnailKeyReady && proofOfPaymentReady && supportingMaterialsReady)}
|
disabled={!(digitalWorkKeyReady && thumbnailKeyReady && proofOfPaymentReady && supportingMaterialsReady)}
|
||||||
onClick={this.submit}>
|
onClick={this.submit}>
|
||||||
@ -191,7 +191,7 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
label={getLangText('Full name')}>
|
label={getLangText('Full name')}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="(e.g. Andy Warhol)"
|
placeholder={getLangText('(e.g. Andy Warhol)')}
|
||||||
required/>
|
required/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
@ -199,7 +199,7 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
label={getLangText('Title of the Work')}>
|
label={getLangText('Title of the Work')}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="(e.g. 32 Campbell's Soup Cans)"
|
placeholder={getLangText("(e.g. 32 Campbell's Soup Cans)")}
|
||||||
required/>
|
required/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
@ -207,7 +207,7 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
label={getLangText('Year of creation')}>
|
label={getLangText('Year of creation')}>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="(e.g. 1962)"
|
placeholder={getLangText('(e.g. 1962)')}
|
||||||
min={1}
|
min={1}
|
||||||
required/>
|
required/>
|
||||||
</Property>
|
</Property>
|
||||||
@ -224,25 +224,51 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
className="ascribe-form-bordered"
|
className="ascribe-form-bordered"
|
||||||
ref="additionalDataForm">
|
ref="additionalDataForm">
|
||||||
<Property
|
<Property
|
||||||
name='artist_bio'
|
name='1-date_of_birth'
|
||||||
|
label={getLangText('Date of Birth')}>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
placeholder={getLangText('(e.g. 1962)')}
|
||||||
|
min={1900}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='2-artist_bio'
|
||||||
label={getLangText('Biography')}>
|
label={getLangText('Biography')}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
placeholder={getLangText('Enter your biography')}/>
|
placeholder={getLangText('Enter your biography')}/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='exhibition'
|
name='3-exhibition'
|
||||||
label={getLangText('Exhibition / Publication history (optional)')}>
|
label={getLangText('Exhibition / Publication history (optional)')}>
|
||||||
<InputTextAreaToggable
|
<InputTextAreaToggable
|
||||||
rows={1}
|
rows={1}
|
||||||
placeholder={getLangText('Enter exhibitions and publication history')}/>
|
placeholder={getLangText('Enter exhibitions and publication history')}/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='contact_information'
|
name='4-phone_number'
|
||||||
label={getLangText('Contact information')}>
|
label={getLangText('Phone Number')}>
|
||||||
<InputTextAreaToggable
|
<input
|
||||||
rows={1}
|
type="tel"
|
||||||
placeholder={getLangText('Enter your contact information (phone/website)')}/>
|
placeholder={getLangText('Enter your phone number')}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='5-email'
|
||||||
|
label={getLangText('Email Address')}>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder={getLangText('Enter your email')}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='6-website'
|
||||||
|
label={getLangText('Website')}>
|
||||||
|
<input
|
||||||
|
type="url"
|
||||||
|
placeholder={getLangText('Enter your website')}
|
||||||
|
required/>
|
||||||
</Property>
|
</Property>
|
||||||
</Form>
|
</Form>
|
||||||
<Form
|
<Form
|
||||||
@ -311,7 +337,7 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
createBlobRoutine={this.getCreateBlobRoutine()}
|
createBlobRoutine={this.getCreateBlobRoutine()}
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
fileClass: 'other_data'
|
fileClass: 'otherdata'
|
||||||
}}
|
}}
|
||||||
validation={{
|
validation={{
|
||||||
itemLimit: AppConstants.fineUploader.validation.registerWork.itemLimit,
|
itemLimit: AppConstants.fineUploader.validation.registerWork.itemLimit,
|
||||||
@ -333,7 +359,7 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
createBlobRoutine={this.getCreateBlobRoutine()}
|
createBlobRoutine={this.getCreateBlobRoutine()}
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
fileClass: 'other_data'
|
fileClass: 'otherdata'
|
||||||
}}
|
}}
|
||||||
validation={{
|
validation={{
|
||||||
itemLimit: AppConstants.fineUploader.validation.registerWork.itemLimit,
|
itemLimit: AppConstants.fineUploader.validation.registerWork.itemLimit,
|
||||||
@ -372,4 +398,4 @@ const PRRegisterPieceForm = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default PRRegisterPieceForm;
|
export default PRRegisterPieceForm;
|
||||||
|
@ -5,32 +5,18 @@ import { Link } from 'react-router';
|
|||||||
|
|
||||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||||
|
|
||||||
import UserStore from '../../../../../stores/user_store';
|
|
||||||
import UserActions from '../../../../../actions/user_actions';
|
|
||||||
|
|
||||||
import { getLangText } from '../../../../../utils/lang_utils';
|
import { getLangText } from '../../../../../utils/lang_utils';
|
||||||
|
|
||||||
|
|
||||||
const PRHero = React.createClass({
|
const PRHero = React.createClass({
|
||||||
getInitialState() {
|
propTypes: {
|
||||||
return UserStore.getState();
|
currentUser: React.PropTypes.shape({
|
||||||
},
|
email: React.PropTypes.object
|
||||||
|
})
|
||||||
componentDidMount() {
|
|
||||||
UserStore.listen(this.onChange);
|
|
||||||
UserActions.fetchCurrentUser.defer();
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
UserStore.unlisten(this.onChange);
|
|
||||||
},
|
|
||||||
|
|
||||||
onChange(state) {
|
|
||||||
this.setState(state);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { currentUser } = this.state;
|
const { currentUser } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="piece--hero">
|
<div className="piece--hero">
|
||||||
|
@ -6,6 +6,8 @@ import GlobalNotification from '../../../global_notification';
|
|||||||
import Hero from './components/pr_hero';
|
import Hero from './components/pr_hero';
|
||||||
import Header from '../../../header';
|
import Header from '../../../header';
|
||||||
|
|
||||||
|
import EventActions from '../../../../actions/event_actions';
|
||||||
|
|
||||||
import UserStore from '../../../../stores/user_store';
|
import UserStore from '../../../../stores/user_store';
|
||||||
import UserActions from '../../../../actions/user_actions';
|
import UserActions from '../../../../actions/user_actions';
|
||||||
|
|
||||||
@ -30,6 +32,19 @@ let PRApp = React.createClass({
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
|
|
||||||
|
if (this.state.currentUser && this.state.currentUser.email) {
|
||||||
|
EventActions.profileDidLoad.defer(this.state.currentUser);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillUpdate(nextProps, nextState) {
|
||||||
|
const { currentUser: { email: curEmail } = {} } = this.state;
|
||||||
|
const { currentUser: { email: nextEmail } = {} } = nextState;
|
||||||
|
|
||||||
|
if (nextEmail && curEmail !== nextEmail) {
|
||||||
|
EventActions.profileDidLoad.defer(nextState.currentUser);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@ -49,7 +64,7 @@ let PRApp = React.createClass({
|
|||||||
|
|
||||||
|
|
||||||
if (currentUser && currentUser.email && history.isActive(`/pieces/${getCookie(currentUser.email)}`)) {
|
if (currentUser && currentUser.email && history.isActive(`/pieces/${getCookie(currentUser.email)}`)) {
|
||||||
header = <Hero />;
|
header = <Hero currentUser={currentUser} />;
|
||||||
style = { paddingTop: '0 !important' };
|
style = { paddingTop: '0 !important' };
|
||||||
} else if(currentUser && (currentUser.is_admin || currentUser.is_jury || currentUser.is_judge)) {
|
} else if(currentUser && (currentUser.is_admin || currentUser.is_jury || currentUser.is_judge)) {
|
||||||
header = <Header routes={routes} />;
|
header = <Header routes={routes} />;
|
||||||
|
@ -6,6 +6,9 @@ import Moment from 'moment';
|
|||||||
|
|
||||||
import StarRating from 'react-star-rating';
|
import StarRating from 'react-star-rating';
|
||||||
|
|
||||||
|
import ReactError from '../../../../../../mixins/react_error';
|
||||||
|
import { ResourceNotFoundError } from '../../../../../../models/errors';
|
||||||
|
|
||||||
import PieceActions from '../../../../../../actions/piece_actions';
|
import PieceActions from '../../../../../../actions/piece_actions';
|
||||||
import PieceStore from '../../../../../../stores/piece_store';
|
import PieceStore from '../../../../../../stores/piece_store';
|
||||||
|
|
||||||
@ -54,6 +57,8 @@ let PieceContainer = React.createClass({
|
|||||||
params: React.PropTypes.object
|
params: React.PropTypes.object
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mixins: [ReactError],
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
PieceStore.getState(),
|
PieceStore.getState(),
|
||||||
@ -63,14 +68,15 @@ let PieceContainer = React.createClass({
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
PieceStore.listen(this.onChange);
|
PieceStore.listen(this.onChange);
|
||||||
PieceActions.fetchOne(this.props.params.pieceId);
|
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
UserActions.fetchCurrentUser();
|
|
||||||
|
|
||||||
// Every time we enter the piece detail page, just reset the piece
|
// 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
|
// store as it will otherwise display wrong/old data once the user loads
|
||||||
// the piece detail a second time
|
// the piece detail a second time
|
||||||
PieceActions.updatePiece({});
|
PieceActions.updatePiece({});
|
||||||
|
|
||||||
|
PieceActions.fetchOne(this.props.params.pieceId);
|
||||||
|
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
|
||||||
@ -82,6 +88,14 @@ let PieceContainer = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
const { pieceError } = this.state;
|
||||||
|
|
||||||
|
if (pieceError && pieceError.status === 404) {
|
||||||
|
this.throws(new ResourceNotFoundError(getLangText("Oops, the piece you're looking for doesn't exist.")));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
PieceStore.unlisten(this.onChange);
|
PieceStore.unlisten(this.onChange);
|
||||||
UserStore.unlisten(this.onChange);
|
UserStore.unlisten(this.onChange);
|
||||||
@ -92,10 +106,6 @@ let PieceContainer = React.createClass({
|
|||||||
this.setState(state);
|
this.setState(state);
|
||||||
},
|
},
|
||||||
|
|
||||||
loadPiece() {
|
|
||||||
PieceActions.fetchOne(this.props.params.pieceId);
|
|
||||||
},
|
|
||||||
|
|
||||||
getActions() {
|
getActions() {
|
||||||
if (this.state.piece &&
|
if (this.state.piece &&
|
||||||
this.state.piece.notifications &&
|
this.state.piece.notifications &&
|
||||||
@ -112,7 +122,7 @@ let PieceContainer = React.createClass({
|
|||||||
render() {
|
render() {
|
||||||
if(this.state.piece && this.state.piece.id) {
|
if(this.state.piece && this.state.piece.id) {
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This really needs a refactor!
|
This really needs a refactor!
|
||||||
|
|
||||||
- Tim
|
- Tim
|
||||||
@ -122,7 +132,7 @@ let PieceContainer = React.createClass({
|
|||||||
let artistName = ((this.state.currentUser.is_jury && !this.state.currentUser.is_judge) ||
|
let artistName = ((this.state.currentUser.is_jury && !this.state.currentUser.is_judge) ||
|
||||||
(this.state.currentUser.is_judge && !this.state.piece.selected )) ?
|
(this.state.currentUser.is_judge && !this.state.piece.selected )) ?
|
||||||
null : this.state.piece.artist_name;
|
null : this.state.piece.artist_name;
|
||||||
|
|
||||||
// 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
|
||||||
let artistEmail = (this.state.currentUser.is_judge && this.state.piece.selected ) ?
|
let artistEmail = (this.state.currentUser.is_judge && this.state.piece.selected ) ?
|
||||||
<DetailProperty label={getLangText('REGISTREE')} value={ this.state.piece.user_registered } /> : null;
|
<DetailProperty label={getLangText('REGISTREE')} value={ this.state.piece.user_registered } /> : null;
|
||||||
@ -146,7 +156,7 @@ let PieceContainer = React.createClass({
|
|||||||
<NavigationHeader
|
<NavigationHeader
|
||||||
piece={this.state.piece}
|
piece={this.state.piece}
|
||||||
currentUser={this.state.currentUser}/>
|
currentUser={this.state.currentUser}/>
|
||||||
|
|
||||||
<h1 className="ascribe-detail-title">{this.state.piece.title}</h1>
|
<h1 className="ascribe-detail-title">{this.state.piece.title}</h1>
|
||||||
<DetailProperty label={getLangText('BY')} value={artistName} />
|
<DetailProperty label={getLangText('BY')} value={artistName} />
|
||||||
<DetailProperty label={getLangText('DATE')} value={Moment(this.state.piece.date_created, 'YYYY-MM-DD').year()} />
|
<DetailProperty label={getLangText('DATE')} value={Moment(this.state.piece.date_created, 'YYYY-MM-DD').year()} />
|
||||||
@ -429,18 +439,21 @@ let PrizePieceDetails = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.props.piece
|
const { piece } = this.props;
|
||||||
&& this.props.piece.prize
|
|
||||||
&& this.props.piece.prize.name
|
if (piece &&
|
||||||
&& Object.keys(this.props.piece.extra_data).length !== 0){
|
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 ref='form'>
|
||||||
{Object.keys(this.props.piece.extra_data).map((data) => {
|
{Object.keys(piece.extra_data).sort().map((data) => {
|
||||||
let label = data.replace('_', ' ');
|
// Remove leading number (for sorting), if any, and underscores with spaces
|
||||||
const value = this.props.piece.extra_data[data] || 'N/A';
|
let label = data.replace(/^\d-/, '').replace(/_/g, ' ');
|
||||||
|
const value = piece.extra_data[data] || 'N/A';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Property
|
<Property
|
||||||
@ -460,8 +473,8 @@ let PrizePieceDetails = React.createClass({
|
|||||||
isReadyForFormSubmission={() => {}}
|
isReadyForFormSubmission={() => {}}
|
||||||
editable={false}
|
editable={false}
|
||||||
overrideForm={true}
|
overrideForm={true}
|
||||||
pieceId={this.props.piece.id}
|
pieceId={piece.id}
|
||||||
otherData={this.props.piece.other_data}
|
otherData={piece.other_data}
|
||||||
multiple={true} />
|
multiple={true} />
|
||||||
</Form>
|
</Form>
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
|
@ -13,8 +13,7 @@ import AppConstants from '../constants/application_constants';
|
|||||||
* @param {boolean} ignoreSentry Defines whether or not the error should be submitted to Sentry
|
* @param {boolean} ignoreSentry Defines whether or not the error should be submitted to Sentry
|
||||||
* @param {string} comment Will also be submitted to Sentry, but will not be logged
|
* @param {string} comment Will also be submitted to Sentry, but will not be logged
|
||||||
*/
|
*/
|
||||||
function logGlobal(error, ignoreSentry = AppConstants.errorMessagesToIgnore.indexOf(error.message) > -1,
|
function logGlobal(error, comment, ignoreSentry = AppConstants.errorMessagesToIgnore.indexOf(error.message) > -1) {
|
||||||
comment) {
|
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
||||||
if(!ignoreSentry) {
|
if(!ignoreSentry) {
|
||||||
@ -24,7 +23,6 @@ function logGlobal(error, ignoreSentry = AppConstants.errorMessagesToIgnore.inde
|
|||||||
Raven.captureException(error);
|
Raven.captureException(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initLogging() {
|
export function initLogging() {
|
||||||
@ -36,4 +34,4 @@ export function initLogging() {
|
|||||||
window.onerror = Raven.process;
|
window.onerror = Raven.process;
|
||||||
|
|
||||||
console.logGlobal = logGlobal;
|
console.logGlobal = logGlobal;
|
||||||
}
|
}
|
||||||
|
@ -10,71 +10,67 @@ import { argsToQueryParams } from '../utils/url_utils';
|
|||||||
|
|
||||||
|
|
||||||
class Requests {
|
class Requests {
|
||||||
unpackResponse(response) {
|
unpackResponse(url) {
|
||||||
if (response.status >= 500) {
|
return (response) => {
|
||||||
let err = new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url);
|
if (response == null) {
|
||||||
|
|
||||||
return response
|
|
||||||
.text()
|
|
||||||
.then((resText) => {
|
|
||||||
const resJson = JSON.parse(resText);
|
|
||||||
err = new Error(resJson.errors.pop());
|
|
||||||
|
|
||||||
// ES6 promises don't have a .finally() clause so
|
|
||||||
// we fake that here by forcing the .catch() clause
|
|
||||||
// to run
|
|
||||||
return Promise.reject();
|
|
||||||
})
|
|
||||||
.catch(() => { throw err; });
|
|
||||||
}
|
|
||||||
|
|
||||||
return Q.Promise((resolve, reject) => {
|
|
||||||
response.text()
|
|
||||||
.then((responseText) => {
|
|
||||||
// If the responses' body does not contain any data,
|
|
||||||
// fetch will resolve responseText to the string 'None'.
|
|
||||||
// If this is the case, we can not try to parse it as JSON.
|
|
||||||
if(responseText !== 'None') {
|
|
||||||
let body = JSON.parse(responseText);
|
|
||||||
|
|
||||||
if(body && body.errors) {
|
|
||||||
let error = new Error('Form Error');
|
|
||||||
error.json = body;
|
|
||||||
reject(error);
|
|
||||||
} else if(body && body.detail) {
|
|
||||||
reject(new Error(body.detail));
|
|
||||||
} else if('success' in body && !body.success) {
|
|
||||||
let error = new Error('Client Request Error');
|
|
||||||
error.json = {
|
|
||||||
status: response.status,
|
|
||||||
statusText: response.statusText,
|
|
||||||
type: response.type,
|
|
||||||
url: response.url
|
|
||||||
};
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if(response.status >= 400) {
|
|
||||||
reject(new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url));
|
|
||||||
} else {
|
|
||||||
resolve({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(reject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleError(url) {
|
|
||||||
return (err) => {
|
|
||||||
if (err instanceof TypeError) {
|
|
||||||
throw new Error('For: ' + url + ' - Server did not respond to the request. (Not even displayed a 500)');
|
throw new Error('For: ' + url + ' - Server did not respond to the request. (Not even displayed a 500)');
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
if (response.status >= 500) {
|
||||||
|
let err = new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url);
|
||||||
|
|
||||||
|
return response
|
||||||
|
.text()
|
||||||
|
.then((resText) => {
|
||||||
|
const resJson = JSON.parse(resText);
|
||||||
|
err = new Error(resJson.errors.pop());
|
||||||
|
|
||||||
|
// ES6 promises don't have a .finally() clause so
|
||||||
|
// we fake that here by forcing the .catch() clause
|
||||||
|
// to run
|
||||||
|
return Promise.reject();
|
||||||
|
})
|
||||||
|
.catch(() => { throw err; });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Q.Promise((resolve, reject) => {
|
||||||
|
response.text()
|
||||||
|
.then((responseText) => {
|
||||||
|
// If the responses' body does not contain any data,
|
||||||
|
// fetch will resolve responseText to the string 'None'.
|
||||||
|
// If this is the case, we can not try to parse it as JSON.
|
||||||
|
if(responseText !== 'None') {
|
||||||
|
let body = JSON.parse(responseText);
|
||||||
|
|
||||||
|
if(body && body.errors) {
|
||||||
|
let error = new Error('Form Error');
|
||||||
|
error.json = body;
|
||||||
|
reject(error);
|
||||||
|
} else if(body && body.detail) {
|
||||||
|
reject(new Error(body.detail));
|
||||||
|
} else if('success' in body && !body.success) {
|
||||||
|
let error = new Error('Client Request Error');
|
||||||
|
error.json = {
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
type: response.type,
|
||||||
|
url: response.url
|
||||||
|
};
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(response.status >= 400) {
|
||||||
|
reject(new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url));
|
||||||
|
} else {
|
||||||
|
resolve({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl(url) {
|
getUrl(url) {
|
||||||
@ -128,8 +124,7 @@ class Requests {
|
|||||||
}
|
}
|
||||||
merged.method = verb;
|
merged.method = verb;
|
||||||
return fetch(url, merged)
|
return fetch(url, merged)
|
||||||
.then(this.unpackResponse)
|
.then(this.unpackResponse(url));
|
||||||
.catch(this.handleError(url));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get(url, params) {
|
get(url, params) {
|
||||||
|
@ -145,4 +145,10 @@ $pr--button-color: $pr--nav-fg-prim-color;
|
|||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// intercom
|
||||||
|
#intercom-container .intercom-launcher-button {
|
||||||
|
background-color: $pr--button-color !important;
|
||||||
|
border-color: $pr--button-color !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user