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

Merge remote-tracking branch 'origin/master' into AD-456-ikonotv-branded-page-for-registra

This commit is contained in:
Tim Daubenschütz 2015-08-27 14:05:21 +02:00
commit b67466d196
32 changed files with 653 additions and 150 deletions

View 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);

View File

@ -39,7 +39,7 @@ let AccordionListItem = React.createClass({
</div> </div>
<span style={{'clear': 'both'}}></span> <span style={{'clear': 'both'}}></span>
<div className="request-action-batch"> <div className="request-action-badge">
{this.props.badge} {this.props.badge}
</div> </div>
</div> </div>

View File

@ -61,13 +61,13 @@ let AccordionListItemWallet = React.createClass({
}, },
getGlyphicon(){ getGlyphicon(){
if (this.props.content.requestAction) { if (this.props.content.requestAction && this.props.content.requestAction.length > 0) {
return ( return (
<OverlayTrigger <OverlayTrigger
delay={500} delay={500}
placement="left" placement="left"
overlay={<Tooltip>{getLangText('You have actions pending in one of your editions')}</Tooltip>}> overlay={<Tooltip>{getLangText('You have actions pending in one of your editions')}</Tooltip>}>
<Glyphicon glyph='bell'/> <Glyphicon glyph='bell' color="green"/>
</OverlayTrigger>); </OverlayTrigger>);
} }
return null; return null;

View File

@ -6,6 +6,7 @@ import ConsignForm from '../ascribe_forms/form_consign';
import UnConsignForm from '../ascribe_forms/form_unconsign'; import UnConsignForm from '../ascribe_forms/form_unconsign';
import TransferForm from '../ascribe_forms/form_transfer'; import TransferForm from '../ascribe_forms/form_transfer';
import LoanForm from '../ascribe_forms/form_loan'; 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 ShareForm from '../ascribe_forms/form_share_email';
import ModalWrapper from '../ascribe_modal/modal_wrapper'; import ModalWrapper from '../ascribe_modal/modal_wrapper';
import AppConstants from '../../constants/application_constants'; import AppConstants from '../../constants/application_constants';
@ -27,6 +28,8 @@ let AclButton = React.createClass({
React.PropTypes.array React.PropTypes.array
]).isRequired, ]).isRequired,
currentUser: React.PropTypes.object, currentUser: React.PropTypes.object,
buttonAcceptName: React.PropTypes.string,
buttonAcceptClassName: React.PropTypes.string,
handleSuccess: React.PropTypes.func.isRequired, handleSuccess: React.PropTypes.func.isRequired,
className: React.PropTypes.string className: React.PropTypes.string
}, },
@ -89,6 +92,18 @@ let AclButton = React.createClass({
handleSuccess: this.showNotification 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'){ else if (this.props.action === 'acl_share'){
return { return {
title: getLangText('Share artwork'), title: getLangText('Share artwork'),
@ -140,17 +155,20 @@ let AclButton = React.createClass({
// Removes the acl_ prefix and converts to upper case // Removes the acl_ prefix and converts to upper case
sanitizeAction() { sanitizeAction() {
if (this.props.buttonAcceptName) {
return this.props.buttonAcceptName;
}
return this.props.action.split('acl_')[1].toUpperCase(); return this.props.action.split('acl_')[1].toUpperCase();
}, },
render() { render() {
let shouldDisplay = this.props.availableAcls[this.props.action]; let shouldDisplay = this.props.availableAcls[this.props.action];
let aclProps = this.actionProperties(); let aclProps = this.actionProperties();
let buttonClassName = this.props.buttonAcceptClassName ? this.props.buttonAcceptClassName : '';
return ( return (
<ModalWrapper <ModalWrapper
trigger={ trigger={
<button className={shouldDisplay ? 'btn btn-default btn-sm ' : 'hidden'}> <button className={shouldDisplay ? 'btn btn-default btn-sm ' + buttonClassName : 'hidden'}>
{this.sanitizeAction()} {this.sanitizeAction()}
</button> </button>
} }

View File

@ -28,7 +28,7 @@ import EditionDetailProperty from './detail_property';
import EditionFurtherDetails from './further_details'; 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 AclButtonList from './../ascribe_buttons/acl_button_list';
import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button'; import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button';
import DeleteButton from '../ascribe_buttons/delete_button'; import DeleteButton from '../ascribe_buttons/delete_button';
@ -101,10 +101,6 @@ let Edition = React.createClass({
this.transitionTo('pieces'); this.transitionTo('pieces');
}, },
getId() {
return {'bitcoin_id': this.props.edition.bitcoin_id};
},
render() { render() {
return ( return (
<Row> <Row>
@ -159,7 +155,7 @@ let Edition = React.createClass({
show={(this.state.currentUser.username && true || false) || show={(this.state.currentUser.username && true || false) ||
(this.props.edition.acl.acl_edit || this.props.edition.public_note)}> (this.props.edition.acl.acl_edit || this.props.edition.public_note)}>
<Note <Note
id={this.getId} id={() => {return {'bitcoin_id': this.props.edition.bitcoin_id}; }}
label={getLangText('Personal note (private)')} label={getLangText('Personal note (private)')}
defaultValue={this.props.edition.private_note ? this.props.edition.private_note : null} defaultValue={this.props.edition.private_note ? this.props.edition.private_note : null}
placeholder={getLangText('Enter your comments ...')} placeholder={getLangText('Enter your comments ...')}
@ -168,7 +164,7 @@ let Edition = React.createClass({
url={ApiUrls.note_private_edition} url={ApiUrls.note_private_edition}
currentUser={this.state.currentUser}/> currentUser={this.state.currentUser}/>
<Note <Note
id={this.getId} id={() => {return {'bitcoin_id': this.props.edition.bitcoin_id}; }}
label={getLangText('Edition note (public)')} label={getLangText('Edition note (public)')}
defaultValue={this.props.edition.public_note ? this.props.edition.public_note : null} defaultValue={this.props.edition.public_note ? this.props.edition.public_note : null}
placeholder={getLangText('Enter your comments ...')} placeholder={getLangText('Enter your comments ...')}
@ -240,12 +236,11 @@ let EditionSummary = React.createClass({
let actions = null; let actions = null;
if (this.props.edition.request_action && this.props.edition.request_action.length > 0){ if (this.props.edition.request_action && this.props.edition.request_action.length > 0){
actions = ( actions = (
<RequestActionForm <ListRequestActions
pieceOrEditions={[this.props.edition]}
currentUser={this.props.currentUser} currentUser={this.props.currentUser}
pieceOrEditions={ [this.props.edition] } handleSuccess={this.showNotification}
requestAction={this.props.edition.request_action} requestActions={this.props.edition.request_action}/>);
requestUser={this.props.edition.owner}
handleSuccess={this.showNotification}/>);
} }
else { else {

View File

@ -26,7 +26,7 @@ import CreateEditionsForm from '../ascribe_forms/create_editions_form';
import CreateEditionsButton from '../ascribe_buttons/create_editions_button'; import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
import DeleteButton from '../ascribe_buttons/delete_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 GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions'; 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 &&
this.state.piece.request_action.length > 0) { this.state.piece.request_action.length > 0) {
return ( return (
<RequestActionForm <ListRequestActions
pieceOrEditions={this.state.piece}
currentUser={this.state.currentUser} currentUser={this.state.currentUser}
pieceOrEditions={ this.state.piece } handleSuccess={this.loadPiece}
requestAction={this.state.piece.request_action} requestActions={this.state.piece.request_action}/>
requestUser={this.state.piece.user_registered} );
handleSuccess={this.loadPiece}/>);
} }
else { else {
return ( return (

View File

@ -28,6 +28,9 @@ let LoanForm = React.createClass({
startdate: React.PropTypes.object, startdate: React.PropTypes.object,
enddate: React.PropTypes.object, enddate: React.PropTypes.object,
showPersonalMessage: React.PropTypes.bool, showPersonalMessage: React.PropTypes.bool,
showEndDate: React.PropTypes.bool,
showStartDate: React.PropTypes.bool,
showPassword: React.PropTypes.bool,
url: React.PropTypes.string, url: React.PropTypes.string,
id: React.PropTypes.object, id: React.PropTypes.object,
message: React.PropTypes.string, message: React.PropTypes.string,
@ -37,7 +40,10 @@ let LoanForm = React.createClass({
getDefaultProps() { getDefaultProps() {
return { return {
loanHeading: '', loanHeading: '',
showPersonalMessage: true showPersonalMessage: true,
showEndDate: true,
showStartDate: true,
showPassword: true
}; };
}, },
@ -47,7 +53,7 @@ let LoanForm = React.createClass({
componentDidMount() { componentDidMount() {
LoanContractStore.listen(this.onChange); LoanContractStore.listen(this.onChange);
LoanContractActions.flushLoanContract(); LoanContractActions.flushLoanContract.defer();
}, },
componentWillUnmount() { componentWillUnmount() {
@ -155,7 +161,7 @@ let LoanForm = React.createClass({
required/> required/>
</Property> </Property>
<Property <Property
name='gallery_name' name='gallery'
label={getLangText('Gallery/exhibition (optional)')} label={getLangText('Gallery/exhibition (optional)')}
editable={!this.props.gallery} editable={!this.props.gallery}
overrideForm={!!this.props.gallery}> overrideForm={!!this.props.gallery}>
@ -167,15 +173,19 @@ let LoanForm = React.createClass({
<Property <Property
name='startdate' name='startdate'
label={getLangText('Start date')} label={getLangText('Start date')}
hidden={this.props.startdate}> editable={!this.props.startdate}
overrideForm={!!this.props.startdate}
hidden={!this.props.showStartDate}>
<InputDate <InputDate
defaultValue={this.props.startdate} defaultValue={this.props.startdate}
placeholderText={getLangText('Loan start date')} /> placeholderText={getLangText('Loan start date')} />
</Property> </Property>
<Property <Property
name='enddate' name='enddate'
editable={!this.props.enddate}
overrideForm={!!this.props.enddate}
label={getLangText('End date')} label={getLangText('End date')}
hidden={this.props.enddate}> hidden={!this.props.showEndDate}>
<InputDate <InputDate
defaultValue={this.props.enddate} defaultValue={this.props.enddate}
placeholderText={getLangText('Loan end date')} /> placeholderText={getLangText('Loan end date')} />
@ -190,15 +200,16 @@ let LoanForm = React.createClass({
editable={true} editable={true}
defaultValue={this.props.message} defaultValue={this.props.message}
placeholder={getLangText('Enter a message...')} placeholder={getLangText('Enter a message...')}
required="required"/> required={this.props.showPersonalMessage ? 'required' : ''}/>
</Property> </Property>
<Property <Property
name='password' name='password'
label={getLangText('Password')}> label={getLangText('Password')}
hidden={!this.props.showPassword}>
<input <input
type="password" type="password"
placeholder={getLangText('Enter your password')} placeholder={getLangText('Enter your password')}
required/> required={this.props.showPassword ? 'required' : ''}/>
</Property> </Property>
{this.getContractCheckbox()} {this.getContractCheckbox()}
{this.props.children} {this.props.children}

View 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;

View File

@ -45,6 +45,9 @@ let RequestActionForm = React.createClass({
} else if (this.props.requestAction === 'loan' && this.isPiece()){ } else if (this.props.requestAction === 'loan' && this.isPiece()){
urls.accept = ApiUrls.ownership_loans_pieces_confirm; urls.accept = ApiUrls.ownership_loans_pieces_confirm;
urls.deny = ApiUrls.ownership_loans_pieces_deny; 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; return urls;
@ -75,8 +78,11 @@ let RequestActionForm = React.createClass({
}, },
getContent() { 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 ( return (
<span> <span>
{message} {message}
@ -90,6 +96,18 @@ let RequestActionForm = React.createClass({
<AclButton <AclButton
availableAcls={{'acl_unconsign': true}} availableAcls={{'acl_unconsign': true}}
action="acl_unconsign" 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} pieceOrEditions={this.props.pieceOrEditions}
currentUser={this.props.currentUser} currentUser={this.props.currentUser}
handleSuccess={this.props.handleSuccess} /> handleSuccess={this.props.handleSuccess} />

View File

@ -9,7 +9,11 @@ let InputDate = React.createClass({
submitted: React.PropTypes.bool, submitted: React.PropTypes.bool,
placeholderText: React.PropTypes.string, placeholderText: React.PropTypes.string,
onChange: React.PropTypes.func, 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() { getInitialState() {
@ -41,10 +45,11 @@ let InputDate = React.createClass({
}); });
}, },
render: function () { render() {
return ( return (
<div> <div>
<DatePicker <DatePicker
disabled={this.props.disabled}
dateFormat="YYYY-MM-DD" dateFormat="YYYY-MM-DD"
selected={this.state.value_moment} selected={this.state.value_moment}
onChange={this.handleChange} onChange={this.handleChange}

View 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;

View File

@ -11,10 +11,10 @@ let TableItemAclFiltered = React.createClass({
render() { render() {
var availableAcls = ['acl_consign', 'acl_loan', 'acl_transfer', 'acl_view', 'acl_share', 'acl_unshare', 'acl_delete']; 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 ( return (
<span> <span>
{this.props.requestAction + ' request pending'} {this.props.requestAction[0].action + ' request pending'}
</span> </span>
); );
} }

View File

@ -28,7 +28,8 @@ let PieceList = React.createClass({
redirectTo: React.PropTypes.string, redirectTo: React.PropTypes.string,
customSubmitButton: React.PropTypes.element, customSubmitButton: React.PropTypes.element,
filterParams: React.PropTypes.array, 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); PieceListStore.listen(this.onChange);
EditionListStore.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){ if (this.state.pieceList.length === 0 || this.state.page !== page){
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, 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()); .then(() => PieceListActions.fetchPieceRequestActions());
} }
}, },

View File

@ -9,16 +9,17 @@ class PrizeRatingActions {
constructor() { constructor() {
this.generateActions( this.generateActions(
'updatePrizeRatings', 'updatePrizeRatings',
'updatePrizeRatingAverage',
'updatePrizeRating' 'updatePrizeRating'
); );
} }
fetch() { fetchAverage(pieceId) {
return Q.Promise((resolve, reject) => { return Q.Promise((resolve, reject) => {
PrizeRatingFetcher PrizeRatingFetcher
.fetch() .fetchAverage(pieceId)
.then((res) => { .then((res) => {
this.actions.updatePrizeRatings(res.ratings); this.actions.updatePrizeRatingAverage(res.data);
resolve(res); resolve(res);
}) })
.catch((err) => { .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) { updateRating(rating) {
this.actions.updatePrizeRating(rating); this.actions.updatePrizeRating(rating);
} }

View File

@ -4,13 +4,17 @@ import React from 'react';
import Router from 'react-router'; import Router from 'react-router';
import StarRating from 'react-star-rating'; import StarRating from 'react-star-rating';
import AccordionListItemPiece from '../../../../ascribe_accordion_list/accordion_list_item_piece';
import PieceListActions from '../../../../../actions/piece_list_actions'; import PieceListActions from '../../../../../actions/piece_list_actions';
import PieceListStore from '../../../../../stores/piece_list_store'; import PieceListStore from '../../../../../stores/piece_list_store';
import PrizeRatingActions from '../../actions/prize_rating_actions';
import UserStore from '../../../../../stores/user_store'; 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 GlobalNotificationModel from '../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../actions/global_notification_actions'; import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
@ -65,17 +69,28 @@ let AccordionListItemPrize = React.createClass({
getPrizeButtons() { getPrizeButtons() {
if (this.state.currentUser && this.state.currentUser.is_jury){ 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 // 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 ( return (
<div id="list-rating" className="pull-right"> <div id="list-rating" className="pull-right">
<Link to='piece' params={{pieceId: this.props.content.id}}> <Link to='piece' params={{pieceId: this.props.content.id}}>
<StarRating <StarRating
ref='rating' ref='rating'
name="prize-rating" name="prize-rating"
caption="Your rating" caption={caption}
step={1} step={0.5}
size='sm' size='sm'
rating={rating} rating={rating}
ratingAmount={5} /> ratingAmount={5} />
@ -83,17 +98,28 @@ let AccordionListItemPrize = React.createClass({
</div>); </div>);
} }
else { else {
if (this.state.currentUser.is_judge){
return (
<div className="react-rating-caption pull-right">
{getLangText('Not rated')}
</div>
);
}
// jury and no rating yet // jury and no rating yet
return ( return (
<div className="react-rating-caption pull-right"> <div className="react-rating-caption pull-right">
<Link to='piece' params={{pieceId: this.props.content.id}}> <Link to='piece' params={{pieceId: this.props.content.id}}>
Submit your rating {getLangText('Submit your rating')}
</Link> </Link>
</div> </div>
); );
} }
} }
// participant return this.getPrizeButtonsParticipant();
},
getPrizeButtonsParticipant() {
return ( return (
<div> <div>
<AclProxy <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() { render() {
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
<span className="glyphicon glyphicon-eye-close" style={{fontSize: '0.75em'}} aria-hidden="true"/> : let artistName = ((this.state.currentUser.is_jury && !this.state.currentUser.is_judge) ||
this.props.content.artist_name; (this.state.currentUser.is_judge && !this.props.content.selected )) ?
<span className="glyphicon glyphicon-eye-close" aria-hidden="true"/> : this.props.content.artist_name;
return ( return (
<AccordionListItemPiece <div>
className={this.props.className} <AccordionListItemPiece
piece={this.props.content} className={this.props.className}
artistName={artistName} piece={this.props.content}
subsubheading={ artistName={artistName}
<div className="pull-left"> subsubheading={
<span>{this.props.content.date_created.split('-')[0]}</span> <div className="pull-left">
</div>} <span>{this.props.content.date_created.split('-')[0]}</span>
buttons={this.getPrizeButtons()}> </div>}
{this.props.children} buttons={this.getPrizeButtons()}
</AccordionListItemPiece> badge={this.getPrizeBadge()}>
{this.props.children}
</AccordionListItemPiece>
</div>
); );
} }
}); });

View File

@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import Router from 'react-router'; import Router from 'react-router';
import Moment from 'moment';
import StarRating from 'react-star-rating'; import StarRating from 'react-star-rating';
@ -17,6 +18,7 @@ import PrizeRatingStore from '../../stores/prize_rating_store';
import UserStore from '../../../../../stores/user_store'; import UserStore from '../../../../../stores/user_store';
import Piece from '../../../../../components/ascribe_detail/piece'; import Piece from '../../../../../components/ascribe_detail/piece';
import Note from '../../../../../components/ascribe_detail/note';
import AppConstants from '../../../../../constants/application_constants'; 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 InputTextAreaToggable from '../../../../../components/ascribe_forms/input_textarea_toggable';
import CollapsibleParagraph from '../../../../../components/ascribe_collapsible/collapsible_paragraph'; 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 GlobalNotificationModel from '../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../actions/global_notification_actions'; import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
@ -53,6 +60,15 @@ let PieceContainer = React.createClass({
UserStore.listen(this.onChange); 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() { componentWillUnmount() {
// Every time we're leaving the piece detail page, // Every time we're leaving the piece detail page,
// just reset the piece that is saved in the piece store // just reset the piece that is saved in the piece store
@ -63,14 +79,6 @@ let PieceContainer = React.createClass({
UserStore.unlisten(this.onChange); 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) { onChange(state) {
this.setState(state); this.setState(state);
@ -78,12 +86,18 @@ let PieceContainer = React.createClass({
loadPiece() { loadPiece() {
PieceActions.fetchOne(this.props.params.pieceId); PieceActions.fetchOne(this.props.params.pieceId);
this.setState(this.state);
}, },
render() { render() {
if('title' in this.state.piece) { 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; <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 ( return (
<Piece <Piece
piece={this.state.piece} piece={this.state.piece}
@ -95,13 +109,20 @@ let PieceContainer = React.createClass({
currentUser={this.state.currentUser}/> currentUser={this.state.currentUser}/>
<hr/> <hr/>
<h1 className="ascribe-detail-title">{this.state.piece.title}</h1> <h1 className="ascribe-detail-title">{this.state.piece.title}</h1>
<DetailProperty label="BY" value={artistName} /> <DetailProperty label={getLangText('BY')} value={artistName} />
<DetailProperty label="DATE" value={ this.state.piece.date_created.slice(0, 4) } /> <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/> <hr/>
</div> </div>
} }
subheader={ subheader={
<PrizePieceRatings <PrizePieceRatings
loadPiece={this.loadPiece}
piece={this.state.piece} piece={this.state.piece}
currentUser={this.state.currentUser}/> currentUser={this.state.currentUser}/>
}> }>
@ -153,6 +174,7 @@ let NavigationHeader = React.createClass({
let PrizePieceRatings = React.createClass({ let PrizePieceRatings = React.createClass({
propTypes: { propTypes: {
loadPiece: React.PropTypes.func,
piece: React.PropTypes.object, piece: React.PropTypes.object,
currentUser: React.PropTypes.object currentUser: React.PropTypes.object
}, },
@ -167,6 +189,7 @@ let PrizePieceRatings = React.createClass({
componentDidMount() { componentDidMount() {
PrizeRatingStore.listen(this.onChange); PrizeRatingStore.listen(this.onChange);
PrizeRatingActions.fetchOne(this.props.piece.id); PrizeRatingActions.fetchOne(this.props.piece.id);
PrizeRatingActions.fetchAverage(this.props.piece.id);
PieceListStore.listen(this.onChange); PieceListStore.listen(this.onChange);
}, },
@ -199,16 +222,142 @@ let PrizePieceRatings = React.createClass({
onRatingClick(event, args) { onRatingClick(event, args) {
event.preventDefault(); event.preventDefault();
PrizeRatingActions.createRating(this.props.piece.id, args.rating).then( PrizeRatingActions.createRating(this.props.piece.id, args.rating).then(
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, this.refreshPieceData()
this.state.orderBy, this.state.orderAsc, this.state.filterBy) );
},
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(){ 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 ( return (
<CollapsibleParagraph <CollapsibleParagraph
title="Rating" title={getLangText('Rating')}
show={true} show={true}
defaultExpanded={true}> defaultExpanded={true}>
<div style={{marginLeft: '1.5em', marginBottom: '1em'}}> <div style={{marginLeft: '1.5em', marginBottom: '1em'}}>
@ -222,8 +371,14 @@ let PrizePieceRatings = React.createClass({
onRatingClick={this.onRatingClick} onRatingClick={this.onRatingClick}
ratingAmount={5} /> ratingAmount={5} />
</div> </div>
<PersonalNote <Note
piece={this.props.piece} 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}/> currentUser={this.props.currentUser}/>
</CollapsibleParagraph>); </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({ let PrizePieceDetails = React.createClass({
propTypes: { propTypes: {

View File

@ -40,23 +40,35 @@ let PrizePieceList = React.createClass({
}, },
getButtonSubmit() { getButtonSubmit() {
if (this.state.prize && this.state.prize.active){ if (this.state.prize && this.state.prize.active && !this.state.currentUser.is_jury){
return ( return (
<ButtonLink to="register_piece"> <ButtonLink to="register_piece">
{getLangText('Submit to prize')} {getLangText('Submit to prize')}
</ButtonLink> </ButtonLink>
); );
} }
else if (this.state.prize && this.state.currentUser.is_judge){
return null;
}
return null; return null;
}, },
render() { 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 ( return (
<div> <div>
<PieceList <PieceList
ref="list"
redirectTo="register_piece" redirectTo="register_piece"
accordionListItemType={AccordionListItemPrize} 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} filterParams={null}
customSubmitButton={this.getButtonSubmit()}/> customSubmitButton={this.getButtonSubmit()}/>
</div> </div>

View File

@ -17,6 +17,8 @@ function getPrizeApiUrls(subdomain) {
'jury_resend': AppPrizeConstants.prizeApiEndpoint + subdomain + '/jury/${email}/resend/', 'jury_resend': AppPrizeConstants.prizeApiEndpoint + subdomain + '/jury/${email}/resend/',
'ratings': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/', 'ratings': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/',
'rating': AppPrizeConstants.prizeApiEndpoint + subdomain + '/ratings/${piece_id}/', '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/', 'notes': AppPrizeConstants.prizeApiEndpoint + subdomain + '/notes/',
'note': AppPrizeConstants.prizeApiEndpoint + subdomain + '/notes/${piece_id}/' 'note': AppPrizeConstants.prizeApiEndpoint + subdomain + '/notes/${piece_id}/'

View File

@ -4,8 +4,8 @@ import requests from '../../../../utils/requests';
let PrizeRatingFetcher = { let PrizeRatingFetcher = {
fetch() { fetchAverage(pieceId) {
return requests.get('rating'); return requests.get('rating_average', {'piece_id': pieceId});
}, },
fetchOne(pieceId) { fetchOne(pieceId) {
@ -13,7 +13,11 @@ let PrizeRatingFetcher = {
}, },
rate(pieceId, rating) { 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});
} }
}; };

View File

@ -8,16 +8,22 @@ class PrizeRatingStore {
constructor() { constructor() {
this.ratings = []; this.ratings = [];
this.currentRating = null; this.currentRating = null;
this.average = null;
this.bindActions(PrizeRatingActions); this.bindActions(PrizeRatingActions);
} }
onUpdatePrizeRatings( ratings ) { onUpdatePrizeRatings(ratings) {
this.ratings = ratings; this.ratings = ratings;
} }
onUpdatePrizeRating( rating ) { onUpdatePrizeRating(rating) {
this.currentRating = parseInt(rating, 10); this.currentRating = parseInt(rating, 10);
} }
onUpdatePrizeRatingAverage(data) {
this.average = data.average;
this.ratings = data.ratings;
}
} }
export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore'); export default alt.createStore(PrizeRatingStore, 'PrizeRatingStore');

View File

@ -67,11 +67,6 @@ let CylandPieceContainer = React.createClass({
PieceActions.fetchOne(this.props.params.pieceId); PieceActions.fetchOne(this.props.params.pieceId);
}, },
getId() {
return {'id': this.state.piece.id};
},
render() { render() {
if('title' in this.state.piece) { if('title' in this.state.piece) {
return ( return (
@ -106,7 +101,7 @@ let CylandPieceContainer = React.createClass({
show={(this.state.currentUser.username && true || false) || show={(this.state.currentUser.username && true || false) ||
(this.state.piece.public_note)}> (this.state.piece.public_note)}>
<Note <Note
id={this.getId} id={() => {return {'id': this.state.piece.id}; }}
label={getLangText('Personal note (private)')} label={getLangText('Personal note (private)')}
defaultValue={this.state.piece.private_note ? this.state.piece.private_note : null} defaultValue={this.state.piece.private_note ? this.state.piece.private_note : null}
placeholder={getLangText('Enter your comments ...')} placeholder={getLangText('Enter your comments ...')}

View File

@ -7,7 +7,8 @@ function getWalletApiUrls(subdomain) {
if (subdomain === 'cyland'){ if (subdomain === 'cyland'){
return { return {
'pieces_list': walletConstants.walletApiEndpoint + subdomain + '/pieces/', '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'){ else if (subdomain === 'ikonotv'){

View File

@ -32,6 +32,9 @@ let ApiUrls = {
'ownership_loans_pieces': AppConstants.apiEndpoint + 'ownership/loans/pieces/', 'ownership_loans_pieces': AppConstants.apiEndpoint + 'ownership/loans/pieces/',
'ownership_loans_pieces_confirm': AppConstants.apiEndpoint + 'ownership/loans/pieces/confirm/', 'ownership_loans_pieces_confirm': AppConstants.apiEndpoint + 'ownership/loans/pieces/confirm/',
'ownership_loans_pieces_deny': AppConstants.apiEndpoint + 'ownership/loans/pieces/deny/', '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_editions': AppConstants.apiEndpoint + 'ownership/loans/editions/',
'ownership_loans_confirm': AppConstants.apiEndpoint + 'ownership/loans/editions/confirm/', 'ownership_loans_confirm': AppConstants.apiEndpoint + 'ownership/loans/editions/confirm/',
'ownership_loans_deny': AppConstants.apiEndpoint + 'ownership/loans/editions/deny/', 'ownership_loans_deny': AppConstants.apiEndpoint + 'ownership/loans/editions/deny/',

View File

@ -17,8 +17,11 @@ let OwnershipFetcher = {
*/ */
fetchLoanContractList(){ fetchLoanContractList(){
return requests.get(ApiUrls.ownership_loans_contract); return requests.get(ApiUrls.ownership_loans_contract);
} },
fetchLoanPieceRequestList(){
return requests.get(ApiUrls.ownership_loans_pieces_request);
}
}; };
export default OwnershipFetcher; export default OwnershipFetcher;

View 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');

View File

@ -23,6 +23,8 @@ export function getAclFormMessage(aclName, entities, senderName) {
message += getLangText('I un-consign'); message += getLangText('I un-consign');
} else if(aclName === 'acl_loan') { } else if(aclName === 'acl_loan') {
message += getLangText('I loan'); message += getLangText('I loan');
} else if(aclName === 'acl_loan_request') {
message += getLangText('I request to loan');
} else if(aclName === 'acl_share') { } else if(aclName === 'acl_share') {
message += getLangText('I share'); message += getLangText('I share');
} else { } else {
@ -34,7 +36,7 @@ export function getAclFormMessage(aclName, entities, senderName) {
if(aclName === 'acl_transfer' || aclName === 'acl_loan' || aclName === 'acl_consign') { if(aclName === 'acl_transfer' || aclName === 'acl_loan' || aclName === 'acl_consign') {
message += getLangText('to you'); message += getLangText('to you');
} else if(aclName === 'acl_unconsign') { } else if(aclName === 'acl_unconsign' || aclName === 'acl_loan_request') {
message += getLangText('from you'); message += getLangText('from you');
} else if(aclName === 'acl_share') { } else if(aclName === 'acl_share') {
message += getLangText('with you'); message += getLangText('with you');

View File

@ -73,7 +73,7 @@
"raven-js": "^1.1.19", "raven-js": "^1.1.19",
"react": "^0.13.2", "react": "^0.13.2",
"react-bootstrap": "^0.24.3", "react-bootstrap": "^0.24.3",
"react-datepicker": "~0.8.0", "react-datepicker": "^0.12.0",
"react-progressbar": "^1.1.0", "react-progressbar": "^1.1.0",
"react-router": "^0.13.3", "react-router": "^0.13.3",
"react-router-bootstrap": "~0.16.0", "react-router-bootstrap": "~0.16.0",

View File

@ -152,11 +152,11 @@ span.ascribe-accordion-list-table-toggle {
} }
} }
.request-action-batch { .request-action-badge {
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 0px; right: 0px;
color: #666; color: $ascribe-color-green;
font-size: 1.2em; font-size: 1.2em;
padding: 0.3em; padding: 0.3em;
} }

View File

@ -145,8 +145,15 @@
display: inline-block; display: inline-block;
width: 100%; width: 100%;
border-top: 1px solid rgba(0,0,0,.05); border-top: 1px solid rgba(0,0,0,.05);
padding: .5em 1.5em .5em 1.5em; padding: .5em 1.5em .5em 1.5em;
}
.ascribe-checkbox-wrapper{
.checkbox > span {color: black;}
}
.ascribe-settings-property-collapsible-toggle, .ascribe-checkbox-wrapper {
cursor:pointer; cursor:pointer;
@ -196,4 +203,10 @@
font-size: 20px; font-size: 20px;
color: rgba(2, 182, 163, 1); color: rgba(2, 182, 163, 1);
} }
}
.ascribe-checkbox-badge{
> span > span {
margin-top: 0;
}
} }

View File

@ -402,17 +402,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 { .disable-select {
-webkit-user-select: none; -webkit-user-select: none;

View File

@ -1,4 +1,5 @@
@import 'landing'; @import 'landing';
@import 'rating';
.ascribe-prize-app { .ascribe-prize-app {
border-radius: 0; border-radius: 0;

View 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;
}