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

Remove prize whitelabels

This commit is contained in:
Brett Sun 2016-05-27 12:04:36 +02:00
parent 53ef5248ca
commit 37e4b68afb
49 changed files with 17 additions and 3047 deletions

View File

@ -1,89 +0,0 @@
'use strict';
import React from 'react';
import Form from './form';
import Property from './property';
import InputTextAreaToggable from './input_textarea_toggable';
import InputCheckbox from './input_checkbox';
import Alert from 'react-bootstrap/lib/Alert';
import AscribeSpinner from '../ascribe_spinner';
import ApiUrls from '../../constants/api_urls';
import { getLangText } from '../../utils/lang_utils.js';
import requests from '../../utils/requests';
let PieceSubmitToPrizeForm = React.createClass({
propTypes: {
piece: React.PropTypes.object,
handleSuccess: React.PropTypes.func
},
render() {
return (
<Form
ref='form'
url={requests.prepareUrl(ApiUrls.piece_submit_to_prize, {piece_id: this.props.piece.id})}
handleSuccess={this.props.handleSuccess}
buttons={
<div className="modal-footer">
<p className="pull-right">
<button
className="btn btn-default btn-sm ascribe-margin-1px"
type="submit">
{getLangText('SUBMIT TO PRIZE')}
</button>
</p>
</div>}
spinner={
<div className="modal-footer">
<p className="pull-right">
<AscribeSpinner color='dark-blue' size='md'/>
</p>
</div>}>
<Property
name='artist_statement'
label={getLangText('Artist statement')}
editable={true}
overrideForm={true}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter your statement')}
required />
</Property>
<Property
name='work_description'
label={getLangText('Work description')}
editable={true}
overrideForm={true}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter the description for your work')}
required />
</Property>
<Property
name="terms"
className="ascribe-property-collapsible-toggle">
<InputCheckbox>
<span>
{' ' + getLangText('I agree to the Terms of Service the art price') + ' '}
(<a href="https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/sluice/terms.pdf" target="_blank" style={{fontSize: '0.9em', color: 'rgba(0,0,0,0.7)'}}>
{getLangText('read')}
</a>)
</span>
</InputCheckbox>
</Property>
<Alert bsStyle='warning'>
<p>{getLangText('Are you sure you want to submit to the prize?')}</p>
<p>{getLangText('This is an irrevocable action%s', '.')}</p>
</Alert>
</Form>
);
}
});
export default PieceSubmitToPrizeForm;

View File

@ -1,28 +0,0 @@
'use strict';
import AppPrizeConstants from './prize_application_constants';
function getPrizeApiUrls(subdomain) {
return {
'users_login': AppPrizeConstants.prizeApiEndpoint + subdomain + '/users/login/',
'users_signup': AppPrizeConstants.prizeApiEndpoint + subdomain + '/users/',
'user': AppPrizeConstants.prizeApiEndpoint + subdomain + '/users/',
'piece_submit_to_prize': AppPrizeConstants.prizeApiEndpoint + subdomain + '/pieces/${piece_id}/submit/',
'pieces_list': AppPrizeConstants.prizeApiEndpoint + subdomain + '/pieces/',
'piece': AppPrizeConstants.prizeApiEndpoint + subdomain + '/pieces/${piece_id}/',
'prize': AppPrizeConstants.prizeApiEndpoint + subdomain + '/',
'jurys': AppPrizeConstants.prizeApiEndpoint + subdomain + '/jury/',
'jury': AppPrizeConstants.prizeApiEndpoint + subdomain + '/jury/${email}/',
'jury_activate': AppPrizeConstants.prizeApiEndpoint + subdomain + '/jury/${email}/activate/',
'jury_resend': AppPrizeConstants.prizeApiEndpoint + subdomain + '/jury/${email}/resend/',
'ratings': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/',
'rating': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/${piece_id}/',
'rating_average': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/${piece_id}/average/',
'select_piece': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/${piece_id}/select/',
'notes': AppPrizeConstants.prizeApiEndpoint + subdomain + '/notes/',
'note': AppPrizeConstants.prizeApiEndpoint + subdomain + '/notes/${piece_id}/'
};
}
export default getPrizeApiUrls;

View File

@ -1,9 +0,0 @@
'use strict';
import AppConstants from '../../../../constants/application_constants';
let prizeConstants = {
prizeApiEndpoint: AppConstants.apiEndpoint + 'prizes/'
};
export default prizeConstants;

View File

@ -1,417 +0,0 @@
'use strict';
import React from 'react';
import { History } from 'react-router';
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
import Form from '../../../../../ascribe_forms/form';
import Property from '../../../../../ascribe_forms/property';
import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable';
import InputFineuploader from '../../../../../ascribe_forms/input_fineuploader';
import UploadButton from '../../../../../ascribe_uploader/ascribe_upload_button/upload_button';
import AscribeSpinner from '../../../../../ascribe_spinner';
import ApiUrls from '../../../../../../constants/api_urls';
import AppConstants from '../../../../../../constants/application_constants';
import { validationParts, validationTypes } from '../../../../../../constants/uploader_constants';
import requests from '../../../../../../utils/requests';
import { getErrorNotificationMessage } from '../../../../../../utils/error_utils';
import { setCookie } from '../../../../../../utils/fetch_api_utils';
import { validateForms } from '../../../../../../utils/form_utils';
import { getLangText } from '../../../../../../utils/lang_utils';
import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils';
const { object } = React.PropTypes;
const PRRegisterPieceForm = React.createClass({
propTypes: {
currentUser: object.isRequired,
location: object
},
mixins: [History],
getInitialState() {
return {
digitalWorkKeyReady: true,
thumbnailKeyReady: true,
// we set this to true, as it is not required
supportingMaterialsReady: true,
proofOfPaymentReady: true,
piece: null,
submitted: false
};
},
/**
* 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() {
if (!this.validateForms()) {
return;
}
// disable the submission button right after the user
// clicks on it to avoid double submission
this.setState({
submitted: true
});
const { currentUser } = this.props;
const { registerPieceForm,
additionalDataForm,
uploadersForm } = this.refs;
const { digitalWorkKey,
thumbnailKey,
supportingMaterials,
proofOfPayment } = uploadersForm.refs;
const additionalDataFormData = additionalDataForm.getFormData();
// composing data for piece registration
const registerPieceFormData = registerPieceForm.getFormData();
registerPieceFormData.digital_work_key = digitalWorkKey.state.value;
registerPieceFormData.thumbnail_file = thumbnailKey.state.value;
registerPieceFormData.terms = true;
// submitting the piece
requests
.post(ApiUrls.pieces_list, { body: registerPieceFormData })
.then(({ piece, notification }) => {
this.setState({piece}, () => {
supportingMaterials.refs.input.createBlobRoutine();
proofOfPayment.refs.input.createBlobRoutine();
});
setCookie(currentUser.email, piece.id);
return requests
.post(ApiUrls.piece_extradata, {
body: {
extradata: additionalDataFormData,
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);
});
})
.then(() => this.history.push(`/pieces/${this.state.piece.id}`))
.catch((err) => {
const errMessage = (getErrorNotificationMessage(err) || getLangText("Oops! We weren't able to send your submission.")) +
getLangText(' Please contact support@ascribe.io');
const notificationMessage = new GlobalNotificationModel(errMessage, 'danger', 10000);
GlobalNotificationActions.appendGlobalNotification(notificationMessage);
console.logGlobal(new Error('Portfolio Review piece registration failed'), err);
// Reset the submit button
this.setState({
submitted: false
});
});
},
validateForms() {
const { registerPieceForm,
additionalDataForm,
uploadersForm } = this.refs;
return validateForms([registerPieceForm, additionalDataForm, uploadersForm], true);
},
getCreateBlobRoutine() {
const { piece } = this.state;
if(piece && piece.id) {
return {
url: ApiUrls.blob_otherdatas,
pieceId: piece.id
};
} else {
return null;
}
},
/**
* These two methods are overloaded so that we can track the ready-state
* of each uploader in the component
* @param {string} uploaderKey Name of the uploader's key to track
*/
setIsUploadReady(uploaderKey) {
return (isUploadReady) => {
this.setState({
[uploaderKey]: isUploadReady
});
};
},
handleOptionalFileValidationFailed(uploaderKey) {
return () => {
this.setState({
[uploaderKey]: true
});
};
},
getSubmitButton() {
const { digitalWorkKeyReady,
thumbnailKeyReady,
supportingMaterialsReady,
proofOfPaymentReady,
submitted } = this.state;
if(submitted) {
return (
<span disabled className="btn btn-default btn-wide btn-spinner">
<AscribeSpinner color="dark-blue" size="md" />
</span>
);
} else {
return (
<button
type="button"
className="btn btn-default btn-wide"
disabled={!(digitalWorkKeyReady && thumbnailKeyReady && proofOfPaymentReady && supportingMaterialsReady)}
onClick={this.submit}>
{getLangText('Submit to Portfolio Review')}
</button>
);
}
},
render() {
const { location } = this.props;
const maxThumbnailSize = validationTypes.workThumbnail.sizeLimit / 1000000;
return (
<div className="register-piece--form">
<Form
buttons={null}
className="ascribe-form-bordered"
ref="registerPieceForm">
<Property
name='artist_name'
label={getLangText('Full name')}>
<input
type="text"
placeholder={getLangText('(e.g. Andy Warhol)')}
required/>
</Property>
<Property
name='title'
label={getLangText('Title of the Work')}>
<input
type="text"
placeholder={getLangText("(e.g. 32 Campbell's Soup Cans)")}
required/>
</Property>
<Property
name='date_created'
label={getLangText('Year of creation')}>
<input
type="number"
placeholder={getLangText('(e.g. 1962)')}
min={1}
required/>
</Property>
<Property
name='artist_statement'
label={getLangText("Artist's statement")}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter your statement')}/>
</Property>
</Form>
<Form
buttons={null}
className="ascribe-form-bordered"
ref="additionalDataForm">
<Property
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')}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter your biography')}/>
</Property>
<Property
name='3-exhibition'
label={getLangText('Exhibition / Publication history (optional)')}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter exhibitions and publication history')}/>
</Property>
<Property
name='4-phone_number'
label={getLangText('Phone Number')}>
<input
type="tel"
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>
</Form>
<Form
buttons={null}
className="ascribe-form-bordered"
ref="uploadersForm">
<Property
name="digitalWorkKey"
label={getLangText('Select the PDF with your work')}>
<InputFineuploader
fileInputElement={UploadButton()}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
setIsUploadReady={this.setIsUploadReady('digitalWorkKeyReady')}
createBlobRoutine={{
url: ApiUrls.blob_digitalworks
}}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'digitalwork'
}}
validation={{
itemLimit: validationTypes.registerWork.itemLimit,
sizeLimit: validationTypes.additionalData.sizeLimit,
allowedExtensions: ['pdf']
}}
location={location}
fileClassToUpload={{
singular: getLangText('Select the Portfolio'),
plural: getLangText('Select the Portfolios')
}}
required/>
</Property>
<Property
name="thumbnailKey"
label={`${getLangText('Featured Cover photo')} (max ${maxThumbnailSize}MB)`}>
<InputFineuploader
fileInputElement={UploadButton()}
createBlobRoutine={{
url: ApiUrls.blob_thumbnails
}}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
setIsUploadReady={this.setIsUploadReady('thumbnailKeyReady')}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'thumbnail'
}}
validation={{
itemLimit: validationTypes.workThumbnail.itemLimit,
sizeLimit: validationTypes.workThumbnail.sizeLimit,
allowedExtensions: validationParts.allowedExtensions.images
}}
location={location}
fileClassToUpload={{
singular: getLangText('Select cover photo'),
plural: getLangText('Select cover photos')
}}
required/>
</Property>
<Property
name="supportingMaterials"
label={getLangText('Supporting Materials (Optional)')}>
<InputFineuploader
fileInputElement={UploadButton()}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
setIsUploadReady={this.setIsUploadReady('supportingMaterialsReady')}
onValidationFailed={this.handleOptionalFileValidationFailed('supportingMaterialsReady')}
createBlobRoutine={this.getCreateBlobRoutine()}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'otherdata'
}}
validation={{
itemLimit: validationParts.itemLimit.single,
sizeLimit: validationTypes.additionalData.sizeLimit
}}
location={location}
fileClassToUpload={{
singular: getLangText('Select supporting material'),
plural: getLangText('Select supporting materials')
}}/>
</Property>
<Property
name="proofOfPayment"
label={getLangText('Proof of payment')}>
<InputFineuploader
fileInputElement={UploadButton()}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
setIsUploadReady={this.setIsUploadReady('proofOfPaymentReady')}
createBlobRoutine={this.getCreateBlobRoutine()}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'otherdata'
}}
validation={{
itemLimit: validationParts.itemLimit.single,
sizeLimit: validationTypes.additionalData.sizeLimit,
allowedExtensions: validationParts.allowedExtensions.images
}}
location={location}
fileClassToUpload={{
singular: getLangText('Select Screenshot'),
plural: getLangText('Select Screenshots')
}}
required/>
</Property>
</Form>
<Form
buttons={null}
className="ascribe-form-bordered">
<Property
name="terms"
className="ascribe-property-collapsible-toggle">
<span>
{getLangText('By submitting this form, you agree to the') + ' '}
<a
href="https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/portfolioreview/tos-portfolioreview.pdf"
target="_blank">
{getLangText('Terms of Service')}
</a>
{' of Portfolio Review.'}
</span>
</Property>
</Form>
{this.getSubmitButton()}
</div>
);
}
});
export default PRRegisterPieceForm;

