1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 17:33:14 +01:00

Finalizing basic submission flow with lazy evaluated form

This commit is contained in:
Tim Daubenschütz 2015-11-09 17:52:09 +01:00
parent deceb61c60
commit 9ae6b10add
9 changed files with 183 additions and 37 deletions

View File

@ -2,6 +2,7 @@
import AppPrizeConstants from './prize_application_constants';
function getPrizeApiUrls(subdomain) {
return {
'users_login': AppPrizeConstants.prizeApiEndpoint + subdomain + '/users/login/',
@ -21,7 +22,6 @@ function getPrizeApiUrls(subdomain) {
'select_piece': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/${piece_id}/select/',
'notes': AppPrizeConstants.prizeApiEndpoint + subdomain + '/notes/',
'note': AppPrizeConstants.prizeApiEndpoint + subdomain + '/notes/${piece_id}/'
};
}

View File

@ -5,30 +5,107 @@ 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 InputCheckbox from '../../../../../ascribe_forms/input_checkbox';
import UploadFileButton from '../../../../../ascribe_buttons/upload_file_button';
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
import AppConstants from '../../../../../../constants/application_constants';
import ApiUrls from '../../../../../../constants/api_urls';
import requests from '../../../../../../utils/requests';
import { getLangText } from '../../../../../../utils/lang_utils';
import { setCookie } from '../../../../../../utils/fetch_api_utils';
const { object } = React.PropTypes;
const PRRegisterPieceForm = React.createClass({
propTypes: {
location: object
location: object,
history: object,
currentUser: object
},
getInitialState(){
return {
isUploadReady: false
isUploadReady: false,
piece: null
};
},
handleSuccess() {
/**
* In this method, we're composing all fields on the page
* in two steps, first submitting the registration of the piece and
* second adding all the additional details
*/
submit() {
const { currentUser } = this.props;
const { registerPieceForm,
digitalWorkForm,
proofOfPaymentForm,
supportingMaterialsForm,
additionalDataForm } = this.refs;
const additionalDataFormData = additionalDataForm.getFormData();
// composing data for piece registration
let registerPieceFormData = registerPieceForm.getFormData();
registerPieceFormData.digital_work_key = digitalWorkForm.state.file ? digitalWorkForm.state.file.key : '';
registerPieceFormData.terms = true;
// submitting the piece
requests
.post(ApiUrls.pieces_list, { body: registerPieceFormData })
.then(({ success, piece, notification }) => {
if(success) {
this.setState({
piece
}, () => {
supportingMaterialsForm.createBlobRoutine();
proofOfPaymentForm.createBlobRoutine();
//thumbnailForm.createBlobRoutine();
});
setCookie(currentUser.email, piece.id);
return requests.post(ApiUrls.piece_extradata, {
body: {
extradata: additionalDataFormData,
piece_id: piece.id
},
piece_id: piece.id
});
} else {
const notificationMessage = new GlobalNotificationModel(notification, 'danger', 5000);
GlobalNotificationActions.appendGlobalNotification(notificationMessage);
}
})
.catch((err) => {
console.log(err);
});
},
getCreateBlobRoutine(fileClass) {
const { piece } = this.state;
if(piece && piece.id) {
if(fileClass === 'other_data') {
return {
url: ApiUrls.blob_otherdatas,
pieceId: piece.id
};
} else if(fileClass === 'thumbnail') {
return {
url: ApiUrls.blob_thumbnail,
pieceId: piece.id
};
}
} else {
return null;
}
},
render() {
@ -37,8 +114,9 @@ const PRRegisterPieceForm = React.createClass({
return (
<div className="register-piece--form">
<Form
buttons={{}}
className="ascribe-form-bordered"
ref="registerPieceFields">
ref="registerPieceForm">
<Property
name='artist_name'
label={getLangText('Full name')}>
@ -64,35 +142,40 @@ const PRRegisterPieceForm = React.createClass({
min={1}
required/>
</Property>
</Form>
<Form
className="ascribe-form-bordered"
ref="additionalData">
<Property
name='biography'
label={getLangText('Biography')}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('THIS NEEDS TEXT')}/>
</Property>
<Property
name='artist_statement'
label={getLangText("Artist's statement")}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('THIS NEEDS TEXT')}/>
placeholder={getLangText('Enter your statement')}/>
</Property>
</Form>
<Form
buttons={{}}
className="ascribe-form-bordered"
ref="additionalDataForm">
<Property
name='artist_bio'
label={getLangText('Biography')}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter your biography')}/>
</Property>
<Property
name='exhibition'
label={getLangText('Exhibition / Publication history (optional)')}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('THIS NEEDS TEXT')}/>
placeholder={getLangText('Enter exhibitions and publication history')}/>
</Property>
</Form>
<div className="input-upload-file-button-property">
{getLangText('Select the PDF with your work')}
<UploadFileButton
ref="digitalWorkForm"
createBlobRoutine={{
url: ApiUrls.blob_digitalworks
}}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'digitalwork'
@ -111,6 +194,8 @@ const PRRegisterPieceForm = React.createClass({
<div className="input-upload-file-button-property">
{getLangText('Featured Cover photo')}
<UploadFileButton
ref="thumbnailForm"
createBlobRoutine={this.getCreateBlobRoutine('thumbnail')}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'thumbnail'
@ -129,6 +214,8 @@ const PRRegisterPieceForm = React.createClass({
<div className="input-upload-file-button-property">
{getLangText('Supporting Materials (Optional)')}
<UploadFileButton
ref="supportingMaterialsForm"
createBlobRoutine={this.getCreateBlobRoutine('other_data')}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'other_data'
@ -146,13 +233,16 @@ const PRRegisterPieceForm = React.createClass({
<div className="input-upload-file-button-property">
{getLangText('Proof of payment')}
<UploadFileButton
ref="proofOfPaymentForm"
createBlobRoutine={this.getCreateBlobRoutine('other_data')}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'other_data'
}}
validation={{
itemLimit: AppConstants.fineUploader.validation.registerWork.itemLimit,
sizeLimit: AppConstants.fineUploader.validation.additionalData.sizeLimit
sizeLimit: AppConstants.fineUploader.validation.additionalData.sizeLimit,
allowedExtensions: ['png', 'jpg']
}}
location={location}
fileClassToUpload={{
@ -161,23 +251,23 @@ const PRRegisterPieceForm = React.createClass({
}}/>
</div>
<Form
className="ascribe-form-bordered"
ref="terms">
buttons={{}}
className="ascribe-form-bordered">
<Property
ref="termsForm"
name="terms"
className="ascribe-property-collapsible-toggle"
style={{paddingBottom: 0}}>
<InputCheckbox
key="terms_explicitly"
defaultChecked={false}>
&nbsp;{getLangText('I agree to the Terms and Conditions of the Portfolio Review')}
</InputCheckbox>
<span>
<input type="checkbox" value="true" />
{getLangText('By submitting this form, you agree to the Terms of Service of Portfolio Review.')}
</span>
</Property>
</Form>
<button
type="submit"
className="btn btn-default btn-wide"
disabled={!this.state.isUploadReady}>
onClick={this.submit}>
{getLangText('Submit to Portfolio Review')}
</button>
</div>

View File

@ -1,14 +1,19 @@
'use strict';
import React from 'react';
import { Link, History } from 'react-router';
import Col from 'react-bootstrap/lib/Col';
import Row from 'react-bootstrap/lib/Row';
import UserStore from '../../../../../stores/user_store';
import UserActions from '../../../../../actions/user_actions';
import PRRegisterPieceForm from './pr_forms/pr_register_piece_form';
import { getLangText } from '../../../../../utils/lang_utils';
import { setDocumentTitle } from '../../../../../utils/dom_utils';
import { getCookie } from '../../../../../utils/fetch_api_utils';
const { object } = React.PropTypes;
@ -18,7 +23,37 @@ const PRRegisterPiece = React.createClass({
location: object
},
mixins: [History],
getInitialState() {
return UserStore.getState();
},
componentDidMount() {
UserStore.listen(this.onChange);
UserActions.fetchCurrentUser();
},
componentDidUpdate() {
const { currentUser } = this.state;
if(currentUser && currentUser.email) {
const submittedPieceId = getCookie(currentUser.email);
if(submittedPieceId) {
this.history.pushState(null, `/pieces/${submittedPieceId}`);
}
}
},
componentWillUnmount() {
UserStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
render() {
const { currentUser } = this.state;
const { location } = this.props;
setDocumentTitle(getLangText('Submission form'));
@ -28,14 +63,25 @@ const PRRegisterPiece = React.createClass({
<div className="register-piece--hero">
<h1>Portfolio Review</h1>
<h2>{getLangText('Submission closing on %s', ' 21 Dec 2015')}</h2>
<p>{getLangText('Submissions are open to everyone, we accept only PDFs.')}</p>
<p>{getLangText('We accept only one PDF with up to 20 images from every participant.')}</p>
<p>{getLangText('You need to pay 50€ in order to apply. We only accept PayPal.')}</p>
<p>
{getLangText('Submissions are open to everyone, we accept only PDFs.')}
</p>
<p>
{getLangText('We accept only one PDF with up to 20 images from every participant.')}
</p>
<p>
{getLangText('You need to pay 50€ in order to apply. We only accept PayPal.')}
</p>
<p style={{marginTop: '1em'}}>
{getLangText("You're submitting as %s. ", currentUser.email)}
<Link to="/logout">{getLangText('Change account?')}</Link>
</p>
</div>
</Col>
<Col xs={6}>
<PRRegisterPieceForm
location={location}/>
location={location}
currentUser={currentUser}/>
</Col>
</Row>
);

View File

@ -1,7 +1,6 @@
'use strict';
import React from 'react';
import Footer from '../../../footer';
import GlobalNotification from '../../../global_notification';
import { getSubdomain } from '../../../../utils/general_utils';
@ -26,7 +25,6 @@ let PrizeApp = React.createClass({
{children}
<GlobalNotification />
<div id="modal" className="container"></div>
<Footer />
</div>
);
}

View File

@ -78,6 +78,7 @@ const ROUTES = {
<Route
path='password_reset'
component={AuthProxyHandler({to: '/register_piece', when: 'loggedIn'})(PasswordResetContainer)} />
<Route path='pieces/:pieceId' component={SPPieceContainer} />
<Route path='*' component={ErrorNotFoundPage} />
</Route>
)

View File

@ -14,6 +14,7 @@ let ApiUrls = {
'blob_digitalworks': AppConstants.apiEndpoint + 'blob/digitalworks/',
'blob_otherdatas': AppConstants.apiEndpoint + 'blob/otherdatas/',
'blob_contracts': AppConstants.apiEndpoint + 'blob/contracts/',
'blob_thumbnails': AppConstants.apiEndpoint + 'blob/thumbnails/',
'coa': AppConstants.apiEndpoint + 'coa/${id}/',
'coa_create': AppConstants.apiEndpoint + 'coa/',
'coa_verify': AppConstants.apiEndpoint + 'coa/verify_coa/',

View File

@ -1,6 +1,7 @@
'use strict';
import Q from 'q';
import moment from 'moment';
import { sanitize } from './general_utils';
import AppConstants from '../constants/application_constants';
@ -70,12 +71,20 @@ export function getCookie(name) {
let parts = document.cookie.split(';');
for(let i = 0; i < parts.length; i++) {
if(parts[i].indexOf(AppConstants.csrftoken + '=') > -1) {
if(parts[i].indexOf(name + '=') > -1) {
return parts[i].split('=').pop();
}
}
}
export function setCookie(key, value, days) {
const exdate = moment();
exdate.add(days, 'days');
console.log(exdate.utc());
value = window.escape(value) + ((days === null) ? '' : `; expires= ${exdate.utc()}`);
document.cookie = `${key}=${value}`;
}
/*
Given a url for an image, this method fetches it and returns a promise that resolves to

View File

@ -222,7 +222,7 @@ $ascribe-red-error: rgb(169, 68, 66);
.input-upload-file-button-property {
background-color: white;
padding: 1.5em 0 1.5em 0;
padding: 1em 0 1em 0;
text-align: right;
button {

View File

@ -31,6 +31,7 @@
}
.register-piece--form {
margin-bottom: 3em;
form {
border-top: none;