mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
Merge pull request #87 from ascribe/AD-1362-implement-portfolio-review-judging-flow-stage-2
AD-1362 Implement portfolio review judging flow stage 2
This commit is contained in:
commit
f819e1313e
@ -12,7 +12,10 @@ import { getLangText } from '../../utils/lang_utils';
|
|||||||
let AccordionListItemPiece = React.createClass({
|
let AccordionListItemPiece = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
artistName: React.PropTypes.string,
|
artistName: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.string,
|
||||||
|
React.PropTypes.element
|
||||||
|
]),
|
||||||
piece: React.PropTypes.object.isRequired,
|
piece: React.PropTypes.object.isRequired,
|
||||||
children: React.PropTypes.oneOfType([
|
children: React.PropTypes.oneOfType([
|
||||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
|
@ -46,7 +46,13 @@ let ModalWrapper = React.createClass({
|
|||||||
renderChildren() {
|
renderChildren() {
|
||||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||||
return ReactAddons.addons.cloneWithProps(child, {
|
return ReactAddons.addons.cloneWithProps(child, {
|
||||||
handleSuccess: this.handleSuccess
|
handleSuccess: (response) => {
|
||||||
|
if (typeof child.props.handleSuccess === 'function') {
|
||||||
|
child.props.handleSuccess(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handleSuccess(response);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -12,6 +12,8 @@ import SPPieceContainer from './simple_prize/components/ascribe_detail/prize_pie
|
|||||||
import SPSettingsContainer from './simple_prize/components/prize_settings_container';
|
import SPSettingsContainer from './simple_prize/components/prize_settings_container';
|
||||||
import SPApp from './simple_prize/prize_app';
|
import SPApp from './simple_prize/prize_app';
|
||||||
|
|
||||||
|
import SluicePieceContainer from './sluice/components/sluice_detail/sluice_piece_container';
|
||||||
|
|
||||||
import PRApp from './portfolioreview/pr_app';
|
import PRApp from './portfolioreview/pr_app';
|
||||||
import PRLanding from './portfolioreview/components/pr_landing';
|
import PRLanding from './portfolioreview/components/pr_landing';
|
||||||
import PRRegisterPiece from './portfolioreview/components/pr_register_piece';
|
import PRRegisterPiece from './portfolioreview/components/pr_register_piece';
|
||||||
@ -53,7 +55,7 @@ const ROUTES = {
|
|||||||
path='collection'
|
path='collection'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(SPPieceList)}
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(SPPieceList)}
|
||||||
headerTitle='COLLECTION'/>
|
headerTitle='COLLECTION'/>
|
||||||
<Route path='pieces/:pieceId' component={SPPieceContainer} />
|
<Route path='pieces/:pieceId' component={SluicePieceContainer} />
|
||||||
<Route path='editions/:editionId' component={EditionContainer} />
|
<Route path='editions/:editionId' component={EditionContainer} />
|
||||||
<Route path='verify' component={CoaVerifyContainer} />
|
<Route path='verify' component={CoaVerifyContainer} />
|
||||||
<Route path='*' component={ErrorNotFoundPage} />
|
<Route path='*' component={ErrorNotFoundPage} />
|
||||||
|
@ -10,7 +10,8 @@ class PrizeRatingActions {
|
|||||||
this.generateActions(
|
this.generateActions(
|
||||||
'updatePrizeRatings',
|
'updatePrizeRatings',
|
||||||
'updatePrizeRatingAverage',
|
'updatePrizeRatingAverage',
|
||||||
'updatePrizeRating'
|
'updatePrizeRating',
|
||||||
|
'resetPrizeRatings'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,23 +171,25 @@ let AccordionListItemPrize = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { children, className, content } = this.props;
|
||||||
|
const { currentUser } = this.state;
|
||||||
|
|
||||||
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
|
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
|
||||||
let artistName = ((this.state.currentUser.is_jury && !this.state.currentUser.is_judge) ||
|
let artistName = ((currentUser.is_jury && !currentUser.is_judge) || (currentUser.is_judge && !content.selected )) ?
|
||||||
(this.state.currentUser.is_judge && !this.props.content.selected )) ?
|
<span className="glyphicon glyphicon-eye-close" aria-hidden="true"/> : content.artist_name;
|
||||||
<span className="glyphicon glyphicon-eye-close" aria-hidden="true"/> : this.props.content.artist_name;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AccordionListItemPiece
|
<AccordionListItemPiece
|
||||||
className={this.props.className}
|
className={className}
|
||||||
piece={this.props.content}
|
piece={content}
|
||||||
artistName={artistName}
|
artistName={artistName}
|
||||||
subsubheading={
|
subsubheading={
|
||||||
<div>
|
<div>
|
||||||
<span>{Moment(this.props.content.date_created, 'YYYY-MM-DD').year()}</span>
|
<span>{Moment(content.date_created, 'YYYY-MM-DD').year()}</span>
|
||||||
</div>}
|
</div>}
|
||||||
buttons={this.getPrizeButtons()}
|
buttons={this.getPrizeButtons()}
|
||||||
badge={this.getPrizeBadge()}>
|
badge={this.getPrizeBadge()}>
|
||||||
{this.props.children}
|
{children}
|
||||||
</AccordionListItemPiece>
|
</AccordionListItemPiece>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -34,9 +34,7 @@ import CollapsibleParagraph from '../../../../../../components/ascribe_collapsib
|
|||||||
import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader';
|
import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader';
|
||||||
|
|
||||||
import InputCheckbox from '../../../../../ascribe_forms/input_checkbox';
|
import InputCheckbox from '../../../../../ascribe_forms/input_checkbox';
|
||||||
import LoanForm from '../../../../../ascribe_forms/form_loan';
|
|
||||||
import ListRequestActions from '../../../../../ascribe_forms/list_form_request_actions';
|
import ListRequestActions from '../../../../../ascribe_forms/list_form_request_actions';
|
||||||
import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
|
|
||||||
|
|
||||||
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
|
import GlobalNotificationModel from '../../../../../../models/global_notification_model';
|
||||||
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
|
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
|
||||||
@ -52,39 +50,41 @@ import { setDocumentTitle } from '../../../../../../utils/dom_utils';
|
|||||||
/**
|
/**
|
||||||
* This is the component that implements resource/data specific functionality
|
* This is the component that implements resource/data specific functionality
|
||||||
*/
|
*/
|
||||||
let PieceContainer = React.createClass({
|
let PrizePieceContainer = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
params: React.PropTypes.object
|
params: React.PropTypes.object,
|
||||||
|
selectedPrizeActionButton: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [ReactError],
|
mixins: [ReactError],
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
//FIXME: this component uses the PieceStore, but we avoid using the getState() here since it may contain stale data
|
||||||
PieceStore.getState(),
|
// It should instead use something like getInitialState() where that call also resets the state.
|
||||||
UserStore.getState()
|
return UserStore.getState();
|
||||||
);
|
},
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
// Every time we enter the piece detail page, just reset the piece
|
||||||
|
// store as it will otherwise display wrong/old data once the user loads
|
||||||
|
// the piece detail a second time
|
||||||
|
PieceActions.updatePiece({});
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
PieceStore.listen(this.onChange);
|
PieceStore.listen(this.onChange);
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
|
|
||||||
// Every time we enter the piece detail page, just reset the piece
|
|
||||||
// store as it will otherwise display wrong/old data once the user loads
|
|
||||||
// the piece detail a second time
|
|
||||||
PieceActions.updatePiece({});
|
|
||||||
|
|
||||||
PieceActions.fetchOne(this.props.params.pieceId);
|
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
|
this.loadPiece();
|
||||||
},
|
},
|
||||||
|
|
||||||
// This is done to update the container when the user clicks on the prev or next
|
// This is done to update the container when the user clicks on the prev or next
|
||||||
// button to update the URL parameter (and therefore to switch pieces)
|
// button to update the URL parameter (and therefore to switch pieces)
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if(this.props.params.pieceId !== nextProps.params.pieceId) {
|
if (this.props.params.pieceId !== nextProps.params.pieceId) {
|
||||||
PieceActions.updatePiece({});
|
PieceActions.updatePiece({});
|
||||||
PieceActions.fetchOne(nextProps.params.pieceId);
|
this.loadPiece(nextProps.params.pieceId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -101,26 +101,32 @@ let PieceContainer = React.createClass({
|
|||||||
UserStore.unlisten(this.onChange);
|
UserStore.unlisten(this.onChange);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
onChange(state) {
|
onChange(state) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
},
|
},
|
||||||
|
|
||||||
getActions() {
|
getActions() {
|
||||||
if (this.state.piece &&
|
const { currentUser, piece } = this.state;
|
||||||
this.state.piece.notifications &&
|
|
||||||
this.state.piece.notifications.length > 0) {
|
if (piece && piece.notifications && piece.notifications.length > 0) {
|
||||||
return (
|
return (
|
||||||
<ListRequestActions
|
<ListRequestActions
|
||||||
pieceOrEditions={this.state.piece}
|
pieceOrEditions={piece}
|
||||||
currentUser={this.state.currentUser}
|
currentUser={currentUser}
|
||||||
handleSuccess={this.loadPiece}
|
handleSuccess={this.loadPiece}
|
||||||
notifications={this.state.piece.notifications}/>);
|
notifications={piece.notifications}/>);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadPiece(pieceId = this.props.params.pieceId) {
|
||||||
|
PieceActions.fetchOne(pieceId);
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if(this.state.piece && this.state.piece.id) {
|
const { selectedPrizeActionButton } = this.props;
|
||||||
|
const { currentUser, piece } = this.state;
|
||||||
|
|
||||||
|
if (piece && piece.id) {
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This really needs a refactor!
|
This really needs a refactor!
|
||||||
@ -129,37 +135,32 @@ let PieceContainer = React.createClass({
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
|
// Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted
|
||||||
let artistName = ((this.state.currentUser.is_jury && !this.state.currentUser.is_judge) ||
|
let artistName;
|
||||||
(this.state.currentUser.is_judge && !this.state.piece.selected )) ?
|
if ((currentUser.is_jury && !currentUser.is_judge) || (currentUser.is_judge && !piece.selected )) {
|
||||||
null : this.state.piece.artist_name;
|
artistName = <span className="glyphicon glyphicon-eye-close" aria-hidden="true"/>;
|
||||||
|
setDocumentTitle(piece.title);
|
||||||
|
} else {
|
||||||
|
artistName = piece.artist_name;
|
||||||
|
setDocumentTitle([artistName, piece.title].join(', '));
|
||||||
|
}
|
||||||
|
|
||||||
// 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 ) ?
|
const artistEmail = (currentUser.is_judge && piece.selected ) ?
|
||||||
<DetailProperty label={getLangText('REGISTREE')} value={ this.state.piece.user_registered } /> : null;
|
<DetailProperty label={getLangText('REGISTREE')} value={ piece.user_registered } /> : null;
|
||||||
|
|
||||||
if (artistName === null) {
|
|
||||||
setDocumentTitle(this.state.piece.title);
|
|
||||||
} else {
|
|
||||||
setDocumentTitle([artistName, this.state.piece.title].join(', '));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (artistName === null) {
|
|
||||||
artistName = <span className="glyphicon glyphicon-eye-close" aria-hidden="true"/>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Piece
|
<Piece
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
loadPiece={this.loadPiece}
|
currentUser={currentUser}
|
||||||
header={
|
header={
|
||||||
<div className="ascribe-detail-header">
|
<div className="ascribe-detail-header">
|
||||||
<NavigationHeader
|
<NavigationHeader
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
currentUser={this.state.currentUser}/>
|
currentUser={currentUser}/>
|
||||||
|
|
||||||
<h1 className="ascribe-detail-title">{this.state.piece.title}</h1>
|
<h1 className="ascribe-detail-title">{piece.title}</h1>
|
||||||
<DetailProperty label={getLangText('BY')} value={artistName} />
|
<DetailProperty label={getLangText('BY')} value={artistName} />
|
||||||
<DetailProperty label={getLangText('DATE')} value={Moment(this.state.piece.date_created, 'YYYY-MM-DD').year()} />
|
<DetailProperty label={getLangText('DATE')} value={Moment(piece.date_created, 'YYYY-MM-DD').year()} />
|
||||||
{artistEmail}
|
{artistEmail}
|
||||||
{this.getActions()}
|
{this.getActions()}
|
||||||
<hr/>
|
<hr/>
|
||||||
@ -168,10 +169,11 @@ let PieceContainer = React.createClass({
|
|||||||
subheader={
|
subheader={
|
||||||
<PrizePieceRatings
|
<PrizePieceRatings
|
||||||
loadPiece={this.loadPiece}
|
loadPiece={this.loadPiece}
|
||||||
piece={this.state.piece}
|
piece={piece}
|
||||||
currentUser={this.state.currentUser}/>
|
currentUser={currentUser}
|
||||||
|
selectedPrizeActionButton={selectedPrizeActionButton} />
|
||||||
}>
|
}>
|
||||||
<PrizePieceDetails piece={this.state.piece} />
|
<PrizePieceDetails piece={piece} />
|
||||||
</Piece>
|
</Piece>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -225,29 +227,26 @@ let PrizePieceRatings = React.createClass({
|
|||||||
propTypes: {
|
propTypes: {
|
||||||
loadPiece: React.PropTypes.func,
|
loadPiece: React.PropTypes.func,
|
||||||
piece: React.PropTypes.object,
|
piece: React.PropTypes.object,
|
||||||
currentUser: React.PropTypes.object
|
currentUser: React.PropTypes.object,
|
||||||
|
selectedPrizeActionButton: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
PieceListStore.getState(),
|
PieceListStore.getState(),
|
||||||
PrizeRatingStore.getState()
|
PrizeRatingStore.getInitialState()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
PrizeRatingStore.listen(this.onChange);
|
PrizeRatingStore.listen(this.onChange);
|
||||||
|
PieceListStore.listen(this.onChange);
|
||||||
|
|
||||||
PrizeRatingActions.fetchOne(this.props.piece.id);
|
PrizeRatingActions.fetchOne(this.props.piece.id);
|
||||||
PrizeRatingActions.fetchAverage(this.props.piece.id);
|
PrizeRatingActions.fetchAverage(this.props.piece.id);
|
||||||
PieceListStore.listen(this.onChange);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
// Every time we're leaving the piece detail page,
|
|
||||||
// just reset the piece that is saved in the piece store
|
|
||||||
// as it will otherwise display wrong/old data once the user loads
|
|
||||||
// the piece detail a second time
|
|
||||||
PrizeRatingActions.updateRating({});
|
|
||||||
PrizeRatingStore.unlisten(this.onChange);
|
PrizeRatingStore.unlisten(this.onChange);
|
||||||
PieceListStore.unlisten(this.onChange);
|
PieceListStore.unlisten(this.onChange);
|
||||||
},
|
},
|
||||||
@ -270,48 +269,23 @@ let PrizePieceRatings = React.createClass({
|
|||||||
|
|
||||||
onRatingClick(event, args) {
|
onRatingClick(event, args) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
PrizeRatingActions.createRating(this.props.piece.id, args.rating).then(
|
PrizeRatingActions
|
||||||
this.refreshPieceData()
|
.createRating(this.props.piece.id, args.rating)
|
||||||
);
|
.then(this.refreshPieceData);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleLoanRequestSuccess(message){
|
getSelectedActionButton() {
|
||||||
let notification = new GlobalNotificationModel(message, 'success', 4000);
|
const { currentUser, piece, selectedPrizeActionButton: SelectedPrizeActionButton } = this.props;
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
|
||||||
},
|
|
||||||
|
|
||||||
getLoanButton(){
|
if (piece.selected && SelectedPrizeActionButton) {
|
||||||
let today = new Moment();
|
return (
|
||||||
let endDate = new Moment();
|
<span className="pull-right">
|
||||||
endDate.add(6, 'months');
|
<SelectedPrizeActionButton
|
||||||
return (
|
piece={piece}
|
||||||
<ModalWrapper
|
currentUser={currentUser} />
|
||||||
trigger={
|
</span>
|
||||||
<button className='btn btn-default btn-sm'>
|
);
|
||||||
{getLangText('SEND LOAN REQUEST')}
|
}
|
||||||
</button>
|
|
||||||
}
|
|
||||||
handleSuccess={this.handleLoanRequestSuccess}
|
|
||||||
title='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: this.props.piece.id}}
|
|
||||||
url={ApiUrls.ownership_loans_pieces_request}
|
|
||||||
email={this.props.currentUser.email}
|
|
||||||
gallery={this.props.piece.prize.name}
|
|
||||||
startDate={today}
|
|
||||||
endDate={endDate}
|
|
||||||
showPersonalMessage={true}
|
|
||||||
showPassword={false}
|
|
||||||
handleSuccess={this.handleLoanSuccess} />
|
|
||||||
</ModalWrapper>);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleShortlistSuccess(message){
|
|
||||||
let notification = new GlobalNotificationModel(message, 'success', 2000);
|
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshPieceData() {
|
refreshPieceData() {
|
||||||
@ -321,20 +295,19 @@ let PrizePieceRatings = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onSelectChange() {
|
onSelectChange() {
|
||||||
PrizeRatingActions.toggleShortlist(this.props.piece.id)
|
PrizeRatingActions
|
||||||
.then(
|
.toggleShortlist(this.props.piece.id)
|
||||||
(res) => {
|
.then((res) => {
|
||||||
this.refreshPieceData();
|
this.refreshPieceData();
|
||||||
return res;
|
|
||||||
})
|
if (res && res.notification) {
|
||||||
.then(
|
const notification = new GlobalNotificationModel(res.notification, 'success', 2000);
|
||||||
(res) => {
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
this.handleShortlistSuccess(res.notification);
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render(){
|
render() {
|
||||||
if (this.props.piece && this.props.currentUser && this.props.currentUser.is_judge && this.state.average) {
|
if (this.props.piece && this.props.currentUser && this.props.currentUser.is_judge && this.state.average) {
|
||||||
// Judge sees shortlisting, average and per-jury notes
|
// Judge sees shortlisting, average and per-jury notes
|
||||||
return (
|
return (
|
||||||
@ -352,9 +325,7 @@ let PrizePieceRatings = React.createClass({
|
|||||||
</span>
|
</span>
|
||||||
</InputCheckbox>
|
</InputCheckbox>
|
||||||
</span>
|
</span>
|
||||||
<span className="pull-right">
|
{this.getSelectedActionButton()}
|
||||||
{this.props.piece.selected ? this.getLoanButton() : null}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
@ -373,13 +344,19 @@ let PrizePieceRatings = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
{this.state.ratings.map((item, i) => {
|
{this.state.ratings.map((item, i) => {
|
||||||
let note = item.note ?
|
let note = item.note ? (
|
||||||
<div className="rating-note">
|
<div className="rating-note">
|
||||||
note: {item.note}
|
note: {item.note}
|
||||||
</div> : null;
|
</div>
|
||||||
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rating-list">
|
<div
|
||||||
<div id="list-rating" className="row no-margin">
|
key={item.user}
|
||||||
|
className="rating-list">
|
||||||
|
<div
|
||||||
|
id="list-rating"
|
||||||
|
className="row no-margin">
|
||||||
<span className="pull-right">
|
<span className="pull-right">
|
||||||
<StarRating
|
<StarRating
|
||||||
ref={'rating' + i}
|
ref={'rating' + i}
|
||||||
@ -399,8 +376,7 @@ let PrizePieceRatings = React.createClass({
|
|||||||
<hr />
|
<hr />
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
} else if (this.props.currentUser && this.props.currentUser.is_jury) {
|
||||||
else if (this.props.currentUser && this.props.currentUser.is_jury) {
|
|
||||||
// Jury can set rating and note
|
// Jury can set rating and note
|
||||||
return (
|
return (
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
@ -427,8 +403,9 @@ let PrizePieceRatings = React.createClass({
|
|||||||
url={ApiUrls.notes}
|
url={ApiUrls.notes}
|
||||||
currentUser={this.props.currentUser}/>
|
currentUser={this.props.currentUser}/>
|
||||||
</CollapsibleParagraph>);
|
</CollapsibleParagraph>);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -457,6 +434,7 @@ let PrizePieceDetails = React.createClass({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Property
|
<Property
|
||||||
|
key={label}
|
||||||
name={data}
|
name={data}
|
||||||
label={label}
|
label={label}
|
||||||
editable={false}
|
editable={false}
|
||||||
@ -484,4 +462,4 @@ let PrizePieceDetails = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default PieceContainer;
|
export default PrizePieceContainer;
|
||||||
|
@ -48,9 +48,8 @@ let PrizePieceList = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getButtonSubmit() {
|
getButtonSubmit() {
|
||||||
const { currentUser } = this.state;
|
const { currentUser, prize } = this.state;
|
||||||
if (this.state.prize && this.state.prize.active &&
|
if (prize && prize.active && !currentUser.is_jury && !currentUser.is_admin && !currentUser.is_judge) {
|
||||||
!currentUser.is_jury && !currentUser.is_admin && !currentUser.is_judge){
|
|
||||||
return (
|
return (
|
||||||
<LinkContainer to="/register_piece">
|
<LinkContainer to="/register_piece">
|
||||||
<Button>
|
<Button>
|
||||||
|
@ -135,14 +135,15 @@ let PrizeJurySettings = React.createClass({
|
|||||||
|
|
||||||
handleCreateSuccess(response) {
|
handleCreateSuccess(response) {
|
||||||
PrizeJuryActions.fetchJury();
|
PrizeJuryActions.fetchJury();
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success', 5000);
|
this.displayNotification(response);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
|
||||||
this.refs.form.refs.email.refs.input.getDOMNode().value = null;
|
this.refs.form.refs.email.refs.input.getDOMNode().value = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleActivate(event) {
|
handleActivate(event) {
|
||||||
let email = event.target.getAttribute('data-id');
|
let email = event.target.getAttribute('data-id');
|
||||||
PrizeJuryActions.activateJury(email).then((response) => {
|
PrizeJuryActions
|
||||||
|
.activateJury(email)
|
||||||
|
.then((response) => {
|
||||||
PrizeJuryActions.fetchJury();
|
PrizeJuryActions.fetchJury();
|
||||||
this.displayNotification(response);
|
this.displayNotification(response);
|
||||||
});
|
});
|
||||||
|
@ -6,10 +6,12 @@ import PrizeRatingActions from '../actions/prize_rating_actions';
|
|||||||
|
|
||||||
class PrizeRatingStore {
|
class PrizeRatingStore {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.ratings = [];
|
this.getInitialState();
|
||||||
this.currentRating = null;
|
|
||||||
this.average = null;
|
|
||||||
this.bindActions(PrizeRatingActions);
|
this.bindActions(PrizeRatingActions);
|
||||||
|
this.exportPublicMethods({
|
||||||
|
getInitialState: this.getInitialState.bind(this)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdatePrizeRatings(ratings) {
|
onUpdatePrizeRatings(ratings) {
|
||||||
@ -24,6 +26,22 @@ class PrizeRatingStore {
|
|||||||
this.average = data.average;
|
this.average = data.average;
|
||||||
this.ratings = data.ratings;
|
this.ratings = data.ratings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onResetPrizeRatings() {
|
||||||
|
this.getInitialState();
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
this.ratings = [];
|
||||||
|
this.currentRating = null;
|
||||||
|
this.average = null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
ratings: this.ratings,
|
||||||
|
currentRating: this.currentRating,
|
||||||
|
average: this.average
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore');
|
export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore');
|
@ -0,0 +1,70 @@
|
|||||||
|
'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: {
|
||||||
|
piece: React.PropTypes.object,
|
||||||
|
currentUser: React.PropTypes.object,
|
||||||
|
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;
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
'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: {
|
||||||
|
params: React.PropTypes.object
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<PrizePieceContainer
|
||||||
|
{...this.props}
|
||||||
|
selectedPrizeActionButton={SluiceSelectedPrizeActionButton} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SluicePieceContainer;
|
Loading…
Reference in New Issue
Block a user