View File

@ -1,33 +0,0 @@
'use strict';
import React from 'react';
import { Link } from 'react-router';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import { getLangText } from '../../../../../utils/lang_utils';
const PRHero = React.createClass({
propTypes: {
currentUser: React.PropTypes.shape({
email: React.PropTypes.object
}).isRequired
},
render() {
const { currentUser } = this.props;
return (
<div className="piece--hero">
<h2><Glyphicon glyph="ok" />
&nbsp;{getLangText('Congratulations') + (currentUser.email ? ` ${currentUser.email}!` : '!')}
</h2>
<h1>{getLangText('You have successfully submitted to Portfolio Review 2016.')}</h1>
<p>Not you? <Link to="/logout">{getLangText('Change account.')}</Link></p>
</div>
);
}
});
export default PRHero;

View File

@ -1,124 +0,0 @@
'use strict';
import React from 'react';
import { History } from 'react-router';
import Button from 'react-bootstrap/lib/Button';
import ButtonGroup from 'react-bootstrap/lib/ButtonGroup';
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
import PrizeActions from '../../simple_prize/actions/prize_actions';
import PrizeStore from '../../simple_prize/stores/prize_store';
import { omitFromObject } from '../../../../../utils/general_utils';
import { getLangText } from '../../../../../utils/lang_utils';
const PRLanding = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object
},
mixins: [History],
getInitialState() {
return PrizeStore.getState();
},
componentDidMount() {
const { location } = this.props;
PrizeStore.listen(this.onChange);
PrizeActions.fetchPrize();
if (location.query.redirect) {
window.setTimeout(() => this.history.replace({
pathname: `/${location.query.redirect}`,
query: omitFromObject(location.query, ['redirect'])
}));
}
},
componentWillUnmount() {
PrizeStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
getButtons() {
if (this.state.prize && this.state.prize.active) {
return (
<ButtonGroup className="enter" bsSize="large" vertical>
<LinkContainer to="/signup">
<Button>
{getLangText('Sign up to submit')}
</Button>
</LinkContainer>
<p>
{getLangText('or, already an ascribe user?')}
</p>
<LinkContainer to="/login">
<Button>
{getLangText('Log in to submit')}
</Button>
</LinkContainer>
</ButtonGroup>
);
} else {
return (
<ButtonGroup className="enter" bsSize="large" vertical>
<a className="btn btn-default" href="https://www.ascribe.io/app/signup">
{getLangText('Sign up to ascribe')}
</a>
<p>
{getLangText('or, already an ascribe user?')}
</p>
<LinkContainer to="/login">
<Button>
{getLangText('Log in')}
</Button>
</LinkContainer>
</ButtonGroup>
);
}
},
getTitle() {
const { prize } = this.state;
return (
<p>
{getLangText(prize && prize.active ? 'This is the submission page for Portfolio Review 2016.'
: 'Submissions for Portfolio Review 2016 are now closed.')}
</p>
);
},
render() {
return (
<div className="container">
<div className="row">
<div className="col-xs-12 wp-landing-wrapper">
<h1>
{getLangText('Welcome to Portfolio Review 2016')}
</h1>
{this.getTitle()}
{this.getButtons()}
</div>
</div>
</div>
);
}
});
export default PRLanding;

View File

@ -1,72 +0,0 @@
'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 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;
const PRRegisterPiece = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object,
// Provided from router
location: object
},
mixins: [History],
componentDidUpdate() {
const { currentUser } = this.props;
if (currentUser.email) {
const submittedPieceId = getCookie(currentUser.email);
if (submittedPieceId) {
this.history.push(`/pieces/${submittedPieceId}`);
}
}
},
render() {
const { currentUser, location } = this.props;
setDocumentTitle(getLangText('Submit to Portfolio Review'));
return (
<Row>
<Col xs={6}>
<div className="register-piece--info">
<h1>Portfolio Review</h1>
<h2>{getLangText('Submission closing on %s', ' 27 Dec 2015')}</h2>
<p>For more information, visit:&nbsp;
<a href="http://www.portfolio-review.de/submission/" target="_blank">
portfolio-review.de
</a>
</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}
currentUser={currentUser} />
</Col>
</Row>
);
}
});
export default PRRegisterPiece;

View File

@ -1,26 +0,0 @@
'use strict';
import history from '../../../../../../history';
export function AuthPrizeRoleRedirect({ to, when }) {
if (when.constructor !== Array || !when.length) {
throw new Error('`when` of AuthPrizeRoleRedirect must be an array containing values');
}
if (!to || to.indexOf('/') === -1) {
throw new Error('`to` of AuthPrizeRoleRedirect must be defined and contain a valid route');
}
return function(currentUser, query) {
const exprToValidate = when
.map(role => currentUser[role])
.reduce((a, b) => a || b);
if (exprToValidate) {
window.setTimeout(() => history.replace({ query, pathname: to }));
return true;
} else {
return false;
}
};
}

