mirror of
https://github.com/ascribe/onion.git
synced 2024-12-23 01:39:36 +01:00
Merge branch 'AD-613-cyland-white-label-page' of bitbucket.org:ascribe/onion into AD-613-cyland-white-label-page
This commit is contained in:
commit
7458bdcb92
@ -28,7 +28,7 @@ let AccordionList = React.createClass({
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={this.props.className + ' ascribe-accordion-list-loading'}>
|
||||
<div className={this.props.className + ' ascribe-loading-position'}>
|
||||
{this.props.loadingElement}
|
||||
</div>
|
||||
);
|
||||
|
@ -11,7 +11,6 @@ let Navigation = Router.Navigation;
|
||||
|
||||
let SlidesContainer = React.createClass({
|
||||
propTypes: {
|
||||
breadcrumbs: React.PropTypes.arrayOf(React.PropTypes.string),
|
||||
children: React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
forwardProcess: React.PropTypes.bool.isRequired
|
||||
},
|
||||
@ -22,15 +21,22 @@ let SlidesContainer = React.createClass({
|
||||
// handle queryParameters
|
||||
let queryParams = this.getQuery();
|
||||
let slideNum = -1;
|
||||
let startFrom = -1;
|
||||
|
||||
if(queryParams && 'slide_num' in queryParams) {
|
||||
slideNum = parseInt(queryParams.slide_num, 10);
|
||||
}
|
||||
// if slide_num is not set, this will be done in componentDidMount
|
||||
|
||||
// the query param 'start_from' removes all slide children before the respective number
|
||||
if(queryParams && 'start_from' in queryParams) {
|
||||
startFrom = parseInt(queryParams.start_from, 10);
|
||||
}
|
||||
|
||||
return {
|
||||
slideNum,
|
||||
startFrom,
|
||||
containerWidth: 0,
|
||||
slideNum: slideNum,
|
||||
historyLength: window.history.length
|
||||
};
|
||||
},
|
||||
@ -55,9 +61,23 @@ let SlidesContainer = React.createClass({
|
||||
window.addEventListener('resize', this.handleContainerResize);
|
||||
},
|
||||
|
||||
componentDidUpdate() {
|
||||
// check if slide_num was defined, and if not then default to 0
|
||||
componentWillReceiveProps() {
|
||||
let queryParams = this.getQuery();
|
||||
|
||||
// also check if start_from was updated
|
||||
// This applies for example when the user tries to submit a already existing piece
|
||||
// (starting from slide 1 for example) and then clicking on + NEW WORK
|
||||
if(queryParams && !('start_from' in queryParams)) {
|
||||
this.setState({
|
||||
startFrom: -1
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
componentDidUpdate() {
|
||||
let queryParams = this.getQuery();
|
||||
|
||||
// check if slide_num was defined, and if not then default to 0
|
||||
this.setSlideNum(queryParams.slide_num);
|
||||
},
|
||||
|
||||
@ -72,6 +92,12 @@ let SlidesContainer = React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
// When the start_from parameter is used, this.setSlideNum can not simply be used anymore.
|
||||
nextSlide() {
|
||||
let nextSlide = this.state.slideNum + 1;
|
||||
this.setSlideNum(nextSlide);
|
||||
},
|
||||
|
||||
// We let every one from the outsite set the page number of the slider,
|
||||
// though only if the slideNum is actually in the range of our children-list.
|
||||
setSlideNum(slideNum) {
|
||||
@ -102,7 +128,7 @@ let SlidesContainer = React.createClass({
|
||||
|
||||
// if slideNum is within the range of slides and none of the previous cases
|
||||
// where matched, we can actually do transitions
|
||||
} else if(slideNum >= 0 || slideNum < React.Children.count(this.props.children)) {
|
||||
} else if(slideNum >= 0 || slideNum < this.customChildrenCount()) {
|
||||
|
||||
if(slideNum !== this.state.slideNum - 1) {
|
||||
// Bootstrapping the component, getInitialState is called once to save
|
||||
@ -135,15 +161,45 @@ let SlidesContainer = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
renderBreadCrumbs() {
|
||||
if (this.props.breadcrumbs) {
|
||||
let numSlides = this.props.breadcrumbs.length;
|
||||
extractBreadcrumbs() {
|
||||
let breadcrumbs = [];
|
||||
|
||||
ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||
if(i >= this.state.startFrom) {
|
||||
breadcrumbs.push(child.props['data-slide-title']);
|
||||
}
|
||||
});
|
||||
|
||||
return breadcrumbs;
|
||||
},
|
||||
|
||||
customChildrenCount() {
|
||||
let count = 0;
|
||||
React.Children.forEach(this.props.children, (child, i) => {
|
||||
if(i >= this.state.startFrom) {
|
||||
count++;
|
||||
}
|
||||
});
|
||||
|
||||
return count;
|
||||
},
|
||||
|
||||
renderBreadcrumbs() {
|
||||
let breadcrumbs = this.extractBreadcrumbs();
|
||||
let numOfChildren = this.customChildrenCount();
|
||||
|
||||
// check if every child/slide has a title,
|
||||
// otherwise do not display the breadcrumbs at all
|
||||
// Also, if there is only one child, do not display the breadcrumbs
|
||||
if(breadcrumbs.length === numOfChildren && breadcrumbs.length > 1 && numOfChildren > 1) {
|
||||
let numSlides = breadcrumbs.length;
|
||||
let columnWidth = Math.floor(12 / numSlides);
|
||||
|
||||
return (
|
||||
<div className="row" style={{width: this.state.containerWidth}}>
|
||||
<div className="col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1 col-xs-12">
|
||||
<div className="no-margin row ascribe-breadcrumb-container">
|
||||
{this.props.breadcrumbs.map((breadcrumb, i) => {
|
||||
{breadcrumbs.map((breadcrumb, i) => {
|
||||
return (
|
||||
<Col
|
||||
className="no-padding"
|
||||
@ -151,7 +207,7 @@ let SlidesContainer = React.createClass({
|
||||
key={i}>
|
||||
<div className="ascribe-breadcrumb">
|
||||
<a className={this.state.slideNum === i ? 'active' : ''}>
|
||||
{this.props.breadcrumbs[i]}
|
||||
{breadcrumb}
|
||||
<span className={i === numSlides - 1 ? 'invisible' : '' + 'pull-right glyphicon glyphicon-chevron-right'}>
|
||||
</span>
|
||||
</a>
|
||||
@ -163,14 +219,19 @@ let SlidesContainer = React.createClass({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
// Since we need to give the slides a width, we need to call ReactAddons.addons.cloneWithProps
|
||||
// Also, a key is nice to have!
|
||||
renderChildren() {
|
||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||
// since the default parameter of startFrom is -1, we do not need to check
|
||||
// if its actually present in the url bar, as it will just not match
|
||||
|
||||
if(i >= this.state.startFrom) {
|
||||
return ReactAddons.addons.cloneWithProps(child, {
|
||||
className: 'ascribe-slide',
|
||||
style: {
|
||||
@ -178,6 +239,10 @@ let SlidesContainer = React.createClass({
|
||||
},
|
||||
key: i
|
||||
});
|
||||
} else {
|
||||
// Abortions are bad mkay
|
||||
return null;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@ -186,11 +251,11 @@ let SlidesContainer = React.createClass({
|
||||
<div
|
||||
className="container ascribe-sliding-container-wrapper"
|
||||
ref="containerWrapper">
|
||||
{this.renderBreadCrumbs()}
|
||||
{this.renderBreadcrumbs()}
|
||||
<div
|
||||
className="container ascribe-sliding-container"
|
||||
style={{
|
||||
width: this.state.containerWidth * React.Children.count(this.props.children),
|
||||
width: this.state.containerWidth * this.customChildrenCount(),
|
||||
transform: 'translateX(' + (-1) * this.state.containerWidth * this.state.slideNum + 'px)'
|
||||
}}>
|
||||
<div className="row">
|
||||
|
@ -138,7 +138,7 @@ let PieceList = React.createClass({
|
||||
this.transitionTo(this.getPathname(), {page: 1});
|
||||
},
|
||||
|
||||
applyOrderBy(orderBy, orderAsc) {
|
||||
applyOrderBy(orderBy) {
|
||||
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
|
||||
orderBy, this.state.orderAsc, this.state.filterBy);
|
||||
},
|
||||
|
@ -3,18 +3,12 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Moment from 'moment';
|
||||
import ButtonLink from 'react-router-bootstrap/lib/ButtonLink';
|
||||
|
||||
import WhitelabelActions from '../../../../../../actions/whitelabel_actions';
|
||||
import WhitelabelStore from '../../../../../../stores/whitelabel_store';
|
||||
|
||||
import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
|
||||
import LoanForm from '../../../../../ascribe_forms/form_loan';
|
||||
|
||||
import ApiUrls from '../../../../../../constants/api_urls';
|
||||
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
import { getAclFormMessage } from '../../../../../../utils/form_utils';
|
||||
|
||||
let CylandSubmitButton = React.createClass({
|
||||
propTypes: {
|
||||
@ -41,36 +35,25 @@ let CylandSubmitButton = React.createClass({
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
getSubmitButton() {
|
||||
render() {
|
||||
let piece = this.props.piece;
|
||||
let startFrom = 1;
|
||||
|
||||
if(piece && piece.extra_data && Object.keys(piece.extra_data).length > 0) {
|
||||
startFrom = 2;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
<ButtonLink
|
||||
to="register_piece"
|
||||
query={{
|
||||
'slide_num': 0,
|
||||
'start_from': startFrom,
|
||||
'piece_id': this.props.piece.id
|
||||
}}
|
||||
className={classNames('btn', 'btn-default', 'btn-xs', this.props.className)}>
|
||||
{getLangText('Submit to Cyland')}
|
||||
</button>
|
||||
);
|
||||
},
|
||||
|
||||
render() {
|
||||
let today = new Moment();
|
||||
let loanEndDate = new Moment();
|
||||
loanEndDate.add(1000, 'years');
|
||||
|
||||
return (
|
||||
<ModalWrapper
|
||||
trigger={this.getSubmitButton()}
|
||||
handleSuccess={this.props.handleSuccess}
|
||||
title={getLangText('Submit to Cyland')}>
|
||||
<LoanForm
|
||||
message={getAclFormMessage('acl_loan', '\"' + this.props.piece.title + '\"', this.props.username)}
|
||||
id={{piece_id: this.props.piece.id}}
|
||||
url={ApiUrls.ownership_loans_pieces}
|
||||
email={this.state.whitelabel.user}
|
||||
gallery="Cyland Archive"
|
||||
startdate={today}
|
||||
enddate={loanEndDate}
|
||||
showPersonalMessage={false}
|
||||
handleSuccess={this.props.handleSuccess}/>
|
||||
</ModalWrapper>
|
||||
</ButtonLink>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -20,11 +20,8 @@ import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_de
|
||||
import DetailProperty from '../../../../../ascribe_detail/detail_property';
|
||||
|
||||
import { mergeOptions } from '../../../../../../utils/general_utils';
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
|
||||
/**
|
||||
* This is the component that implements resource/data specific functionality
|
||||
*/
|
||||
|
||||
let CylandPieceContainer = React.createClass({
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
@ -106,10 +103,11 @@ let CylandPieceDetails = React.createClass({
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
<Form ref='form'>
|
||||
{Object.keys(this.props.piece.extra_data).map((data) => {
|
||||
{Object.keys(this.props.piece.extra_data).map((data, i) => {
|
||||
let label = data.replace('_', ' ');
|
||||
return (
|
||||
<Property
|
||||
key={i}
|
||||
name={data}
|
||||
label={label}
|
||||
editable={false}>
|
||||
|
@ -24,7 +24,7 @@ let CylandAdditionalDataForm = React.createClass({
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
isUploadReady: false
|
||||
isUploadReady: true
|
||||
};
|
||||
},
|
||||
|
||||
@ -119,7 +119,11 @@ let CylandAdditionalDataForm = React.createClass({
|
||||
</Form>
|
||||
);
|
||||
} else {
|
||||
return <span>First register the piece.</span>;
|
||||
return (
|
||||
<div className="ascribe-loading-position">
|
||||
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -40,9 +40,10 @@ import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
import { getAclFormMessage } from '../../../../../utils/form_utils';
|
||||
|
||||
|
||||
let CylandRegisterPiece = React.createClass({
|
||||
|
||||
mixins: [Router.Navigation],
|
||||
mixins: [Router.Navigation, Router.State],
|
||||
|
||||
getInitialState(){
|
||||
return mergeOptions(
|
||||
@ -63,6 +64,12 @@ let CylandRegisterPiece = React.createClass({
|
||||
WhitelabelStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
WhitelabelActions.fetchWhitelabel();
|
||||
|
||||
let queryParams = this.getQuery();
|
||||
|
||||
if(queryParams && 'piece_id' in queryParams) {
|
||||
PieceActions.fetchOne(queryParams.piece_id);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -85,24 +92,32 @@ let CylandRegisterPiece = React.createClass({
|
||||
|
||||
handleRegisterSuccess(response){
|
||||
|
||||
this.refreshPieceList();
|
||||
|
||||
// also start loading the piece for the next step
|
||||
if(response && response.piece) {
|
||||
PieceActions.updatePiece(response.piece);
|
||||
}
|
||||
|
||||
this.refs.slidesContainer.setSlideNum(1);
|
||||
this.refs.slidesContainer.nextSlide();
|
||||
},
|
||||
|
||||
handleAdditionalDataSuccess() {
|
||||
this.refs.slidesContainer.setSlideNum(2);
|
||||
this.refreshPieceList();
|
||||
this.refs.slidesContainer.nextSlide();
|
||||
},
|
||||
|
||||
handleLoanSuccess(response) {
|
||||
let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
// once the user was able to register + loan a piece successfully, we need to make sure to keep
|
||||
// the piece list up to date
|
||||
this.refreshPieceList();
|
||||
|
||||
PieceActions.fetchOne(this.state.piece.id);
|
||||
this.transitionTo('piece', {pieceId: this.state.piece.id});
|
||||
},
|
||||
|
||||
refreshPieceList() {
|
||||
PieceListActions.fetchPieceList(
|
||||
this.state.page,
|
||||
this.state.pageSize,
|
||||
@ -111,9 +126,6 @@ let CylandRegisterPiece = React.createClass({
|
||||
this.state.orderAsc,
|
||||
this.state.filterBy
|
||||
);
|
||||
|
||||
PieceActions.fetchOne(this.state.piece.id);
|
||||
this.transitionTo('piece', {pieceId: this.state.piece.id});
|
||||
},
|
||||
|
||||
changeSlide() {
|
||||
@ -138,9 +150,8 @@ let CylandRegisterPiece = React.createClass({
|
||||
return (
|
||||
<SlidesContainer
|
||||
ref="slidesContainer"
|
||||
breadcrumbs={['Register work', 'Additional details', 'Loan']}
|
||||
forwardProcess={true}>
|
||||
<div>
|
||||
<div data-slide-title="Register work">
|
||||
<Row className="no-margin">
|
||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||
<RegisterPieceForm
|
||||
@ -167,7 +178,7 @@ let CylandRegisterPiece = React.createClass({
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div>
|
||||
<div data-slide-title="Additional details">
|
||||
<Row className="no-margin">
|
||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||
<CylandAdditionalDataForm
|
||||
@ -176,7 +187,7 @@ let CylandRegisterPiece = React.createClass({
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div>
|
||||
<div data-slide-title="Loan">
|
||||
<Row className="no-margin">
|
||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||
<LoanForm
|
||||
|
@ -65,7 +65,7 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
a {
|
||||
a:not(.btn) {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
@ -79,11 +79,6 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
|
||||
}
|
||||
}
|
||||
|
||||
.ascribe-accordion-list-loading {
|
||||
padding-top: 30%;
|
||||
padding-bottom: 30%;
|
||||
}
|
||||
|
||||
.ascribe-accordion-list-loading img {
|
||||
display: block;
|
||||
margin: auto;
|
||||
|
@ -428,3 +428,9 @@ hr {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.ascribe-loading-position {
|
||||
padding-top: 30%;
|
||||
padding-bottom: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user