mirror of
https://github.com/ascribe/onion.git
synced 2024-11-14 09:05:08 +01:00
Merged in AD-661-due-1208-implement-jury-rating-an (pull request #40)
Ad 661 due 1208 implement jury rating an
This commit is contained in:
commit
b229dbb79f
38
js/actions/ownership_actions.js
Normal file
38
js/actions/ownership_actions.js
Normal file
@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import OwnershipFetcher from '../fetchers/ownership_fetcher';
|
||||
|
||||
|
||||
class OwnershipActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
'updateLoanPieceRequestList',
|
||||
'updateLoanPieceRequest',
|
||||
'flushLoanPieceRequest'
|
||||
);
|
||||
}
|
||||
|
||||
fetchLoanRequestList() {
|
||||
OwnershipFetcher.fetchLoanPieceRequestList()
|
||||
.then((data) => {
|
||||
this.actions.updateLoanPieceRequestList(data.loan_requests);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.logGlobal(err);
|
||||
this.actions.updateLoanPieceRequestList(null);
|
||||
});
|
||||
}
|
||||
|
||||
fetchLoanRequest(pieceId) {
|
||||
OwnershipFetcher.fetchLoanPieceRequestList()
|
||||
.then((data) => {
|
||||
this.actions.updateLoanPieceRequest({loanRequests: data.loan_requests, pieceId: pieceId});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.logGlobal(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createActions(OwnershipActions);
|
@ -39,7 +39,7 @@ let AccordionListItem = React.createClass({
|
||||
</div>
|
||||
<span style={{'clear': 'both'}}></span>
|
||||
|
||||
<div className="request-action-batch">
|
||||
<div className="request-action-badge">
|
||||
{this.props.badge}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -61,13 +61,13 @@ let AccordionListItemWallet = React.createClass({
|
||||
},
|
||||
|
||||
getGlyphicon(){
|
||||
if (this.props.content.requestAction) {
|
||||
if (this.props.content.requestAction && this.props.content.requestAction.length > 0) {
|
||||
return (
|
||||
<OverlayTrigger
|
||||
delay={500}
|
||||
placement="left"
|
||||
overlay={<Tooltip>{getLangText('You have actions pending in one of your editions')}</Tooltip>}>
|
||||
<Glyphicon glyph='bell'/>
|
||||
<Glyphicon glyph='bell' color="green"/>
|
||||
</OverlayTrigger>);
|
||||
}
|
||||
return null;
|
||||
|
@ -6,6 +6,7 @@ import ConsignForm from '../ascribe_forms/form_consign';
|
||||
import UnConsignForm from '../ascribe_forms/form_unconsign';
|
||||
import TransferForm from '../ascribe_forms/form_transfer';
|
||||
import LoanForm from '../ascribe_forms/form_loan';
|
||||
import LoanRequestAnswerForm from '../ascribe_forms/form_loan_request_answer';
|
||||
import ShareForm from '../ascribe_forms/form_share_email';
|
||||
import ModalWrapper from '../ascribe_modal/modal_wrapper';
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
@ -27,6 +28,8 @@ let AclButton = React.createClass({
|
||||
React.PropTypes.array
|
||||
]).isRequired,
|
||||
currentUser: React.PropTypes.object,
|
||||
buttonAcceptName: React.PropTypes.string,
|
||||
buttonAcceptClassName: React.PropTypes.string,
|
||||
handleSuccess: React.PropTypes.func.isRequired,
|
||||
className: React.PropTypes.string
|
||||
},
|
||||
@ -89,6 +92,18 @@ let AclButton = React.createClass({
|
||||
handleSuccess: this.showNotification
|
||||
};
|
||||
}
|
||||
else if (this.props.action === 'acl_loan_request'){
|
||||
return {
|
||||
title: getLangText('Loan artwork'),
|
||||
tooltip: getLangText('Someone requested you to loan your artwork for a limited period of time'),
|
||||
form: (<LoanRequestAnswerForm
|
||||
message={message}
|
||||
id={this.getFormDataId()}
|
||||
url={ApiUrls.ownership_loans_pieces_request_confirm}/>
|
||||
),
|
||||
handleSuccess: this.showNotification
|
||||
};
|
||||
}
|
||||
else if (this.props.action === 'acl_share'){
|
||||
return {
|
||||
title: getLangText('Share artwork'),
|
||||
@ -140,17 +155,20 @@ let AclButton = React.createClass({
|
||||
|
||||
// Removes the acl_ prefix and converts to upper case
|
||||
sanitizeAction() {
|
||||
if (this.props.buttonAcceptName) {
|
||||
return this.props.buttonAcceptName;
|
||||
}
|
||||
return this.props.action.split('acl_')[1].toUpperCase();
|
||||
},
|
||||
|
||||
render() {
|
||||
let shouldDisplay = this.props.availableAcls[this.props.action];
|
||||
let aclProps = this.actionProperties();
|
||||
|
||||
let buttonClassName = this.props.buttonAcceptClassName ? this.props.buttonAcceptClassName : '';
|
||||
return (
|
||||
<ModalWrapper
|
||||
trigger={
|
||||
<button className={shouldDisplay ? 'btn btn-default btn-sm ' : 'hidden'}>
|
||||
<button className={shouldDisplay ? 'btn btn-default btn-sm ' + buttonClassName : 'hidden'}>
|
||||
{this.sanitizeAction()}
|
||||
</button>
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import EditionDetailProperty from './detail_property';
|
||||
|
||||
import EditionFurtherDetails from './further_details';
|
||||
|
||||
import RequestActionForm from './../ascribe_forms/form_request_action';
|
||||
import ListRequestActions from './../ascribe_forms/list_form_request_actions';
|
||||
import AclButtonList from './../ascribe_buttons/acl_button_list';
|
||||
import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button';
|
||||
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||
@ -101,10 +101,6 @@ let Edition = React.createClass({
|
||||
this.transitionTo('pieces');
|
||||
},
|
||||
|
||||
getId() {
|
||||
return {'bitcoin_id': this.props.edition.bitcoin_id};
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Row>
|
||||
@ -159,7 +155,7 @@ let Edition = React.createClass({
|
||||
show={(this.state.currentUser.username && true || false) ||
|
||||
(this.props.edition.acl.acl_edit || this.props.edition.public_note)}>
|
||||
<Note
|
||||
id={this.getId}
|
||||
id={() => {return {'bitcoin_id': this.props.edition.bitcoin_id}; }}
|
||||
label={getLangText('Personal note (private)')}
|
||||
defaultValue={this.props.edition.private_note ? this.props.edition.private_note : null}
|
||||
placeholder={getLangText('Enter your comments ...')}
|
||||
@ -168,7 +164,7 @@ let Edition = React.createClass({
|
||||
url={ApiUrls.note_private_edition}
|
||||
currentUser={this.state.currentUser}/>
|
||||
<Note
|
||||
id={this.getId}
|
||||
id={() => {return {'bitcoin_id': this.props.edition.bitcoin_id}; }}
|
||||
label={getLangText('Edition note (public)')}
|
||||
defaultValue={this.props.edition.public_note ? this.props.edition.public_note : null}
|
||||
placeholder={getLangText('Enter your comments ...')}
|
||||
@ -240,12 +236,11 @@ let EditionSummary = React.createClass({
|
||||
let actions = null;
|
||||
if (this.props.edition.request_action && this.props.edition.request_action.length > 0){
|
||||
actions = (
|
||||
<RequestActionForm
|
||||
<ListRequestActions
|
||||
pieceOrEditions={[this.props.edition]}
|
||||
currentUser={this.props.currentUser}
|
||||
pieceOrEditions={ [this.props.edition] }
|
||||
requestAction={this.props.edition.request_action}
|
||||
requestUser={this.props.edition.owner}
|
||||
handleSuccess={this.showNotification}/>);
|
||||
handleSuccess={this.showNotification}
|
||||
requestActions={this.props.edition.request_action}/>);
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -26,7 +26,7 @@ import CreateEditionsForm from '../ascribe_forms/create_editions_form';
|
||||
import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
|
||||
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||
|
||||
import RequestActionForm from '../ascribe_forms/form_request_action';
|
||||
import ListRequestActions from '../ascribe_forms/list_form_request_actions';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
@ -175,12 +175,12 @@ let PieceContainer = React.createClass({
|
||||
this.state.piece.request_action &&
|
||||
this.state.piece.request_action.length > 0) {
|
||||
return (
|
||||
<RequestActionForm
|
||||
<ListRequestActions
|
||||
pieceOrEditions={this.state.piece}
|
||||
currentUser={this.state.currentUser}
|
||||
pieceOrEditions={ this.state.piece }
|
||||
requestAction={this.state.piece.request_action}
|
||||
requestUser={this.state.piece.user_registered}
|
||||
handleSuccess={this.loadPiece}/>);
|
||||
handleSuccess={this.loadPiece}
|
||||
requestActions={this.state.piece.request_action}/>
|
||||
);
|
||||
}
|
||||
else {
|
||||
return (
|
||||
|
@ -28,6 +28,9 @@ let LoanForm = React.createClass({
|
||||
startdate: React.PropTypes.object,
|
||||
enddate: React.PropTypes.object,
|
||||
showPersonalMessage: React.PropTypes.bool,
|
||||
showEndDate: React.PropTypes.bool,
|
||||
showStartDate: React.PropTypes.bool,
|
||||
showPassword: React.PropTypes.bool,
|
||||
url: React.PropTypes.string,
|
||||
id: React.PropTypes.object,
|
||||
message: React.PropTypes.string,
|
||||
@ -37,7 +40,10 @@ let LoanForm = React.createClass({
|
||||
getDefaultProps() {
|
||||
return {
|
||||
loanHeading: '',
|
||||
showPersonalMessage: true
|
||||
showPersonalMessage: true,
|
||||
showEndDate: true,
|
||||
showStartDate: true,
|
||||
showPassword: true
|
||||
};
|
||||
},
|
||||
|
||||
@ -47,7 +53,7 @@ let LoanForm = React.createClass({
|
||||
|
||||
componentDidMount() {
|
||||
LoanContractStore.listen(this.onChange);
|
||||
LoanContractActions.flushLoanContract();
|
||||
LoanContractActions.flushLoanContract.defer();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -155,7 +161,7 @@ let LoanForm = React.createClass({
|
||||
required/>
|
||||
</Property>
|
||||
<Property
|
||||
name='gallery_name'
|
||||
name='gallery'
|
||||
label={getLangText('Gallery/exhibition (optional)')}
|
||||
editable={!this.props.gallery}
|
||||
overrideForm={!!this.props.gallery}>
|
||||
@ -167,15 +173,19 @@ let LoanForm = React.createClass({
|
||||
<Property
|
||||
name='startdate'
|
||||
label={getLangText('Start date')}
|
||||
hidden={this.props.startdate}>
|
||||
editable={!this.props.startdate}
|
||||
overrideForm={!!this.props.startdate}
|
||||
hidden={!this.props.showStartDate}>
|
||||
<InputDate
|
||||
defaultValue={this.props.startdate}
|
||||
placeholderText={getLangText('Loan start date')} />
|
||||
</Property>
|
||||
<Property
|
||||
name='enddate'
|
||||
editable={!this.props.enddate}
|
||||
overrideForm={!!this.props.enddate}
|
||||
label={getLangText('End date')}
|
||||
hidden={this.props.enddate}>
|
||||
hidden={!this.props.showEndDate}>
|
||||
<InputDate
|
||||
defaultValue={this.props.enddate}
|
||||
placeholderText={getLangText('Loan end date')} />
|
||||
@ -190,15 +200,16 @@ let LoanForm = React.createClass({
|
||||
editable={true}
|
||||
defaultValue={this.props.message}
|
||||
placeholder={getLangText('Enter a message...')}
|
||||
required="required"/>
|
||||
required={this.props.showPersonalMessage ? 'required' : ''}/>
|
||||
</Property>
|
||||
<Property
|
||||
name='password'
|
||||
label={getLangText('Password')}>
|
||||
label={getLangText('Password')}
|
||||
hidden={!this.props.showPassword}>
|
||||
<input
|
||||
type="password"
|
||||
placeholder={getLangText('Enter your password')}
|
||||
required/>
|
||||
required={this.props.showPassword ? 'required' : ''}/>
|
||||
</Property>
|
||||
{this.getContractCheckbox()}
|
||||
{this.props.children}
|
||||
|
79
js/components/ascribe_forms/form_loan_request_answer.js
Normal file
79
js/components/ascribe_forms/form_loan_request_answer.js
Normal file
@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Moment from 'moment';
|
||||
|
||||
import LoanForm from './form_loan';
|
||||
|
||||
import OwnershipActions from '../../actions/ownership_actions';
|
||||
import OwnershipStore from '../../stores/ownership_store';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
|
||||
let LoanRequestAnswerForm = React.createClass({
|
||||
propTypes: {
|
||||
url: React.PropTypes.string,
|
||||
id: React.PropTypes.object,
|
||||
message: React.PropTypes.string,
|
||||
handleSuccess: React.PropTypes.func.required
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
loanHeading: '',
|
||||
showPersonalMessage: true,
|
||||
showEndDate: false,
|
||||
showStartDate: false,
|
||||
showPassword: true
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return OwnershipStore.getState();
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
OwnershipStore.listen(this.onChange);
|
||||
OwnershipActions.fetchLoanRequest(this.props.id.piece_id);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
OwnershipStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
|
||||
render() {
|
||||
let startDate = null;
|
||||
let endDate = null;
|
||||
|
||||
if (this.state.loanRequest) {
|
||||
startDate = new Moment(this.state.loanRequest.datetime_from, Moment.ISO_8601);
|
||||
endDate = new Moment(this.state.loanRequest.datetime_to, Moment.ISO_8601);
|
||||
|
||||
return (
|
||||
<LoanForm
|
||||
loanHeading={null}
|
||||
message={''}
|
||||
id={this.props.id}
|
||||
url={this.props.url}
|
||||
email={this.state.loanRequest ? this.state.loanRequest.new_owner : null}
|
||||
gallery={this.state.loanRequest ? this.state.loanRequest.gallery : null}
|
||||
startdate={startDate}
|
||||
enddate={endDate}
|
||||
showPassword={true}
|
||||
showPersonalMessage={false}
|
||||
handleSuccess={this.props.handleSuccess}/>
|
||||
);
|
||||
}
|
||||
return <span/>;
|
||||
}
|
||||
});
|
||||
|
||||
export default LoanRequestAnswerForm;
|
@ -45,6 +45,9 @@ let RequestActionForm = React.createClass({
|
||||
} else if (this.props.requestAction === 'loan' && this.isPiece()){
|
||||
urls.accept = ApiUrls.ownership_loans_pieces_confirm;
|
||||
urls.deny = ApiUrls.ownership_loans_pieces_deny;
|
||||
} else if (this.props.requestAction === 'loan_request' && this.isPiece()){
|
||||
urls.accept = ApiUrls.ownership_loans_pieces_request_confirm;
|
||||
urls.deny = ApiUrls.ownership_loans_pieces_request_deny;
|
||||
}
|
||||
|
||||
return urls;
|
||||
@ -75,8 +78,11 @@ let RequestActionForm = React.createClass({
|
||||
},
|
||||
|
||||
getContent() {
|
||||
let message = this.props.requestUser + ' ' + getLangText('requests you') + ' ' + this.props.requestAction + ' ' + getLangText('this edition%s', '.');
|
||||
|
||||
let pieceOrEditionStr = this.isPiece() ? getLangText('this work%s', '.') : getLangText('this edition%s', '.');
|
||||
let message = this.props.requestUser + ' ' + getLangText('requests you') + ' ' + this.props.requestAction + ' ' + pieceOrEditionStr;
|
||||
if (this.props.requestAction === 'loan_request'){
|
||||
message = this.props.requestUser + ' ' + getLangText('requests you to loan') + ' ' + pieceOrEditionStr;
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
{message}
|
||||
@ -90,6 +96,18 @@ let RequestActionForm = React.createClass({
|
||||
<AclButton
|
||||
availableAcls={{'acl_unconsign': true}}
|
||||
action="acl_unconsign"
|
||||
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
|
||||
pieceOrEditions={this.props.pieceOrEditions}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.props.handleSuccess} />
|
||||
);
|
||||
} else if(this.props.requestAction === 'loan_request') {
|
||||
return (
|
||||
<AclButton
|
||||
availableAcls={{'acl_loan_request': true}}
|
||||
action="acl_loan_request"
|
||||
buttonAcceptName="LOAN"
|
||||
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
|
||||
pieceOrEditions={this.props.pieceOrEditions}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.props.handleSuccess} />
|
||||
|
@ -9,7 +9,11 @@ let InputDate = React.createClass({
|
||||
submitted: React.PropTypes.bool,
|
||||
placeholderText: React.PropTypes.string,
|
||||
onChange: React.PropTypes.func,
|
||||
defaultValue: React.PropTypes.object
|
||||
defaultValue: React.PropTypes.object,
|
||||
|
||||
// DatePicker implements the disabled attribute
|
||||
// https://github.com/Hacker0x01/react-datepicker/blob/master/src/datepicker.jsx#L30
|
||||
disabled: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -41,10 +45,11 @@ let InputDate = React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
render: function () {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<DatePicker
|
||||
disabled={this.props.disabled}
|
||||
dateFormat="YYYY-MM-DD"
|
||||
selected={this.state.value_moment}
|
||||
onChange={this.handleChange}
|
||||
|
37
js/components/ascribe_forms/list_form_request_actions.js
Normal file
37
js/components/ascribe_forms/list_form_request_actions.js
Normal file
@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import RequestActionForm from './form_request_action';
|
||||
|
||||
let ListRequestActions = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
pieceOrEditions: React.PropTypes.oneOfType([
|
||||
React.PropTypes.object,
|
||||
React.PropTypes.array
|
||||
]).isRequired,
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
handleSuccess: React.PropTypes.func.isRequired,
|
||||
requestActions: React.PropTypes.array.isRequired
|
||||
},
|
||||
|
||||
render () {
|
||||
if (this.props.requestActions &&
|
||||
this.props.requestActions.length > 0) {
|
||||
return (
|
||||
<div>
|
||||
{this.props.requestActions.map((requestAction) =>
|
||||
<RequestActionForm
|
||||
currentUser={this.props.currentUser}
|
||||
pieceOrEditions={ this.props.pieceOrEditions }
|
||||
requestAction={requestAction.action}
|
||||
requestUser={requestAction.by}
|
||||
handleSuccess={this.props.handleSuccess}/>)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
export default ListRequestActions;
|
@ -11,10 +11,10 @@ let TableItemAclFiltered = React.createClass({
|
||||
|
||||
render() {
|
||||
var availableAcls = ['acl_consign', 'acl_loan', 'acl_transfer', 'acl_view', 'acl_share', 'acl_unshare', 'acl_delete'];
|
||||
if (this.props.requestAction){
|
||||
if (this.props.requestAction && this.props.requestAction.length > 0){
|
||||
return (
|
||||
<span>
|
||||
{this.props.requestAction + ' request pending'}
|
||||
{this.props.requestAction[0].action + ' request pending'}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ let PieceList = React.createClass({
|
||||
redirectTo: React.PropTypes.string,
|
||||
customSubmitButton: React.PropTypes.element,
|
||||
filterParams: React.PropTypes.array,
|
||||
orderParams: React.PropTypes.array
|
||||
orderParams: React.PropTypes.array,
|
||||
orderBy: React.PropTypes.string
|
||||
|
||||
},
|
||||
|
||||
@ -59,10 +60,10 @@ let PieceList = React.createClass({
|
||||
|
||||
PieceListStore.listen(this.onChange);
|
||||
EditionListStore.listen(this.onChange);
|
||||
|
||||
let orderBy = this.props.orderBy ? this.props.orderBy : this.state.orderBy;
|
||||
if (this.state.pieceList.length === 0 || this.state.page !== page){
|
||||
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search,
|
||||
this.state.orderBy, this.state.orderAsc, this.state.filterBy)
|
||||
orderBy, this.state.orderAsc, this.state.filterBy)
|
||||
.then(() => PieceListActions.fetchPieceRequestActions());
|
||||
}
|
||||
},
|
||||
|
@ -9,16 +9,17 @@ class PrizeRatingActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
'updatePrizeRatings',
|
||||
'updatePrizeRatingAverage',
|
||||
'updatePrizeRating'
|
||||
);
|
||||
}
|
||||
|
||||
fetch() {
|
||||
fetchAverage(pieceId) {
|
||||
return Q.Promise((resolve, reject) => {
|
||||
PrizeRatingFetcher
|
||||
.fetch()
|
||||
.fetchAverage(pieceId)
|
||||
.then((res) => {
|
||||
this.actions.updatePrizeRatings(res.ratings);
|
||||
this.actions.updatePrizeRatingAverage(res.data);
|
||||
resolve(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -56,6 +57,20 @@ class PrizeRatingActions {
|
||||
});
|
||||
}
|
||||
|
||||
toggleShortlist(pieceId) {
|
||||
return Q.Promise((resolve, reject) => {
|
||||
PrizeRatingFetcher
|
||||
.select(pieceId)
|
||||
.then((res) => {
|
||||
this.actions.updatePrizeRatings(res.data.ratings);
|
||||
resolve(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateRating(rating) {
|
||||
this.actions.updatePrizeRating(rating);
|
||||
}
|
||||
|
@ -4,13 +4,17 @@ import React from 'react';
|
||||
import Router from 'react-router';
|
||||
import StarRating from 'react-star-rating';
|
||||
|
||||
import AccordionListItemPiece from '../../../../ascribe_accordion_list/accordion_list_item_piece';
|
||||
|
||||
import PieceListActions from '../../../../../actions/piece_list_actions';
|
||||
import PieceListStore from '../../../../../stores/piece_list_store';
|
||||
|
||||
import PrizeRatingActions from '../../actions/prize_rating_actions';
|
||||
|
||||
import UserStore from '../../../../../stores/user_store';
|
||||
|
||||
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';
|
||||
|
||||
@ -65,17 +69,28 @@ let AccordionListItemPrize = React.createClass({
|
||||
|
||||
getPrizeButtons() {
|
||||
if (this.state.currentUser && this.state.currentUser.is_jury){
|
||||
if (this.props.content.ratings && this.props.content.ratings.rating){
|
||||
if ((this.props.content.ratings) &&
|
||||
(this.props.content.ratings.rating || this.props.content.ratings.average)){
|
||||
// jury and rating available
|
||||
let rating = parseInt(this.props.content.ratings.rating, 10);
|
||||
let rating = null,
|
||||
caption = null;
|
||||
if (this.props.content.ratings.rating){
|
||||
rating = parseInt(this.props.content.ratings.rating, 10);
|
||||
caption = getLangText('Your rating');
|
||||
}
|
||||
else if (this.props.content.ratings.average){
|
||||
rating = this.props.content.ratings.average;
|
||||
caption = getLangText('Average of ' + this.props.content.ratings.num_ratings + ' rating(s)');
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="list-rating" className="pull-right">
|
||||
<Link to='piece' params={{pieceId: this.props.content.id}}>
|
||||
<StarRating
|
||||
ref='rating'
|
||||
name="prize-rating"
|
||||
caption="Your rating"
|
||||
step={1}
|
||||
caption={caption}
|
||||
step={0.5}
|
||||
size='sm'
|
||||
rating={rating}
|
||||
ratingAmount={5} />
|
||||
@ -83,17 +98,28 @@ let AccordionListItemPrize = React.createClass({
|
||||
</div>);
|
||||
}
|
||||
else {
|
||||
if (this.state.currentUser.is_judge){
|
||||
return (
|
||||
<div className="react-rating-caption pull-right">
|
||||
{getLangText('Not rated')}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// jury and no rating yet
|
||||
return (
|
||||
<div className="react-rating-caption pull-right">
|
||||
<Link to='piece' params={{pieceId: this.props.content.id}}>
|
||||
Submit your rating
|
||||
{getLangText('Submit your rating')}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
// participant
|
||||
return this.getPrizeButtonsParticipant();
|
||||
|
||||
},
|
||||
|
||||
getPrizeButtonsParticipant() {
|
||||
return (
|
||||
<div>
|
||||
<AclProxy
|
||||
@ -108,22 +134,64 @@ let AccordionListItemPrize = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
handleShortlistSuccess(message){
|
||||
let notification = new GlobalNotificationModel(message, 'success', 2000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
refreshPieceData() {
|
||||
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
|
||||
this.state.orderBy, this.state.orderAsc, this.state.filterBy);
|
||||
},
|
||||
|
||||
onSelectChange(){
|
||||
PrizeRatingActions.toggleShortlist(this.props.content.id)
|
||||
.then(
|
||||
(res) => {
|
||||
this.refreshPieceData();
|
||||
return res;
|
||||
})
|
||||
.then(
|
||||
(res) => {
|
||||
this.handleShortlistSuccess(res.notification);
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
getPrizeBadge(){
|
||||
if (this.state.currentUser && this.state.currentUser.is_judge) {
|
||||
return (
|
||||
<span className="pull-right ascribe-checkbox-wrapper ascribe-checkbox-badge">
|
||||
<InputCheckbox
|
||||
defaultChecked={this.props.content.selected}
|
||||
onChange={this.onSelectChange}/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
render() {
|
||||
let artistName = this.state.currentUser.is_jury ?
|
||||
<span className="glyphicon glyphicon-eye-close" style={{fontSize: '0.75em'}} aria-hidden="true"/> :
|
||||
this.props.content.artist_name;
|
||||
// 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) ||
|
||||
(this.state.currentUser.is_judge && !this.props.content.selected )) ?
|
||||
<span className="glyphicon glyphicon-eye-close" aria-hidden="true"/> : this.props.content.artist_name;
|
||||
return (
|
||||
<AccordionListItemPiece
|
||||
className={this.props.className}
|
||||
piece={this.props.content}
|
||||
artistName={artistName}
|
||||
subsubheading={
|
||||
<div className="pull-left">
|
||||
<span>{this.props.content.date_created.split('-')[0]}</span>
|
||||
</div>}
|
||||
buttons={this.getPrizeButtons()}>
|
||||
{this.props.children}
|
||||
</AccordionListItemPiece>
|
||||
<div>
|
||||
<AccordionListItemPiece
|
||||
className={this.props.className}
|
||||
piece={this.props.content}
|
||||
artistName={artistName}
|
||||
subsubheading={
|
||||
<div className="pull-left">
|
||||
<span>{this.props.content.date_created.split('-')[0]}</span>
|
||||
</div>}
|
||||
buttons={this.getPrizeButtons()}
|
||||
badge={this.getPrizeBadge()}>
|
||||
{this.props.children}
|
||||
</AccordionListItemPiece>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
import Moment from 'moment';
|
||||
|
||||
import StarRating from 'react-star-rating';
|
||||
|
||||
@ -17,6 +18,7 @@ import PrizeRatingStore from '../../stores/prize_rating_store';
|
||||
import UserStore from '../../../../../stores/user_store';
|
||||
|
||||
import Piece from '../../../../../components/ascribe_detail/piece';
|
||||
import Note from '../../../../../components/ascribe_detail/note';
|
||||
|
||||
import AppConstants from '../../../../../constants/application_constants';
|
||||
|
||||
@ -25,6 +27,11 @@ 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 InputCheckbox from '../../../../ascribe_forms/input_checkbox';
|
||||
import LoanForm from '../../../../ascribe_forms/form_loan';
|
||||
import ListRequestActions from '../../../../ascribe_forms/list_form_request_actions';
|
||||
import ModalWrapper from '../../../../ascribe_modal/modal_wrapper';
|
||||
|
||||
import GlobalNotificationModel from '../../../../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
|
||||
|
||||
@ -53,6 +60,15 @@ let PieceContainer = React.createClass({
|
||||
UserStore.listen(this.onChange);
|
||||
},
|
||||
|
||||
// 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)
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if(this.props.params.pieceId !== nextProps.params.pieceId) {
|
||||
PieceActions.updatePiece({});
|
||||
PieceActions.fetchOne(nextProps.params.pieceId);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
// Every time we're leaving the piece detail page,
|
||||
// just reset the piece that is saved in the piece store
|
||||
@ -63,14 +79,6 @@ let PieceContainer = React.createClass({
|
||||
UserStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
// 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)
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if(this.props.params.pieceId !== nextProps.params.pieceId) {
|
||||
PieceActions.updatePiece({});
|
||||
PieceActions.fetchOne(nextProps.params.pieceId);
|
||||
}
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
@ -78,12 +86,18 @@ let PieceContainer = React.createClass({
|
||||
|
||||
loadPiece() {
|
||||
PieceActions.fetchOne(this.props.params.pieceId);
|
||||
this.setState(this.state);
|
||||
},
|
||||
|
||||
render() {
|
||||
if('title' in this.state.piece) {
|
||||
let artistName = this.state.currentUser.is_jury ?
|
||||
// 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) ||
|
||||
(this.state.currentUser.is_judge && !this.state.piece.selected )) ?
|
||||
<span className="glyphicon glyphicon-eye-close" aria-hidden="true"/> : this.state.piece.artist_name;
|
||||
// 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 ) ?
|
||||
<DetailProperty label={getLangText('REGISTREE')} value={ this.state.piece.user_registered } /> : null;
|
||||
return (
|
||||
<Piece
|
||||
piece={this.state.piece}
|
||||
@ -95,13 +109,20 @@ let PieceContainer = React.createClass({
|
||||
currentUser={this.state.currentUser}/>
|
||||
<hr/>
|
||||
<h1 className="ascribe-detail-title">{this.state.piece.title}</h1>
|
||||
<DetailProperty label="BY" value={artistName} />
|
||||
<DetailProperty label="DATE" value={ this.state.piece.date_created.slice(0, 4) } />
|
||||
<DetailProperty label={getLangText('BY')} value={artistName} />
|
||||
<DetailProperty label={getLangText('DATE')} value={ this.state.piece.date_created.slice(0, 4) } />
|
||||
{artistEmail}
|
||||
<ListRequestActions
|
||||
pieceOrEditions={this.state.piece}
|
||||
currentUser={this.state.currentUser}
|
||||
handleSuccess={this.loadPiece}
|
||||
requestActions={this.state.piece.request_action}/>
|
||||
<hr/>
|
||||
</div>
|
||||
}
|
||||
subheader={
|
||||
<PrizePieceRatings
|
||||
loadPiece={this.loadPiece}
|
||||
piece={this.state.piece}
|
||||
currentUser={this.state.currentUser}/>
|
||||
}>
|
||||
@ -153,6 +174,7 @@ let NavigationHeader = React.createClass({
|
||||
|
||||
let PrizePieceRatings = React.createClass({
|
||||
propTypes: {
|
||||
loadPiece: React.PropTypes.func,
|
||||
piece: React.PropTypes.object,
|
||||
currentUser: React.PropTypes.object
|
||||
},
|
||||
@ -167,6 +189,7 @@ let PrizePieceRatings = React.createClass({
|
||||
componentDidMount() {
|
||||
PrizeRatingStore.listen(this.onChange);
|
||||
PrizeRatingActions.fetchOne(this.props.piece.id);
|
||||
PrizeRatingActions.fetchAverage(this.props.piece.id);
|
||||
PieceListStore.listen(this.onChange);
|
||||
},
|
||||
|
||||
@ -199,16 +222,142 @@ let PrizePieceRatings = React.createClass({
|
||||
onRatingClick(event, args) {
|
||||
event.preventDefault();
|
||||
PrizeRatingActions.createRating(this.props.piece.id, args.rating).then(
|
||||
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
|
||||
this.state.orderBy, this.state.orderAsc, this.state.filterBy)
|
||||
this.refreshPieceData()
|
||||
);
|
||||
},
|
||||
|
||||
handleLoanRequestSuccess(message){
|
||||
let notification = new GlobalNotificationModel(message, 'success', 4000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
getLoanButton(){
|
||||
let today = new Moment();
|
||||
let endDate = new Moment();
|
||||
endDate.add(6, 'months');
|
||||
return (
|
||||
<ModalWrapper
|
||||
trigger={
|
||||
<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() {
|
||||
this.props.loadPiece();
|
||||
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
|
||||
this.state.orderBy, this.state.orderAsc, this.state.filterBy);
|
||||
},
|
||||
|
||||
onSelectChange() {
|
||||
PrizeRatingActions.toggleShortlist(this.props.piece.id)
|
||||
.then(
|
||||
(res) => {
|
||||
this.refreshPieceData();
|
||||
return res;
|
||||
})
|
||||
.then(
|
||||
(res) => {
|
||||
this.handleShortlistSuccess(res.notification);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
render(){
|
||||
if (this.props.currentUser && this.props.currentUser.is_jury) {
|
||||
if (this.props.piece && this.props.currentUser && this.props.currentUser.is_judge && this.state.average) {
|
||||
// Judge sees shortlisting, average and per-jury notes
|
||||
return (
|
||||
<div>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Shortlisting')}
|
||||
show={true}
|
||||
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>
|
||||
<span className="pull-right">
|
||||
{this.props.piece.selected ? this.getLoanButton() : null}
|
||||
</span>
|
||||
</div>
|
||||
<hr />
|
||||
</CollapsibleParagraph>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Average Rating')}
|
||||
show={true}
|
||||
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 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 && this.props.currentUser.is_jury) {
|
||||
// Jury can set rating and note
|
||||
return (
|
||||
<CollapsibleParagraph
|
||||
title="Rating"
|
||||
title={getLangText('Rating')}
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
<div style={{marginLeft: '1.5em', marginBottom: '1em'}}>
|
||||
@ -222,8 +371,14 @@ let PrizePieceRatings = React.createClass({
|
||||
onRatingClick={this.onRatingClick}
|
||||
ratingAmount={5} />
|
||||
</div>
|
||||
<PersonalNote
|
||||
piece={this.props.piece}
|
||||
<Note
|
||||
id={() => {return {'piece_id': this.props.piece.id}; }}
|
||||
label={getLangText('Jury note')}
|
||||
defaultValue={this.props.piece && this.props.piece.note_from_user ? this.props.piece.note_from_user.note : null}
|
||||
placeholder={getLangText('Enter your comments ...')}
|
||||
editable={true}
|
||||
successMessage={getLangText('Jury note saved')}
|
||||
url={ApiUrls.notes}
|
||||
currentUser={this.props.currentUser}/>
|
||||
</CollapsibleParagraph>);
|
||||
}
|
||||
@ -231,43 +386,6 @@ let PrizePieceRatings = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
let PersonalNote = React.createClass({
|
||||
propTypes: {
|
||||
piece: React.PropTypes.object,
|
||||
currentUser: React.PropTypes.object
|
||||
},
|
||||
showNotification(){
|
||||
let notification = new GlobalNotificationModel(getLangText('Jury note saved'), 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
render() {
|
||||
if (this.props.currentUser && this.props.currentUser.username) {
|
||||
return (
|
||||
<Form
|
||||
url={ApiUrls.notes}
|
||||
handleSuccess={this.showNotification}>
|
||||
<Property
|
||||
name='value'
|
||||
label={getLangText('Jury note')}
|
||||
editable={true}>
|
||||
<InputTextAreaToggable
|
||||
rows={1}
|
||||
editable={true}
|
||||
defaultValue={this.props.piece && this.props.piece.note_from_user ? this.props.piece.note_from_user.note : null}
|
||||
placeholder={getLangText('Enter your comments...')}/>
|
||||
</Property>
|
||||
<Property hidden={true} name='piece_id'>
|
||||
<input defaultValue={this.props.piece.id}/>
|
||||
</Property>
|
||||
<hr />
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let PrizePieceDetails = React.createClass({
|
||||
propTypes: {
|
||||
|
@ -40,23 +40,35 @@ let PrizePieceList = React.createClass({
|
||||
},
|
||||
|
||||
getButtonSubmit() {
|
||||
if (this.state.prize && this.state.prize.active){
|
||||
if (this.state.prize && this.state.prize.active && !this.state.currentUser.is_jury){
|
||||
return (
|
||||
<ButtonLink to="register_piece">
|
||||
{getLangText('Submit to prize')}
|
||||
</ButtonLink>
|
||||
);
|
||||
}
|
||||
else if (this.state.prize && this.state.currentUser.is_judge){
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
render() {
|
||||
let orderParams = ['artist_name', 'title'];
|
||||
if (this.state.currentUser.is_jury) {
|
||||
orderParams = ['rating', 'title'];
|
||||
}
|
||||
if (this.state.currentUser.is_judge) {
|
||||
orderParams = ['rating', 'title', 'selected'];
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<PieceList
|
||||
ref="list"
|
||||
redirectTo="register_piece"
|
||||
accordionListItemType={AccordionListItemPrize}
|
||||
orderParams={this.state.currentUser.is_jury ? ['rating', 'title'] : ['artist_name', 'title']}
|
||||
orderParams={orderParams}
|
||||
orderBy={this.state.currentUser.is_jury ? 'rating' : null}
|
||||
filterParams={null}
|
||||
customSubmitButton={this.getButtonSubmit()}/>
|
||||
</div>
|
||||
|
@ -17,6 +17,8 @@ function getPrizeApiUrls(subdomain) {
|
||||
'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}/'
|
||||
|
||||
|
@ -4,8 +4,8 @@ import requests from '../../../../utils/requests';
|
||||
|
||||
|
||||
let PrizeRatingFetcher = {
|
||||
fetch() {
|
||||
return requests.get('rating');
|
||||
fetchAverage(pieceId) {
|
||||
return requests.get('rating_average', {'piece_id': pieceId});
|
||||
},
|
||||
|
||||
fetchOne(pieceId) {
|
||||
@ -13,7 +13,11 @@ let PrizeRatingFetcher = {
|
||||
},
|
||||
|
||||
rate(pieceId, rating) {
|
||||
return requests.post('ratings', {body: {'piece_id': pieceId, 'value': rating}});
|
||||
return requests.post('ratings', {body: {'piece_id': pieceId, 'note': rating}});
|
||||
},
|
||||
|
||||
select(pieceId) {
|
||||
return requests.post('select_piece', {'piece_id': pieceId});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -8,16 +8,22 @@ class PrizeRatingStore {
|
||||
constructor() {
|
||||
this.ratings = [];
|
||||
this.currentRating = null;
|
||||
this.average = null;
|
||||
this.bindActions(PrizeRatingActions);
|
||||
}
|
||||
|
||||
onUpdatePrizeRatings( ratings ) {
|
||||
onUpdatePrizeRatings(ratings) {
|
||||
this.ratings = ratings;
|
||||
}
|
||||
|
||||
onUpdatePrizeRating( rating ) {
|
||||
onUpdatePrizeRating(rating) {
|
||||
this.currentRating = parseInt(rating, 10);
|
||||
}
|
||||
|
||||
onUpdatePrizeRatingAverage(data) {
|
||||
this.average = data.average;
|
||||
this.ratings = data.ratings;
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore');
|
@ -67,11 +67,6 @@ let CylandPieceContainer = React.createClass({
|
||||
PieceActions.fetchOne(this.props.params.pieceId);
|
||||
},
|
||||
|
||||
getId() {
|
||||
return {'id': this.state.piece.id};
|
||||
},
|
||||
|
||||
|
||||
render() {
|
||||
if('title' in this.state.piece) {
|
||||
return (
|
||||
@ -106,7 +101,7 @@ let CylandPieceContainer = React.createClass({
|
||||
show={(this.state.currentUser.username && true || false) ||
|
||||
(this.state.piece.public_note)}>
|
||||
<Note
|
||||
id={this.getId}
|
||||
id={() => {return {'id': this.state.piece.id}; }}
|
||||
label={getLangText('Personal note (private)')}
|
||||
defaultValue={this.state.piece.private_note ? this.state.piece.private_note : null}
|
||||
placeholder={getLangText('Enter your comments ...')}
|
||||
|
@ -7,7 +7,8 @@ function getWalletApiUrls(subdomain) {
|
||||
if (subdomain === 'cyland'){
|
||||
return {
|
||||
'pieces_list': walletConstants.walletApiEndpoint + subdomain + '/pieces/',
|
||||
'piece': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/'
|
||||
'piece': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/',
|
||||
'piece_extradata': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/extradata/'
|
||||
};
|
||||
}
|
||||
else if (subdomain === 'ikonotv'){
|
||||
|
@ -32,6 +32,9 @@ let ApiUrls = {
|
||||
'ownership_loans_pieces': AppConstants.apiEndpoint + 'ownership/loans/pieces/',
|
||||
'ownership_loans_pieces_confirm': AppConstants.apiEndpoint + 'ownership/loans/pieces/confirm/',
|
||||
'ownership_loans_pieces_deny': AppConstants.apiEndpoint + 'ownership/loans/pieces/deny/',
|
||||
'ownership_loans_pieces_request': AppConstants.apiEndpoint + 'ownership/loans/pieces/request/',
|
||||
'ownership_loans_pieces_request_confirm': AppConstants.apiEndpoint + 'ownership/loans/pieces/request_confirm/',
|
||||
'ownership_loans_pieces_request_deny': AppConstants.apiEndpoint + 'ownership/loans/pieces/request_deny/',
|
||||
'ownership_loans_editions': AppConstants.apiEndpoint + 'ownership/loans/editions/',
|
||||
'ownership_loans_confirm': AppConstants.apiEndpoint + 'ownership/loans/editions/confirm/',
|
||||
'ownership_loans_deny': AppConstants.apiEndpoint + 'ownership/loans/editions/deny/',
|
||||
|
@ -17,8 +17,11 @@ let OwnershipFetcher = {
|
||||
*/
|
||||
fetchLoanContractList(){
|
||||
return requests.get(ApiUrls.ownership_loans_contract);
|
||||
}
|
||||
},
|
||||
|
||||
fetchLoanPieceRequestList(){
|
||||
return requests.get(ApiUrls.ownership_loans_pieces_request);
|
||||
}
|
||||
};
|
||||
|
||||
export default OwnershipFetcher;
|
||||
|
35
js/stores/ownership_store.js
Normal file
35
js/stores/ownership_store.js
Normal file
@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import OwnershipActions from '../actions/ownership_actions';
|
||||
|
||||
|
||||
class OwnershipStore {
|
||||
constructor() {
|
||||
this.loanRequestList = [];
|
||||
this.loanRequest = null;
|
||||
this.bindActions(OwnershipActions);
|
||||
}
|
||||
|
||||
onUpdateLoanPieceRequestList(loanRequests) {
|
||||
this.loanRequestList = loanRequests;
|
||||
}
|
||||
|
||||
onUpdateLoanPieceRequest({loanRequests, pieceId}) {
|
||||
this.loanRequestList = loanRequests;
|
||||
this.loanRequest = loanRequests.filter((item) => item.piece_id === pieceId.toString());
|
||||
if (this.loanRequest.length > 0){
|
||||
this.loanRequest = this.loanRequest[0];
|
||||
}
|
||||
else {
|
||||
this.loanRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
onFlushLoanPieceRequest(){
|
||||
this.loanRequestList = [];
|
||||
this.loanRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createStore(OwnershipStore, 'OwnershipStore');
|
@ -23,6 +23,8 @@ export function getAclFormMessage(aclName, entities, senderName) {
|
||||
message += getLangText('I un-consign');
|
||||
} else if(aclName === 'acl_loan') {
|
||||
message += getLangText('I loan');
|
||||
} else if(aclName === 'acl_loan_request') {
|
||||
message += getLangText('I request to loan');
|
||||
} else if(aclName === 'acl_share') {
|
||||
message += getLangText('I share');
|
||||
} else {
|
||||
@ -34,7 +36,7 @@ export function getAclFormMessage(aclName, entities, senderName) {
|
||||
|
||||
if(aclName === 'acl_transfer' || aclName === 'acl_loan' || aclName === 'acl_consign') {
|
||||
message += getLangText('to you');
|
||||
} else if(aclName === 'acl_unconsign') {
|
||||
} else if(aclName === 'acl_unconsign' || aclName === 'acl_loan_request') {
|
||||
message += getLangText('from you');
|
||||
} else if(aclName === 'acl_share') {
|
||||
message += getLangText('with you');
|
||||
|
@ -73,7 +73,7 @@
|
||||
"raven-js": "^1.1.19",
|
||||
"react": "^0.13.2",
|
||||
"react-bootstrap": "^0.24.3",
|
||||
"react-datepicker": "~0.8.0",
|
||||
"react-datepicker": "^0.12.0",
|
||||
"react-progressbar": "^1.1.0",
|
||||
"react-router": "^0.13.3",
|
||||
"react-router-bootstrap": "~0.16.0",
|
||||
|
@ -152,11 +152,11 @@ span.ascribe-accordion-list-table-toggle {
|
||||
}
|
||||
}
|
||||
|
||||
.request-action-batch {
|
||||
.request-action-badge {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
color: #666;
|
||||
color: $ascribe-color-green;
|
||||
font-size: 1.2em;
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
@ -145,8 +145,15 @@
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
border-top: 1px solid rgba(0,0,0,.05);
|
||||
|
||||
|
||||
padding: .5em 1.5em .5em 1.5em;
|
||||
}
|
||||
|
||||
.ascribe-checkbox-wrapper{
|
||||
.checkbox > span {color: black;}
|
||||
}
|
||||
|
||||
.ascribe-settings-property-collapsible-toggle, .ascribe-checkbox-wrapper {
|
||||
|
||||
cursor:pointer;
|
||||
|
||||
@ -196,4 +203,10 @@
|
||||
font-size: 20px;
|
||||
color: rgba(2, 182, 163, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.ascribe-checkbox-badge{
|
||||
> span > span {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
@ -403,17 +403,6 @@ hr {
|
||||
}
|
||||
}
|
||||
|
||||
.rating-container .rating-stars {
|
||||
width: 25px;
|
||||
color: #02b6a3;
|
||||
}
|
||||
#list-rating > a > span > span > .rating-container .rating-stars{
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.react-rating-caption {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.disable-select {
|
||||
-webkit-user-select: none;
|
||||
|
@ -1,4 +1,5 @@
|
||||
@import 'landing';
|
||||
@import 'rating';
|
||||
|
||||
.ascribe-prize-app {
|
||||
border-radius: 0;
|
||||
|
34
sass/whitelabel/prize/rating.scss
Normal file
34
sass/whitelabel/prize/rating.scss
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
.rating-container .rating-stars {
|
||||
width: 25px;
|
||||
color: #02b6a3;
|
||||
}
|
||||
|
||||
#list-rating {
|
||||
> a > span > span > .rating-container .rating-stars {
|
||||
color: #000;
|
||||
}
|
||||
> span > span > span > .rating-container .rating-stars {
|
||||
color: #000;
|
||||
}
|
||||
> span > span > .rating-container .rating-stars {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
.react-rating-caption {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.rating-list {
|
||||
margin-left: 1.5em;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 0.3em;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.rating-note {
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
padding: 0.7em;
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user