View File

@ -1,73 +0,0 @@
'use strict';
import React from 'react';
import classNames from 'classnames';
import EventActions from '../../../../actions/event_actions';
import UserStore from '../../../../stores/user_store';
import UserActions from '../../../../actions/user_actions';
import Hero from './components/pr_hero';
import AppBase from '../../../app_base';
import AppRouteWrapper from '../../../app_route_wrapper';
import Header from '../../../header';
import { getSubdomain } from '../../../../utils/general_utils';
import { getCookie } from '../../../../utils/fetch_api_utils';
let PRApp = React.createClass({
propTypes: {
activeRoute: React.PropTypes.object.isRequired,
children: React.PropTypes.element.isRequired,
history: React.PropTypes.object.isRequired,
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
// Provided from AppBase
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object
},
render() {
const { activeRoute, children, currentUser, history, routes, whitelabel } = this.props;
const subdomain = getSubdomain();
const path = activeRoute && activeRoute.path;
const Footer = activeRoute && activeRoute.footer;
let style = {};
let header;
if (currentUser && currentUser.email && history.isActive(`/pieces/${getCookie(currentUser.email)}`)) {
header = (<Hero currentUser={currentUser} />);
style = { paddingTop: '0 !important' };
} else if (currentUser && (currentUser.is_admin || currentUser.is_jury || currentUser.is_judge)) {
header = (
<Header
currentUser={currentUser}
routes={routes}
whitelabel={whitelabel}
/>
);
} else {
style = { paddingTop: '0 !important' };
}
return (
<div
style={style}
className={classNames('ascribe-app', 'ascribe-prize-app', `route--${(path ? path.split('/')[0] : 'landing')}`)}>
{header}
<AppRouteWrapper
currentUser={currentUser}
whitelabel={whitelabel}>
{/* Routes are injected here */}
{children}
</AppRouteWrapper>
{Footer ? <Footer /> : null}
</div>
);
}
});
export default AppBase(PRApp);

View File

@ -1,137 +0,0 @@
'use strict';
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import { ProxyHandler, AuthRedirect } from '../../../components/ascribe_routes/proxy_handler';
import { AuthPrizeRoleRedirect } from './portfolioreview/components/pr_routes/pr_proxy_handler';
// General components
import EditionContainer from '../../ascribe_detail/edition_container';
import LogoutContainer from '../../logout_container';
import PasswordResetContainer from '../../password_reset_container';
import CoaVerifyContainer from '../../coa_verify_container';
import ErrorNotFoundPage from '../../error_not_found_page';
import SPApp from './simple_prize/prize_app';
import SPLanding from './simple_prize/components/prize_landing';
import SPLoginContainer from './simple_prize/components/prize_login_container';
import SPSignupContainer from './simple_prize/components/prize_signup_container';
import SPRegisterPiece from './simple_prize/components/prize_register_piece';
import SPPieceList from './simple_prize/components/prize_piece_list';
import SPPieceContainer from './simple_prize/components/ascribe_detail/prize_piece_container';
import SPSettingsContainer from './simple_prize/components/prize_settings_container';
import SluicePieceContainer from './sluice/components/sluice_detail/sluice_piece_container';
import PRApp from './portfolioreview/pr_app';
import PRLanding from './portfolioreview/components/pr_landing';
import PRRegisterPiece from './portfolioreview/components/pr_register_piece';
import { getLangText } from '../../../utils/lang_utils';
const ROUTES = {
sluice: (
<Route path='/' component={SPApp}>
<IndexRoute
component={ProxyHandler(AuthRedirect({to: '/collection', when: 'loggedIn'}))(SPLanding)} />
<Route
path='login'
component={ProxyHandler(AuthRedirect({to: '/collection', when: 'loggedIn'}))(SPLoginContainer)} />
<Route
path='logout'
component={ProxyHandler(AuthRedirect({to: '/', when: 'loggedOut'}))(LogoutContainer)} />
<Route
path='signup'
component={ProxyHandler(AuthRedirect({to: '/collection', when: 'loggedIn'}))(SPSignupContainer)} />
<Route
path='password_reset'
component={ProxyHandler(AuthRedirect({to: '/collection', when: 'loggedIn'}))(PasswordResetContainer)} />
<Route
path='settings'
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(SPSettingsContainer)} />
<Route
path='register_piece'
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(SPRegisterPiece)}
headerTitle={getLangText('+ NEW WORK')} />
<Route
path='collection'
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(SPPieceList)}
headerTitle={getLangText('COLLECTION')} />
<Route
path='pieces/:pieceId'
component={SluicePieceContainer} />
<Route
path='editions/:editionId'
component={EditionContainer} />
<Route
path='coa_verify'
component={CoaVerifyContainer} />
<Route
path='*'
component={ErrorNotFoundPage} />
</Route>
),
portfolioreview: (
<Route path='/' component={PRApp}>
<IndexRoute
component={ProxyHandler(AuthPrizeRoleRedirect({ to: '/collection', when: ['is_admin', 'is_judge', 'is_jury'] }))(PRLanding)} />
<Route
path='register_piece'
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(PRRegisterPiece)} />
<Route
path='collection'
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(SPPieceList)}
headerTitle={getLangText('SUBMISSIONS')} />
<Route
path='login'
component={ProxyHandler(
AuthPrizeRoleRedirect({ to: '/collection', when: ['is_admin', 'is_judge', 'is_jury'] }),
AuthRedirect({to: '/register_piece', when: 'loggedIn'})
)(SPLoginContainer)} />
<Route
path='logout'
component={ProxyHandler(AuthRedirect({to: '/', when: 'loggedOut'}))(LogoutContainer)} />
<Route
path='signup'
component={ProxyHandler(
AuthPrizeRoleRedirect({ to: '/collection', when: ['is_admin', 'is_judge', 'is_jury'] }),
AuthRedirect({to: '/register_piece', when: 'loggedIn'})
)(SPSignupContainer)} />
<Route
path='password_reset'
component={ProxyHandler(
AuthPrizeRoleRedirect({ to: '/collection', when: ['is_admin', 'is_judge', 'is_jury'] }),
AuthRedirect({to: '/register_piece', when: 'loggedIn'})
)(PasswordResetContainer)} />
<Route
path='settings'
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(SPSettingsContainer)} />
<Route
path='pieces/:pieceId'
component={SPPieceContainer} />
<Route
path='editions/:editionId'
component={EditionContainer} />
<Route
path='coa_verify'
component={CoaVerifyContainer} />
<Route
path='*'
component={ErrorNotFoundPage} />
</Route>
)
};
function getRoutes(commonRoutes, subdomain) {
if(subdomain in ROUTES) {
return ROUTES[subdomain];
} else {
throw new Error('Subdomain wasn\'t specified in the wallet app.');
}
}
export default getRoutes;

View File

@ -1,28 +0,0 @@
'use strict';
import { alt } from '../../../../../alt';
import PrizeFetcher from '../fetchers/prize_fetcher';
class PrizeActions {
constructor() {
this.generateActions(
'updatePrize'
);
}
fetchPrize() {
PrizeFetcher
.fetch()
.then((res) => {
this.actions.updatePrize({
prize: res
});
})
.catch((err) => {
console.logGlobal(err);
});
}
}
export default alt.createActions(PrizeActions);

View File

@ -1,76 +0,0 @@
'use strict';
import { alt } from '../../../../../alt';
import Q from 'q';
import PrizeJuryFetcher from '../fetchers/prize_jury_fetcher';
class PrizeJuryActions {
constructor() {
this.generateActions(
'updatePrizeJury',
'removePrizeJury',
'activatePrizeJury'
);
}
fetchJury() {
return Q.Promise((resolve, reject) => {
PrizeJuryFetcher
.fetch()
.then((res) => {
this.actions.updatePrizeJury(res.members);
resolve(res);
})
.catch((err) => {
console.logGlobal(err);
reject(err);
});
});
}
activateJury(email) {
return Q.Promise((resolve, reject) => {
PrizeJuryFetcher
.activate(email)
.then((res) => {
resolve(res);
})
.catch((err) => {
console.logGlobal(err);
reject(err);
});
});
}
revokeJury(email) {
return Q.Promise((resolve, reject) => {
PrizeJuryFetcher
.delete(email)
.then((res) => {
this.actions.removePrizeJury(email);
resolve(res);
})
.catch((err) => {
console.logGlobal(err);
reject(err);
});
});
}
resendJuryInvitation(email) {
return Q.Promise((resolve, reject) => {
PrizeJuryFetcher
.resend(email)
.then((res) => {
resolve(res);
})
.catch((err) => {
console.logGlobal(err);
reject(err);
});
});
}
}
export default alt.createActions(PrizeJuryActions);

View File

@ -1,76 +0,0 @@
'use strict';
import { alt } from '../../../../../alt';
import Q from 'q';
import PrizeRatingFetcher from '../fetchers/prize_rating_fetcher';
class PrizeRatingActions {
constructor() {
this.generateActions(
'updatePrizeRatings',
'updatePrizeRatingAverage',
'updatePrizeRating',
'resetPrizeRatings'
);
}
fetchAverage(pieceId, round) {
return Q.Promise((resolve, reject) => {
PrizeRatingFetcher
.fetchAverage(pieceId, round)
.then((res) => {
this.actions.updatePrizeRatingAverage(res.data);
resolve(res);
})
.catch((err) => {
console.logGlobal(err);
reject(err);
});
});
}
fetchOne(pieceId, round) {
return Q.Promise((resolve, reject) => {
PrizeRatingFetcher
.fetchOne(pieceId, round)
.then((res) => {
this.actions.updatePrizeRating(res.rating.rating);
resolve(res);
})
.catch((err) => {
reject(err);
});
});
}
createRating(pieceId, rating, round) {
return Q.Promise((resolve, reject) => {
PrizeRatingFetcher
.rate(pieceId, rating, round)
.then((res) => {
this.actions.updatePrizeRating(res.rating.rating);
resolve(res);
})
.catch((err) => {
reject(err);
});
});
}
toggleShortlist(pieceId) {
return Q.Promise((resolve, reject) => {
PrizeRatingFetcher
.select(pieceId)
.then((res) => {
this.actions.updatePrizeRatings(res.data.ratings);
resolve(res);
})
.catch((err) => {
reject(err);
});
});
}
}
export default alt.createActions(PrizeRatingActions);

View File

@ -1,191 +0,0 @@
'use strict';
import React from 'react';
import { Link } from 'react-router';
import StarRating from 'react-star-rating';
import Moment from 'moment';
import PieceListActions from '../../../../../../actions/piece_list_actions';
import PieceListStore from '../../../../../../stores/piece_list_store';
import PrizeRatingActions from '../../actions/prize_rating_actions';
import InputCheckbox from '../../../../../ascribe_forms/input_checkbox';
import AccordionListItemPiece from '../../../../../ascribe_accordion_list/accordion_list_item_piece';
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
import AclProxy from '../../../../../acl_proxy';
import SubmitToPrizeButton from './../ascribe_buttons/submit_to_prize_button';
import { getLangText } from '../../../../../../utils/lang_utils';
let AccordionListItemPrize = React.createClass({
propTypes: {
content: React.PropTypes.object.isRequired,
currentUser: React.PropTypes.object.isRequired,
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.element),
React.PropTypes.element
]),
className: React.PropTypes.string
},
getInitialState() {
return PieceListStore.getState();
},
componentDidMount() {
PieceListStore.listen(this.onChange);
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
handleSubmitPrizeSuccess(response) {
const { filterBy, orderAsc, orderBy, page, pageSize, search } = this.state;
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
const notification = new GlobalNotificationModel(response.notification, 'success', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
getPrizeButtons() {
const { currentUser, content: { id, ratings } } = this.props;
if (currentUser && (currentUser.is_jury || currentUser.is_judge)) {
if (ratings && (ratings.rating || ratings.average)) {
// jury and rating available
let rating = null;
let caption = null;
if (ratings.rating) {
rating = parseInt(ratings.rating, 10);
caption = getLangText('Your rating');
} else if (ratings.average) {
rating = ratings.average;
caption = getLangText('Average of ' + ratings.num_ratings + ' rating(s)');
}
return (
<div id="list-rating" className="pull-right">
<Link to={`/pieces/${id}`}>
<StarRating
ref='rating'
name="prize-rating"
caption={caption}
step={0.5}
size='sm'
rating={rating}
ratingAmount={5} />
</Link>
</div>
);
} else {
if (currentUser.is_judge) {
return (
<div className="react-rating-caption pull-right">
{getLangText('Not rated')}
</div>
);
} else {
// jury and no rating yet
return (
<div className="react-rating-caption pull-right">
<Link to={`/pieces/${id}`}>
{getLangText('Submit your rating')}
</Link>
</div>
);
}
}
} else {
return this.getPrizeButtonsParticipant();
}
},
getPrizeButtonsParticipant() {
return (
<AclProxy
aclObject={this.props.content.acl}
aclName="acl_wallet_submit">
<SubmitToPrizeButton
className="pull-right"
piece={this.props.content}
handleSuccess={this.handleSubmitPrizeSuccess} />
</AclProxy>
);
},
handleShortlistSuccess(message) {
const notification = new GlobalNotificationModel(message, 'success', 2000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
refreshPieceData() {
const { filterBy, orderAsc, orderBy, page, pageSize, search } = this.state;
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
},
onSelectChange() {
PrizeRatingActions.toggleShortlist(this.props.content.id)
.then((res) => {
this.refreshPieceData();
this.handleShortlistSuccess(res.notification);
});
},
getPrizeBadge() {
const { currentUser } = this.props;
if (currentUser && currentUser.is_judge) {
return (
<span className="pull-right ascribe-checkbox-wrapper ascribe-checkbox-badge">
<InputCheckbox
defaultChecked={this.props.content.selected}
onChange={this.onSelectChange} />
</span>
);
} else {
return null;
}
},
render() {
const { children, className, content, currentUser } = this.props;
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
const artistName = ((currentUser.is_jury && !currentUser.is_judge) || (currentUser.is_judge && !content.selected )) ?
<span className="glyphicon glyphicon-eye-close" aria-hidden="true"/> : content.artist_name;
return (
<AccordionListItemPiece
className={className}
piece={content}
artistName={artistName}
subsubheading={
<div>
<span>{Moment(content.date_created, 'YYYY-MM-DD').year()}</span>
</div>
}
buttons={this.getPrizeButtons()}
badge={this.getPrizeBadge()}>
{children}
</AccordionListItemPiece>
);
}
});
export default AccordionListItemPrize;

View File

@ -1,55 +0,0 @@
'use strict';
import React from 'react';
import classNames from 'classnames';
import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
import PieceSubmitToPrizeForm from '../../../../../ascribe_forms/form_submit_to_prize';
import { getLangText } from '../../../../../../utils/lang_utils';
let SubmitToPrizeButton = React.createClass({
propTypes: {
className: React.PropTypes.string,
handleSuccess: React.PropTypes.func,
piece: React.PropTypes.object.isRequired
},
getSubmitButton() {
if (this.props.piece.prize) {
return (
<button
disabled
className="btn btn-default btn-xs pull-right">
{getLangText('Submitted to prize') + ' '}
<span className='ascribe-icon icon-ascribe-ok'/>
</button>
);
}
else {
return (
<button
className={classNames('btn', 'btn-default', 'btn-xs', this.props.className)}>
{getLangText('Submit to prize')}
</button>
);
}
},
render() {
return (
<ModalWrapper
trigger={this.getSubmitButton()}
handleSuccess={this.props.handleSuccess}
title={getLangText('Submit to prize')}>
<PieceSubmitToPrizeForm
piece={this.props.piece}
handleSuccess={this.props.handleSuccess}/>
</ModalWrapper>
);
}
});
export default SubmitToPrizeButton;

View File

@ -1,495 +0,0 @@
'use strict';
import React from 'react';
import { Link } from 'react-router';
import Moment from 'moment';
import StarRating from 'react-star-rating';
import ReactError from '../../../../../../mixins/react_error';
import { ResourceNotFoundError } from '../../../../../../models/errors';
import PrizeActions from '../../actions/prize_actions';
import PrizeStore from '../../stores/prize_store';
import PrizeRatingActions from '../../actions/prize_rating_actions';
import PrizeRatingStore from '../../stores/prize_rating_store';
import PieceListStore from '../../../../../../stores/piece_list_store';
import PieceListActions from '../../../../../../actions/piece_list_actions';
import PieceActions from '../../../../../../actions/piece_actions';
import PieceStore from '../../../../../../stores/piece_store';
import Piece from '../../../../../../components/ascribe_detail/piece';
import Note from '../../../../../../components/ascribe_detail/note';
import AscribeSpinner from '../../../../../ascribe_spinner';
import Form from '../../../../../../components/ascribe_forms/form';
import Property from '../../../../../../components/ascribe_forms/property';
import InputTextAreaToggable from '../../../../../../components/ascribe_forms/input_textarea_toggable';
import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph';
import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader';
import InputCheckbox from '../../../../../ascribe_forms/input_checkbox';
import ListRequestActions from '../../../../../ascribe_forms/list_form_request_actions';
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
import DetailProperty from '../../../../../ascribe_detail/detail_property';
import ApiUrls from '../../../../../../constants/api_urls';
import { mergeOptions } from '../../../../../../utils/general_utils';
import { getLangText } from '../../../../../../utils/lang_utils';
import { setDocumentTitle } from '../../../../../../utils/dom_utils';
/**
* This is the component that implements resource/data specific functionality
*/
let PrizePieceContainer = React.createClass({
propTypes: {
selectedPrizeActionButton: React.PropTypes.func,
// Provided from PrizeApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object,
params: React.PropTypes.object
},
mixins: [ReactError],
getInitialState() {
return PieceStore.getInitialState();
},
componentDidMount() {
PieceStore.listen(this.onChange);
this.loadPiece();
},
// This is done to update the container when the user clicks on the prev or next
// button to update the URL parameter (and therefore to switch pieces) or
// when the user clicks on a notification while being in another piece view
componentWillReceiveProps(nextProps) {
if (this.props.params.pieceId !== nextProps.params.pieceId) {
PieceActions.flushPiece();
this.loadPiece(nextProps.params.pieceId);
}
},
componentDidUpdate() {
const { pieceMeta: { err: pieceErr } } = this.state;
if (pieceErr && pieceErr.status === 404) {
this.throws(new ResourceNotFoundError(getLangText("Oops, the piece you're looking for doesn't exist.")));
}
},
componentWillUnmount() {
PieceStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
getActions() {
const { currentUser } = this.props;
const { piece } = this.state;
if (piece.notifications && piece.notifications.length > 0) {
return (
<ListRequestActions
pieceOrEditions={piece}
currentUser={currentUser}
handleSuccess={this.loadPiece}
notifications={piece.notifications} />);
}
},
loadPiece(pieceId = this.props.params.pieceId) {
PieceActions.fetchPiece(pieceId);
},
render() {
const { currentUser, selectedPrizeActionButton } = this.props;
const { piece } = this.state;
if (piece.id) {
/*
This really needs a refactor!
- Tim
*/
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
let artistName;
if ((currentUser.is_jury && !currentUser.is_judge) || (currentUser.is_judge && !piece.selected )) {
artistName = <span className="glyphicon glyphicon-eye-close" aria-hidden="true" />;
setDocumentTitle(piece.title);
} else {
artistName = piece.artist_name;
setDocumentTitle(`${artistName}, ${piece.title}`);
}
// Only show the artist email if you are a judge and the piece is shortlisted
const artistEmail = currentUser.is_judge && piece.selected ? (
<DetailProperty
label={getLangText('REGISTREE')}
value={piece.user_registered} />
) : null;
return (
<Piece
piece={piece}
currentUser={currentUser}
header={
<div className="ascribe-detail-header">
<NavigationHeader
piece={piece}
currentUser={currentUser} />
<h1 className="ascribe-detail-title">{piece.title}</h1>
<DetailProperty label={getLangText('BY')} value={artistName} />
<DetailProperty label={getLangText('DATE')} value={Moment(piece.date_created, 'YYYY-MM-DD').year()} />
{artistEmail}
{this.getActions()}
<hr />
</div>
}
subheader={
<PrizePieceRatings
loadPiece={this.loadPiece}
piece={piece}
currentUser={currentUser}
selectedPrizeActionButton={selectedPrizeActionButton} />
}>
<PrizePieceDetails piece={piece} />
</Piece>
);
} else {
return (
<div className="fullpage-spinner">
<AscribeSpinner color='dark-blue' size='lg' />
</div>
);
}
}
});
let NavigationHeader = React.createClass({
propTypes: {
currentUser: React.PropTypes.object.isRequired,
piece: React.PropTypes.object.isRequired
},
render() {
const { currentUser, piece } = this.props;
if (currentUser.email && currentUser.is_judge && currentUser.is_jury && !currentUser.is_admin && piece.navigation) {
const nav = piece.navigation;
return (
<div style={{marginBottom: '1em'}}>
<div className="row no-margin">
<Link className="disable-select" to={`/pieces/${ nav.prev_index || piece.id }`}>
<span className="glyphicon glyphicon-chevron-left pull-left link-ascribe" aria-hidden="true">
{getLangText('Previous')}
</span>
</Link>
<Link className="disable-select" to={`/pieces/${ nav.next_index || piece.id }`}>
<span className="pull-right link-ascribe">
{getLangText('Next')}
<span className="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
</span>
</Link>
</div>
<hr/>
</div>
);
} else {
return null;
}
}
});
let PrizePieceRatings = React.createClass({
propTypes: {
currentUser: React.PropTypes.object.isRequired,
loadPiece: React.PropTypes.func.isRequired,
piece: React.PropTypes.object.isRequired,
selectedPrizeActionButton: React.PropTypes.func
},
getInitialState() {
return mergeOptions(
PieceListStore.getState(),
PrizeStore.getState(),
PrizeRatingStore.getInitialState()
);
},
componentDidMount() {
PrizeRatingStore.listen(this.onChange);
PrizeStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
PrizeActions.fetchPrize();
this.fetchRatingsIfAuthorized();
},
componentWillReceiveProps(nextProps) {
if (nextProps.currentUser.email !== this.props.currentUser.email) {
this.fetchRatingsIfAuthorized();
}
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
PrizeStore.unlisten(this.onChange);
PrizeRatingStore.unlisten(this.onChange);
},
// The StarRating component does not have a property that lets us set
// a default value at initialization. Since the ratingCache would otherwise on
// every mouseover be overridden, we need to set it ourselves initially to deal
// with the problem.
onChange(state) {
if (state.prize && state.prize.active_round != this.state.prize.active_round) {
this.fetchRatingsIfAuthorized(state);
}
this.setState(state);
if (this.refs.rating) {
this.refs.rating.state.ratingCache = {
pos: this.refs.rating.state.pos,
rating: this.state.currentRating,
caption: this.refs.rating.props.caption,
name: this.refs.rating.props.name
};
}
},
fetchRatingsIfAuthorized(state = this.state) {
const { currentUser: {
is_admin: isAdmin,
is_judge: isJudge,
is_jury: isJury
},
piece: { id: pieceId } } = this.props;
if (state.prize && 'active_round' in state.prize && (isAdmin || isJudge || isJury)) {
PrizeRatingActions.fetchOne(pieceId, state.prize.active_round);
PrizeRatingActions.fetchAverage(pieceId, state.prize.active_round);
}
},
onRatingClick(event, args) {
event.preventDefault();
PrizeRatingActions
.createRating(this.props.piece.id, args.rating, this.state.prize.active_round)
.then(this.refreshPieceData);
},
getSelectedActionButton() {
const { currentUser, piece, selectedPrizeActionButton: SelectedPrizeActionButton } = this.props;
if (piece.selected && SelectedPrizeActionButton) {
return (
<span className="pull-right">
<SelectedPrizeActionButton
piece={piece}
currentUser={currentUser} />
</span>
);
}
},
refreshPieceData() {
const { filterBy, orderAsc, orderBy, page, pageSize, search } = this.state;
this.props.loadPiece();
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
},
onSelectChange() {
PrizeRatingActions
.toggleShortlist(this.props.piece.id)
.then((res) => {
this.refreshPieceData();
if (res && res.notification) {
const notification = new GlobalNotificationModel(res.notification, 'success', 2000);
GlobalNotificationActions.appendGlobalNotification(notification);
}
});
},
render() {
if (this.props.piece.id && this.props.currentUser.is_judge && this.state.average) {
// Judge sees shortlisting, average and per-jury notes
return (
<div>
<CollapsibleParagraph
title={getLangText('Shortlisting')}
defaultExpanded={true}>
<div className="row no-margin">
<span className="ascribe-checkbox-wrapper" style={{marginLeft: '1.5em'}}>
<InputCheckbox
defaultChecked={this.props.piece.selected}
onChange={this.onSelectChange}>
<span>
{getLangText('Select for the prize')}
</span>
</InputCheckbox>
</span>
{this.getSelectedActionButton()}
</div>
<hr />
</CollapsibleParagraph>
<CollapsibleParagraph
title={getLangText('Average Rating')}
defaultExpanded={true}>
<div id="list-rating" style={{marginLeft: '1.5em', marginBottom: '1em'}}>
<StarRating
ref='average-rating'
name="average-rating"
caption=""
size='md'
step={0.5}
rating={this.state.average}
ratingAmount={5} />
</div>
<hr />
{this.state.ratings.map((item, i) => {
let note = item.note ? (
<div className="rating-note">
note: {item.note}
</div>
) : null;
return (
<div
key={item.user}
className="rating-list">
<div
id="list-rating"
className="row no-margin">
<span className="pull-right">
<StarRating
ref={'rating' + i}
name={'rating' + i}
caption=""
size='sm'
step={0.5}
rating={item.rating}
ratingAmount={5} />
</span>
<span> {item.user}</span>
{note}
</div>
</div>
);
})}
<hr />
</CollapsibleParagraph>
</div>);
} else if (this.props.currentUser.is_jury) {
// Jury can set rating and note
return (
<CollapsibleParagraph
title={getLangText('Rating')}
defaultExpanded={true}>
<div style={{marginLeft: '1.5em', marginBottom: '1em'}}>
<StarRating
ref='rating'
name="prize-rating"
caption=""
step={1}
size='md'
rating={this.state.currentRating}
onRatingClick={this.onRatingClick}
ratingAmount={5} />
</div>
<Note
id={() => ({ 'piece_id': this.props.piece.id })}
label={getLangText('Jury note')}
defaultValue={this.props.piece.note_from_user || null}
placeholder={getLangText('Enter your comments ...')}
editable={true}
successMessage={getLangText('Jury note saved')}
url={ApiUrls.notes}
currentUser={this.props.currentUser} />
</CollapsibleParagraph>);
} else {
return null;
}
}
});
let PrizePieceDetails = React.createClass({
propTypes: {
piece: React.PropTypes.object.isRequired
},
render() {
const { piece } = this.props;
if (piece.prize && piece.prize.name && Object.keys(piece.extra_data).length) {
return (
<CollapsibleParagraph
title={getLangText('Prize Details')}
defaultExpanded={true}>
<Form>
{Object
.keys(piece.extra_data)
.sort()
.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 (
<Property
key={label}
name={data}
label={label}
editable={false}
overrideForm={true}>
<InputTextAreaToggable
rows={1}
defaultValue={value} />
</Property>
);
})
}
<FurtherDetailsFileuploader
submitFile={() => {}}
setIsUploadReady={() => {}}
isReadyForFormSubmission={() => {}}
editable={false}
overrideForm={true}
pieceId={piece.id}
otherData={piece.other_data}
multiple={true} />
</Form>
</CollapsibleParagraph>
);
} else {
return null;
}
}
});
export default PrizePieceContainer;

View File

@ -1,20 +0,0 @@
'use strict';
import React from 'react';
import constants from '../../../../../constants/application_constants';
let Hero = React.createClass({
render() {
return (
<div className="hero">
<img
className="logo" src={constants.whitelabel.logo}
alt="Sluice Art Prize"
height="200px"/>
</div>
);
}
});
export default Hero;

View File

@ -1,111 +0,0 @@
'use strict';
import React from 'react';
import Button from 'react-bootstrap/lib/Button';
import ButtonGroup from 'react-bootstrap/lib/ButtonGroup';
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
import PrizeActions from '../actions/prize_actions';
import PrizeStore from '../stores/prize_store';
import { getLangText } from '../../../../../utils/lang_utils';
let Landing = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object
},
getInitialState() {
return PrizeStore.getState();
},
componentDidMount() {
PrizeStore.listen(this.onChange);
PrizeActions.fetchPrize();
},
componentWillUnmount() {
PrizeStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
getButtons() {
if (this.state.prize && this.state.prize.active) {
return (
<ButtonGroup className="enter" bsSize="large" vertical>
<LinkContainer to="/signup">
<Button>
{getLangText('Sign up to submit')}
</Button>
</LinkContainer>
<p>
{getLangText('or, already an ascribe user?')}
</p>
<LinkContainer to="/login">
<Button>
{getLangText('Log in to submit')}
</Button>
</LinkContainer>
</ButtonGroup>
);
} else {
return (
<ButtonGroup className="enter" bsSize="large" vertical>
<a className="btn btn-default" href="https://www.ascribe.io/app/signup">
{getLangText('Sign up to ascribe')}
</a>
<p>
{getLangText('or, already an ascribe user?')}
</p>
<LinkContainer to="/login">
<Button>
{getLangText('Log in')}
</Button>
</LinkContainer>
</ButtonGroup>
);
}
},
getTitle() {
const { prize } = this.state;
return (
<p>
{getLangText(prize && prize.active ? 'This is the submission page for Sluice_screens ↄc Prize 2015.'
: 'Submissions for Sluice_screens ↄc Prize 2015 are now closed.')}
</p>
);
},
render() {
return (
<div className="container">
<div className="row">
<div className="col-xs-12 wp-landing-wrapper">
<h1>
{getLangText('Sluice_screens ↄc Prize 2015')}
</h1>
{this.getTitle()}
{this.getButtons()}
</div>
</div>
</div>
);
}
});
export default Landing;

View File

@ -1,45 +0,0 @@
'use strict';
import React from 'react';
import { Link } from 'react-router';
import LoginForm from '../../../../ascribe_forms/form_login';
import { getLangText } from '../../../../../utils/lang_utils';
import { setDocumentTitle } from '../../../../../utils/dom_utils';
let LoginContainer = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object
},
render() {
setDocumentTitle(getLangText('Log in'));
return (
<div className="ascribe-login-wrapper">
<LoginForm
headerMessage={getLangText('Log in with ascribe')}
location={this.props.location} />
<div className="ascribe-login-text">
{getLangText('I\'m not a user') + ' '}
<Link to="/signup">{getLangText('Sign up...')}</Link>
<br />
{getLangText('I forgot my password') + ' '}
<Link to="/password_reset">{getLangText('Rescue me...')}</Link>
</div>
</div>
);
}
});
export default LoginContainer;

View File

@ -1,94 +0,0 @@
'use strict';
import React from 'react';
import Button from 'react-bootstrap/lib/Button';
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
import PrizeActions from '../actions/prize_actions';
import PrizeStore from '../stores/prize_store';
import AccordionListItemPrize from './ascribe_accordion_list/accordion_list_item_prize';
import PieceList from '../../../../piece_list';
import { mergeOptions } from '../../../../../utils/general_utils';
import { getLangText } from '../../../../../utils/lang_utils';
import { setDocumentTitle } from '../../../../../utils/dom_utils';
let PrizePieceList = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object
},
getInitialState() {
return PrizeStore.getState();
},
componentDidMount() {
PrizeStore.listen(this.onChange);
PrizeActions.fetchPrize();
},
componentWillUnmount() {
PrizeStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
getButtonSubmit() {
const { currentUser } = this.props;
const { prize } = this.state;
if (prize && prize.active && !currentUser.is_jury && !currentUser.is_admin && !currentUser.is_judge) {
return (
<LinkContainer to="/register_piece">
<Button>
{getLangText('Submit to prize')}
</Button>
</LinkContainer>
);
} else {
return null;
}
},
shouldRedirect(pieceCount) {
const { currentUser } = this.props;
return !currentUser.is_admin && !currentUser.is_jury && !currentUser.is_judge && !pieceCount;
},
render() {
const { currentUser, location } = this.props;
setDocumentTitle(getLangText('Collection'));
let orderParams = ['artist_name', 'title'];
if (currentUser.is_jury) {
orderParams = ['rating', 'title'];
}
if (currentUser.is_judge) {
orderParams = ['rating', 'title', 'selected'];
}
return (
<PieceList
ref="list"
{...this.props}
accordionListItemType={AccordionListItemPrize}
customSubmitButton={this.getButtonSubmit()}
filterParams={[]}
orderParams={orderParams}
orderBy={currentUser.is_jury ? 'rating' : null}
shouldRedirect={this.shouldRedirect} />
);
}
});
export default PrizePieceList;

View File

@ -1,102 +0,0 @@
'use strict';
import React from 'react';
import PrizeActions from '../actions/prize_actions';
import PrizeStore from '../stores/prize_store';
import RegisterPiece from '../../../../register_piece';
import Property from '../../../../ascribe_forms/property';
import InputTextAreaToggable from '../../../../ascribe_forms/input_textarea_toggable';
import InputCheckbox from '../../../../ascribe_forms/input_checkbox';
import { getLangText } from '../../../../../utils/lang_utils';
import { setDocumentTitle } from '../../../../../utils/dom_utils';
let PrizeRegisterPiece = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object
},
getInitialState() {
return PrizeStore.getState();
},
componentDidMount() {
PrizeStore.listen(this.onChange);
PrizeActions.fetchPrize();
},
componentWillUnmount() {
PrizeStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
render() {
const { prize } = this.state;
setDocumentTitle(getLangText('Submit to the prize'));
if (prize && prize.active) {
return (
<RegisterPiece
{...this.props}
enableLocalHashing={false}
headerMessage={''}
submitMessage={getLangText('Submit')}>
<Property
name='artist_statement'
label={getLangText('Artist statement')}
editable={true}
overrideForm={true}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter your statement')}
required />
</Property>
<Property
name='work_description'
label={getLangText('Work description')}
editable={true}
overrideForm={true}>
<InputTextAreaToggable
rows={1}
placeholder={getLangText('Enter the description for your work')}
required />
</Property>
<Property
name="terms"
className="ascribe-property-collapsible-toggle">
<InputCheckbox>
<span>
{' ' + getLangText('I agree to the Terms of Service the art price') + ' '}
(<a href="https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/sluice/terms.pdf" target="_blank" style={{fontSize: '0.9em', color: 'rgba(0,0,0,0.7)'}}>
{getLangText('read')}
</a>)
</span>
</InputCheckbox>
</Property>
</RegisterPiece>
);
} else {
return (
<div className='row'>
<div style={{textAlign: 'center'}}>
{getLangText('The prize is no longer active')}
</div>
</div>
);
}
}
});
export default PrizeRegisterPiece;

View File

@ -1,302 +0,0 @@
'use strict';
import React from 'react';
import PrizeActions from '../actions/prize_actions';
import PrizeStore from '../stores/prize_store';
import PrizeJuryActions from '../actions/prize_jury_actions';
import PrizeJuryStore from '../stores/prize_jury_store';
import SettingsContainer from '../../../../ascribe_settings/settings_container';
import CollapsibleParagraph from '../../../../ascribe_collapsible/collapsible_paragraph';
import Form from '../../../../ascribe_forms/form';
import Property from '../../../../ascribe_forms/property';
import ActionPanel from '../../../../ascribe_panel/action_panel';
import GlobalNotificationModel from '../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
import AscribeSpinner from '../../../../ascribe_spinner';
import ApiUrls from '../../../../../constants/api_urls';
import { getLangText } from '../../../../../utils/lang_utils';
import { setDocumentTitle } from '../../../../../utils/dom_utils';
let Settings = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object
},
render() {
setDocumentTitle(getLangText('Account settings'));
return (
<SettingsContainer {...this.props}>
{this.props.currentUser.is_admin ? <PrizeSettings /> : null}
</SettingsContainer>
);
}
});
let PrizeSettings = React.createClass({
getInitialState() {
return PrizeStore.getState();
},
componentDidMount() {
PrizeStore.listen(this.onChange);
PrizeActions.fetchPrize();
},
componentWillUnmount() {
PrizeStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
render() {
return (
<CollapsibleParagraph
title={getLangText('Prize Settings for ') + this.state.prize.name}
defaultExpanded={true}>
<Form >
<Property
name='prize_name'
label={getLangText('Prize name')}
editable={false}>
<pre className="ascribe-pre">{this.state.prize.name}</pre>
</Property>
<Property
name='prize_rounds'
label={getLangText('Active round/Number of rounds')}
editable={false}>
<pre className="ascribe-pre">{this.state.prize.active_round}/{this.state.prize.rounds}</pre>
</Property>
<Property
name='num_submissions'
label={getLangText('Allowed number of submissions per user')}
editable={false}>
<pre className="ascribe-pre">{this.state.prize.num_submissions}</pre>
</Property>
<hr />
</Form>
<PrizeJurySettings
prize={this.state.prize}/>
</CollapsibleParagraph>
);
}
});
let PrizeJurySettings = React.createClass({
propTypes: {
prize: React.PropTypes.object
},
getInitialState() {
return PrizeJuryStore.getState();
},
componentDidMount() {
PrizeJuryStore.listen(this.onChange);
PrizeJuryActions.fetchJury();
},
componentWillUnmount() {
PrizeJuryStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
handleCreateSuccess(response) {
PrizeJuryActions.fetchJury();
this.displayNotification(response);
this.refs.form.refs.email.refs.input.getDOMNode().value = null;
},
handleActivate(event) {
let email = event.target.getAttribute('data-id');
PrizeJuryActions
.activateJury(email)
.then((response) => {
PrizeJuryActions.fetchJury();
this.displayNotification(response);
});
},
handleRevoke(event) {
let email = event.target.getAttribute('data-id');
PrizeJuryActions
.revokeJury(email)
.then(this.displayNotification);
},
handleResend(event) {
let email = event.target.getAttribute('data-id');
PrizeJuryActions
.resendJuryInvitation(email)
.then(this.displayNotification);
},
displayNotification(response) {
let notification = new GlobalNotificationModel(response.notification, 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
getMembersPending() {
return this.state.membersPending.map(function(member, i) {
return (
<ActionPanel
name={member.email}
key={i}
content={
<div>
<div className='ascribe-panel-title'>
{member.email}
</div>
<div className="ascribe-panel-subtitle">
{member.status}
</div>
</div>
}
buttons={
<div className="pull-right">
<button
className="btn btn-default btn-sm margin-left-2px"
onClick={this.handleResend}
data-id={member.email}>
{getLangText('RESEND')}
</button>
<button
className="btn btn-warning btn-sm margin-left-2px"
onClick={this.handleRevoke}
data-id={member.email}>
{getLangText('REVOKE')}
</button>
</div>
}/>
);
}, this);
},
getMembersActive() {
return this.state.membersActive.map(function(member, i) {
return (
<ActionPanel
name={member.email}
key={i}
content={
<div>
<div className='ascribe-panel-title'>
{member.email}
</div>
<div className="ascribe-panel-subtitle">
{member.status}
</div>
</div>
}
buttons={
<button
className="btn btn-warning btn-sm"
onClick={this.handleRevoke}
data-id={member.email}>
{getLangText('REVOKE')}
</button>
}/>
);
}, this);
},
getMembersInactive() {
return this.state.membersInactive.map(function(member, i) {
return (
<ActionPanel
name={member.email}
key={i}
content={
<div>
<div className='ascribe-panel-title'>
{member.email}
</div>
<div className="ascribe-panel-subtitle">
{member.status}
</div>
</div>
}
buttons={
<button
className="btn btn-default btn-sm"
onClick={this.handleActivate}
data-id={member.email}>
{getLangText('ACTIVATE')}
</button>
}/>
);
}, this);
},
getMembers() {
let content = <AscribeSpinner color='dark-blue' size='md' />;
if (this.state.members.length > -1) {
content = (
<div>
<CollapsibleParagraph
title={getLangText('Active Jury Members')}
defaultExpanded={true}>
{this.getMembersActive()}
</CollapsibleParagraph>
<CollapsibleParagraph
title={getLangText('Pending Jury Invitations')}
defaultExpanded={true}>
{this.getMembersPending()}
</CollapsibleParagraph>
<CollapsibleParagraph
title={getLangText('Deactivated Jury Members')}
defaultExpanded={false}>
{this.getMembersInactive()}
</CollapsibleParagraph>
</div>);
}
return content;
},
render() {
return (
<div>
<Form
url={ApiUrls.jurys}
handleSuccess={this.handleCreateSuccess}
ref='form'
buttonSubmitText={getLangText('INVITE')}>
<div className="ascribe-form-header">
<h4 style={{margin: '30px 0px 10px 10px'}}>
{getLangText('Jury Members')}
</h4>
</div>
<Property
name='email'
label={getLangText('New jury member')}>
<input
type="email"
placeholder={getLangText('Enter an email to invite a jury member')}
required/>
</Property>
<hr />
</Form>
{this.getMembers()}
</div>
);
}
});
export default Settings;

View File

@ -1,61 +0,0 @@
'use strict';
import React from 'react';
import SignupForm from '../../../../ascribe_forms/form_signup';
import { getLangText } from '../../../../../utils/lang_utils';
import { setDocumentTitle } from '../../../../../utils/dom_utils';
let SignupContainer = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object
},
getInitialState() {
return {
submitted: false,
message: null
};
},
handleSuccess(message) {
this.setState({
submitted: true,
message: message
});
},
render() {
const { location } = this.props;
const { message, submitted } = this.state;
setDocumentTitle(getLangText('Sign up'));
if (submitted) {
return (
<div className="ascribe-login-wrapper">
<div className="ascribe-login-text ascribe-login-header">
{message}
</div>
</div>
);
} else {
return (
<div className="ascribe-login-wrapper">
<SignupForm
headerMessage={getLangText('Create account for submission')}
submitMessage={getLangText('Sign up')}
handleSuccess={this.handleSuccess}
location={location} />
</div>
);
}
}
});
export default SignupContainer;

View File

@ -1,12 +0,0 @@
'use strict';
import requests from '../../../../../utils/requests';
let PrizeFetcher = {
fetch() {
return requests.get('prize');
}
};
export default PrizeFetcher;

View File

@ -1,24 +0,0 @@
'use strict';
import requests from '../../../../../utils/requests';
let PrizeJuryFetcher = {
fetch() {
return requests.get('jurys');
},
activate(email) {
return requests.post('jury_activate', {'email': email});
},
delete(email) {
return requests.delete('jury', {'email': email});
},
resend(email) {
return requests.post('jury_resend', {'email': email});
}
};
export default PrizeJuryFetcher;

View File

@ -1,49 +0,0 @@
'use strict';
import requests from '../../../../../utils/requests';
let PrizeRatingFetcher = {
fetchAverage(pieceId, round) {
const params = {
'piece_id': pieceId
};
if (typeof round === 'number') {
params['prize_round'] = round;
}
return requests.get('rating_average', params);
},
fetchOne(pieceId, round) {
const params = {
'piece_id': pieceId
};
if (typeof round === 'number') {
params['prize_round'] = round;
}
return requests.get('rating', params);
},
rate(pieceId, rating, round) {
const body = {
'piece_id': pieceId,
'note': rating
};
if (typeof round === 'number') {
body['prize_round'] = round;
}
return requests.post('ratings', { body });
},
select(pieceId) {
return requests.post('select_piece', {'piece_id': pieceId});
}
};
export default PrizeRatingFetcher;

View File

@ -1,61 +0,0 @@
'use strict';
import React from 'react';
import classNames from 'classnames';
import Hero from './components/prize_hero';
import AppBase from '../../../app_base';
import AppRouteWrapper from '../../../app_route_wrapper';
import Header from '../../../header';
import { getSubdomain } from '../../../../utils/general_utils';
let PrizeApp = React.createClass({
propTypes: {
activeRoute: React.PropTypes.object.isRequired,
children: React.PropTypes.element.isRequired,
history: React.PropTypes.object.isRequired,
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
// Provided from AppBase
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object
},
render() {
const { activeRoute, children, currentUser, history, routes, whitelabel } = this.props;
const subdomain = getSubdomain();
const path = activeRoute && activeRoute.path;
const Footer = activeRoute && activeRoute.footer;
let header = null;
// if the path of the current activeRoute is not defined, then this is the IndexRoute
if (!path || history.isActive('/login') || history.isActive('/signup')) {
header = (<Hero />);
} else {
header = (
<Header
currentUser={currentUser}
routes={routes}
whitelabel={whitelabel} />
);
}
return (
<div className={classNames('ascribe-app', 'ascribe-prize-app', `route--${(path ? path.split('/')[0] : 'landing')}`)}>
{header}
<AppRouteWrapper
currentUser={currentUser}
whitelabel={whitelabel}>
{/* Routes are injected here */}
{children}
</AppRouteWrapper>
{Footer ? <Footer /> : null}
</div>
);
}
});
export default AppBase(PrizeApp);

View File

@ -1,35 +0,0 @@
'use strict';
import { alt } from '../../../../../alt';
import PrizeJuryActions from '../actions/prize_jury_actions';
class PrizeJuryStore {
constructor() {
this.members = [];
this.membersActive = [];
this.membersPending = [];
this.membersInactive = [];
this.bindActions(PrizeJuryActions);
}
onUpdatePrizeJury( members ) {
this.members = members;
this.splitJuryMembers();
}
onRemovePrizeJury( email ) {
let memberInactive = this.members.filter((item)=> item.email === email );
this.membersActive = this.membersActive.filter((item)=> item.email !== email );
this.membersPending = this.membersPending.filter((item)=> item.email !== email );
this.membersInactive = this.membersInactive.concat(memberInactive);
}
splitJuryMembers(){
this.membersActive = this.members.filter((item)=> item.status === 'Invitation accepted' );
this.membersPending = this.members.filter((item)=> item.status === 'Invitation pending' );
this.membersInactive = this.members.filter((item)=> item.status === 'Deactivated' );
}
}
export default alt.createStore(PrizeJuryStore, 'PrizeJuryStore');

View File

@ -1,47 +0,0 @@
'use strict';
import { alt } from '../../../../../alt';
import PrizeRatingActions from '../actions/prize_rating_actions';
class PrizeRatingStore {
constructor() {
this.getInitialState();
this.bindActions(PrizeRatingActions);
this.exportPublicMethods({
getInitialState: this.getInitialState.bind(this)
});
}
getInitialState() {
this.ratings = [];
this.currentRating = null;
this.average = null;
return {
ratings: this.ratings,
currentRating: this.currentRating,
average: this.average
};
}
onUpdatePrizeRatings(ratings) {
this.ratings = ratings;
}
onUpdatePrizeRating(rating) {
this.currentRating = parseInt(rating, 10);
}
onUpdatePrizeRatingAverage(data) {
this.average = data.average;
this.ratings = data.ratings;
}
onResetPrizeRatings() {
this.getInitialState();
}
}
export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore');

View File

@ -1,18 +0,0 @@
'use strict';
import { alt } from '../../../../../alt';
import PrizeActions from '../actions/prize_actions';
class PrizeStore {
constructor() {
this.prize = {};
this.bindActions(PrizeActions);
}
onUpdatePrize({ prize }) {
this.prize = prize;
}
}
export default alt.createStore(PrizeStore, 'PrizeStore');

View File

@ -1,71 +0,0 @@
'use strict';
import React from 'react';
import Moment from 'moment';
import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
import LoanForm from '../../../../../ascribe_forms/form_loan';
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
import ApiUrls from '../../../../../../constants/api_urls';
import { getLangText } from '../../../../../../utils/lang_utils';
const SluiceSelectedPrizeActionButton = React.createClass({
propTypes: {
currentUser: React.PropTypes.object.isRequired,
piece: React.PropTypes.object.isRequired,
startLoanDate: React.PropTypes.object,
endLoanDate: React.PropTypes.object,
className: React.PropTypes.string,
handleSuccess: React.PropTypes.func
},
handleSuccess(res) {
const notification = new GlobalNotificationModel(res && res.notification || getLangText('You have successfully requested the loan, pending their confirmation.'), 'success', 4000);
GlobalNotificationActions.appendGlobalNotification(notification);
if (typeof this.props.handleSuccess === 'function') {
this.props.handleSuccess(res);
}
},
render() {
const { currentUser, piece } = this.props;
// Can't use default props since those are only created once
const startLoanDate = this.props.startLoanDate || new Moment();
const endLoanDate = this.props.endLoanDate || new Moment().add(6, 'months');
return (
<ModalWrapper
trigger={
<button className='btn btn-default btn-sm'>
{getLangText('SEND LOAN REQUEST')}
</button>
}
handleSuccess={this.handleSuccess}
title={getLangText('REQUEST LOAN')}>
<LoanForm
loanHeading={null}
message={getLangText('Congratulations,\nYou have been selected for the prize.\n' +
'Please accept the loan request to proceed.')}
id={{ piece_id: piece.id }}
url={ApiUrls.ownership_loans_pieces_request}
email={currentUser.email}
gallery={piece.prize.name}
startDate={startLoanDate}
endDate={endLoanDate}
showPersonalMessage={true}
showPassword={false} />
</ModalWrapper>
);
}
});
export default SluiceSelectedPrizeActionButton;

View File

@ -1,29 +0,0 @@
'use strict';
import React from 'react';
import SluiceSelectedPrizeActionButton from '../sluice_buttons/sluice_selected_prize_action_button';
import PrizePieceContainer from '../../../simple_prize/components/ascribe_detail/prize_piece_container';
const SluicePieceContainer = React.createClass({
propTypes: {
// Provided from PrizeApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,
// Provided from router
location: React.PropTypes.object,
params: React.PropTypes.object
},
render() {
return (
<PrizePieceContainer
{...this.props}
selectedPrizeActionButton={SluiceSelectedPrizeActionButton} />
);
}
});
export default SluicePieceContainer;

View File

@ -8,7 +8,7 @@ import MarketPieceList from '../market/market_piece_list';
let Vivi23PieceList = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,

View File

@ -11,7 +11,7 @@ import { setDocumentTitle } from '../../../../../utils/dom_utils';
let ArtcityLanding = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object.isRequired
},

View File

@ -31,7 +31,7 @@ import { mergeOptions } from '../../../../../../utils/general_utils';
let CylandPieceContainer = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object,

View File

@ -14,7 +14,7 @@ import { setDocumentTitle } from '../../../../../utils/dom_utils';
let CylandLanding = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -10,7 +10,7 @@ import { setDocumentTitle } from '../../../../../utils/dom_utils';
let CylandPieceList = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -36,7 +36,7 @@ import { getAclFormMessage } from '../../../../../utils/form_utils';
let CylandRegisterPiece = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -25,7 +25,7 @@ import { setDocumentTitle } from '../../../../../utils/dom_utils';
let IkonotvContractNotifications = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -32,7 +32,7 @@ import { mergeOptions } from '../../../../../../utils/general_utils';
let IkonotvPieceContainer = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object,

View File

@ -12,7 +12,7 @@ import { setDocumentTitle } from '../../../../../utils/dom_utils';
let IkonotvLanding = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object,

View File

@ -14,7 +14,7 @@ import { getLangText } from '../../../../../utils/lang_utils';
let IkonotvPieceList = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -34,7 +34,7 @@ let IkonotvRegisterPiece = React.createClass({
propTypes: {
handleSuccess: React.PropTypes.func,
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -11,7 +11,7 @@ import { setDocumentTitle } from '../../../../../utils/dom_utils';
let LumenusLanding = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -14,7 +14,7 @@ let MarketPieceList = React.createClass({
propTypes: {
customThumbnailPlaceholder: React.PropTypes.func,
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object.isRequired,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -25,7 +25,7 @@ import { mergeOptions } from '../../../../../utils/general_utils';
let MarketRegisterPiece = React.createClass({
propTypes: {
// Provided from PrizeApp
// Provided from WalletApp
currentUser: React.PropTypes.object,
whitelabel: React.PropTypes.object.isRequired,

View File

@ -2,7 +2,6 @@
import AppConstants from './application_constants';
import getPrizeApiUrls from '../components/whitelabel/prize/constants/prize_api_urls';
import getWalletApiUrls from '../components/whitelabel/wallet/constants/wallet_api_urls';
import { update } from '../utils/general_utils';
@ -81,14 +80,9 @@ let ApiUrls = {
export function updateApiUrls(type, subdomain) {
let newUrls = {};
if (type === 'prize') {
newUrls = getPrizeApiUrls(subdomain);
} else if(type === 'wallet') {
newUrls = getWalletApiUrls(subdomain);
if (type === 'wallet') {
update(getWalletApiUrls(subdomain));
}
update(ApiUrls, newUrls);
}
export default ApiUrls;

View File

@ -27,12 +27,6 @@ const constants = {
'type': 'wallet',
'ga': 'UA-60614729-4'
},
{
'subdomain': 'sluice',
'name': 'Sluice Art Fair',
'type': 'prize',
'ga': 'UA-60614729-5'
},
{
'subdomain': 'cyland',
'name': 'Cyland media art lab',
@ -72,11 +66,6 @@ const constants = {
'subdomain': 'liquidgallery',
'name': 'Liquid Gallery',
'type': 'wallet'
},
{
'subdomain': 'portfolioreview',
'name': 'Portfolio Review',
'type': 'prize'
}
],
'defaultDomain': {

View File

@ -3,7 +3,6 @@
import React from 'react';
import { Route } from 'react-router';
import getPrizeRoutes from './components/whitelabel/prize/prize_routes';
import getWalletRoutes from './components/whitelabel/wallet/wallet_routes';
import AscribeApp from './components/ascribe_app';
@ -82,9 +81,7 @@ const COMMON_ROUTES = (
function getRoutes(type, subdomain) {
if (type === 'prize') {
return getPrizeRoutes(COMMON_ROUTES, subdomain);
} else if(type === 'wallet') {
if (type === 'wallet') {
return getWalletRoutes(COMMON_ROUTES, subdomain);
} else {
return COMMON_ROUTES;