1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-23 01:39:36 +01:00

Merged in AD-598-register-action-switches (pull request #14)

Ad 598 register action switches
This commit is contained in:
TimDaubenschuetz 2015-07-28 16:36:57 +02:00
commit 78049b448e
9 changed files with 132 additions and 46 deletions

View File

@ -13,7 +13,7 @@ class UserActions {
} }
fetchCurrentUser() { fetchCurrentUser() {
UserFetcher.fetchOne() return UserFetcher.fetchOne()
.then((res) => { .then((res) => {
this.actions.updateCurrentUser(res.users[0]); this.actions.updateCurrentUser(res.users[0]);
}) })

View File

@ -25,7 +25,8 @@ let LoginForm = React.createClass({
headerMessage: React.PropTypes.string, headerMessage: React.PropTypes.string,
submitMessage: React.PropTypes.string, submitMessage: React.PropTypes.string,
redirectOnLoggedIn: React.PropTypes.bool, redirectOnLoggedIn: React.PropTypes.bool,
redirectOnLoginSuccess: React.PropTypes.bool redirectOnLoginSuccess: React.PropTypes.bool,
onLogin: React.PropTypes.func
}, },
mixins: [Router.Navigation], mixins: [Router.Navigation],
@ -70,18 +71,29 @@ let LoginForm = React.createClass({
// The easiest way to check if the user was successfully logged in is to fetch the user // The easiest way to check if the user was successfully logged in is to fetch the user
// in the user store (which is obviously only possible if the user is logged in), since // in the user store (which is obviously only possible if the user is logged in), since
// register_piece is listening to the changes of the user_store. // register_piece is listening to the changes of the user_store.
UserActions.fetchCurrentUser(); UserActions.fetchCurrentUser()
.then(() => {
if(this.props.redirectOnLoginSuccess) {
/* Taken from http://stackoverflow.com/a/14916411 */
/*
We actually have to trick the Browser into showing the "save password" dialog
as Chrome expects the login page to be reloaded after the login.
Users on Stack Overflow claim this is a bug in chrome and should be fixed in the future.
Until then, we redirect the HARD way, but reloading the whole page using window.location
*/
window.location = AppConstants.baseUrl + 'collection';
} else if(this.props.onLogin) {
// In some instances we want to give a callback to an outer container,
// to show that the one login action the user triggered actually went through.
// We can not do this by listening on a store's state as it wouldn't really tell us
// if the user did log in or was just fetching the user's data again
this.props.onLogin();
}
})
.catch((err) => {
console.logGlobal(err);
});
/* Taken from http://stackoverflow.com/a/14916411 */
/*
We actually have to trick the Browser into showing the "save password" dialog
as Chrome expects the login page to be reloaded after the login.
Users on Stack Overflow claim this is a bug in chrome and should be fixed in the future.
Until then, we redirect the HARD way, but reloading the whole page using window.location
*/
if(this.props.redirectOnLoginSuccess) {
window.location = AppConstants.baseUrl + 'collection';
}
}, },
render() { render() {

View File

@ -21,8 +21,9 @@ let RegisterPieceForm = React.createClass({
headerMessage: React.PropTypes.string, headerMessage: React.PropTypes.string,
submitMessage: React.PropTypes.string, submitMessage: React.PropTypes.string,
handleSuccess: React.PropTypes.func, handleSuccess: React.PropTypes.func,
isFineUploaderEditable: React.PropTypes.bool, isFineUploaderActive: React.PropTypes.bool,
children: React.PropTypes.element children: React.PropTypes.element,
onLoggedOut: React.PropTypes.func
}, },
getDefaultProps() { getDefaultProps() {
@ -94,7 +95,8 @@ let RegisterPieceForm = React.createClass({
submitKey={this.submitKey} submitKey={this.submitKey}
setIsUploadReady={this.setIsUploadReady} setIsUploadReady={this.setIsUploadReady}
isReadyForFormSubmission={this.isReadyForFormSubmission} isReadyForFormSubmission={this.isReadyForFormSubmission}
editable={this.props.isFineUploaderEditable}/> isFineUploaderActive={this.props.isFineUploaderActive}
onLoggedOut={this.props.onLoggedOut}/>
</Property> </Property>
<Property <Property
name='artist_name' name='artist_name'
@ -133,10 +135,11 @@ let FileUploader = React.createClass({
submitKey: React.PropTypes.func, submitKey: React.PropTypes.func,
isReadyForFormSubmission: React.PropTypes.func, isReadyForFormSubmission: React.PropTypes.func,
onClick: React.PropTypes.func, onClick: React.PropTypes.func,
// editable is used to lock react fine uploader in case // isFineUploaderActive is used to lock react fine uploader in case
// a user is actually not logged in already to prevent him from droping files // a user is actually not logged in already to prevent him from droping files
// before login in // before login in
editable: React.PropTypes.bool isFineUploaderActive: React.PropTypes.bool,
onLoggedOut: React.PropTypes.func
}, },
render() { render() {
@ -158,7 +161,7 @@ let FileUploader = React.createClass({
setIsUploadReady={this.props.setIsUploadReady} setIsUploadReady={this.props.setIsUploadReady}
isReadyForFormSubmission={this.props.isReadyForFormSubmission} isReadyForFormSubmission={this.props.isReadyForFormSubmission}
areAssetsDownloadable={false} areAssetsDownloadable={false}
areAssetsEditable={this.props.editable} areAssetsEditable={this.props.isFineUploaderActive}
signature={{ signature={{
endpoint: AppConstants.serverUrl + 's3/signature/', endpoint: AppConstants.serverUrl + 's3/signature/',
customHeaders: { customHeaders: {
@ -172,7 +175,8 @@ let FileUploader = React.createClass({
customHeaders: { customHeaders: {
'X-CSRFToken': getCookie(AppConstants.csrftoken) 'X-CSRFToken': getCookie(AppConstants.csrftoken)
} }
}}/> }}
onInactive={this.props.onLoggedOut}/>
); );
} }
}); });

View File

@ -17,7 +17,7 @@ let SlidesContainer = React.createClass({
getInitialState() { getInitialState() {
// handle queryParameters // handle queryParameters
let queryParams = this.getQuery(); let queryParams = this.getQuery();
let slideNum = 0; let slideNum = -1;
if(queryParams && 'slide_num' in queryParams) { if(queryParams && 'slide_num' in queryParams) {
slideNum = parseInt(queryParams.slide_num, 10); slideNum = parseInt(queryParams.slide_num, 10);
@ -26,17 +26,12 @@ let SlidesContainer = React.createClass({
return { return {
containerWidth: 0, containerWidth: 0,
slideNum: slideNum slideNum: slideNum,
historyLength: window.history.length
}; };
}, },
componentDidMount() { componentDidMount() {
// check if slide_num was defined, and if not then default to 0
let queryParams = this.getQuery();
if(!('slide_num' in queryParams)) {
this.replaceWith(this.getPathname(), null, {slide_num: 0});
}
// init container width // init container width
this.handleContainerResize(); this.handleContainerResize();
@ -45,6 +40,12 @@ let SlidesContainer = React.createClass({
window.addEventListener('resize', this.handleContainerResize); window.addEventListener('resize', this.handleContainerResize);
}, },
componentDidUpdate() {
// check if slide_num was defined, and if not then default to 0
let queryParams = this.getQuery();
this.setSlideNum(queryParams.slide_num);
},
componentWillUnmount() { componentWillUnmount() {
window.removeEventListener('resize', this.handleContainerResize); window.removeEventListener('resize', this.handleContainerResize);
}, },
@ -58,9 +59,45 @@ let SlidesContainer = React.createClass({
// We let every one from the outsite set the page number of the slider, // 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. // though only if the slideNum is actually in the range of our children-list.
setSlideNum(slideNum) { setSlideNum(slideNum) {
if(slideNum < 0 || slideNum < React.Children.count(this.props.children)) {
// slideNum can in some instances be not a number,
// therefore we have to parse it to one and make sure that its not NaN
slideNum = parseInt(slideNum, 10);
// if slideNum is not a number (even after we parsed it to one) and there has
// never been a transition to another slide (this.state.slideNum ==== -1 indicates that)
// then we want to "replace" (in this case append) the current url with ?slide_num=0
if(isNaN(slideNum) && this.state.slideNum === -1) {
slideNum = 0;
this.replaceWith(this.getPathname(), null, {slide_num: slideNum}); this.replaceWith(this.getPathname(), null, {slide_num: slideNum});
this.setState({slideNum: slideNum});
return;
// slideNum always represents the future state. So if slideNum and
// this.state.slideNum are equal, there is no sense in redirecting
} else if(slideNum === this.state.slideNum) {
return;
// 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)) {
if(slideNum !== this.state.slideNum - 1) {
// Bootstrapping the component, getInitialState is called once to save
// the tabs history length.
// In order to know if we already pushed a new state on the history stack or not,
// we're comparing the old history length with the new one and if it didn't change then
// we push a new state on it ONCE (ever).
// Otherwise, we're able to use the browsers history.forward() method
// to keep the stack clean
if(this.state.historyLength === window.history.length) {
this.transitionTo(this.getPathname(), null, {slide_num: slideNum});
} else {
window.history.forward();
}
}
this.setState({ this.setState({
slideNum: slideNum slideNum: slideNum
}); });

View File

@ -18,6 +18,7 @@ let FileDragAndDrop = React.createClass({
onDragLeave: React.PropTypes.func, onDragLeave: React.PropTypes.func,
onDragOver: React.PropTypes.func, onDragOver: React.PropTypes.func,
onDragEnd: React.PropTypes.func, onDragEnd: React.PropTypes.func,
onInactive: React.PropTypes.func,
filesToUpload: React.PropTypes.array, filesToUpload: React.PropTypes.array,
handleDeleteFile: React.PropTypes.func, handleDeleteFile: React.PropTypes.func,
handleCancelFile: React.PropTypes.func, handleCancelFile: React.PropTypes.func,
@ -72,6 +73,15 @@ let FileDragAndDrop = React.createClass({
event.stopPropagation(); event.stopPropagation();
let files; let files;
if(this.props.dropzoneInactive) {
// if there is a handle function for doing stuff
// when the dropzone is inactive, then call it
if(this.props.onInactive) {
this.props.onInactive();
}
return;
}
// handle Drag and Drop // handle Drag and Drop
if(event.dataTransfer && event.dataTransfer.files.length > 0) { if(event.dataTransfer && event.dataTransfer.files.length > 0) {
files = event.dataTransfer.files; files = event.dataTransfer.files;
@ -113,10 +123,15 @@ let FileDragAndDrop = React.createClass({
this.props.handleResumeFile(fileId); this.props.handleResumeFile(fileId);
}, },
handleOnClick(event) { handleOnClick() {
// when multiple is set to false and the user already uploaded a piece, // when multiple is set to false and the user already uploaded a piece,
// do not propagate event // do not propagate event
if(this.props.dropzoneInactive) { if(this.props.dropzoneInactive) {
// if there is a handle function for doing stuff
// when the dropzone is inactive, then call it
if(this.props.onInactive) {
this.props.onInactive();
}
return; return;
} }

View File

@ -95,7 +95,8 @@ var ReactS3FineUploader = React.createClass({
isReadyForFormSubmission: React.PropTypes.func, isReadyForFormSubmission: React.PropTypes.func,
areAssetsDownloadable: React.PropTypes.bool, areAssetsDownloadable: React.PropTypes.bool,
areAssetsEditable: React.PropTypes.bool, areAssetsEditable: React.PropTypes.bool,
defaultErrorMessage: React.PropTypes.string defaultErrorMessage: React.PropTypes.string,
onInactive: React.PropTypes.func
}, },
getDefaultProps() { getDefaultProps() {
@ -560,7 +561,8 @@ var ReactS3FineUploader = React.createClass({
multiple={this.props.multiple} multiple={this.props.multiple}
areAssetsDownloadable={this.props.areAssetsDownloadable} areAssetsDownloadable={this.props.areAssetsDownloadable}
areAssetsEditable={this.props.areAssetsEditable} areAssetsEditable={this.props.areAssetsEditable}
dropzoneInactive={!this.props.areAssetsEditable || !this.props.multiple && this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0} /> dropzoneInactive={!this.props.areAssetsEditable || !this.props.multiple && this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0}
onInactive={this.props.onInactive}/>
</div> </div>
); );
} }

View File

@ -14,7 +14,8 @@ let LoginContainer = React.createClass({
propTypes: { propTypes: {
message: React.PropTypes.string, message: React.PropTypes.string,
redirectOnLoggedIn: React.PropTypes.bool, redirectOnLoggedIn: React.PropTypes.bool,
redirectOnLoginSuccess: React.PropTypes.bool redirectOnLoginSuccess: React.PropTypes.bool,
onLogin: React.PropTypes.func
}, },
getDefaultProps() { getDefaultProps() {
@ -31,7 +32,8 @@ let LoginContainer = React.createClass({
<LoginForm <LoginForm
redirectOnLoggedIn={this.props.redirectOnLoggedIn} redirectOnLoggedIn={this.props.redirectOnLoggedIn}
redirectOnLoginSuccess={this.props.redirectOnLoginSuccess} redirectOnLoginSuccess={this.props.redirectOnLoginSuccess}
message={this.props.message} /> message={this.props.message}
onLogin={this.props.onLogin}/>
<div className="ascribe-login-text"> <div className="ascribe-login-text">
{getLangText('Not an ascribe user')}&#63; <Link to="signup">{getLangText('Sign up')}...</Link><br/> {getLangText('Not an ascribe user')}&#63; <Link to="signup">{getLangText('Sign up')}...</Link><br/>
{getLangText('Forgot my password')}&#63; <Link to="password_reset">{getLangText('Rescue me')}...</Link> {getLangText('Forgot my password')}&#63; <Link to="password_reset">{getLangText('Rescue me')}...</Link>

View File

@ -59,7 +59,7 @@ let RegisterPiece = React.createClass( {
PieceListStore.getState(), PieceListStore.getState(),
{ {
selectedLicense: 0, selectedLicense: 0,
isFineUploaderEditable: false isFineUploaderActive: false
}); });
}, },
@ -82,14 +82,10 @@ let RegisterPiece = React.createClass( {
onChange(state) { onChange(state) {
this.setState(state); this.setState(state);
// once the currentUser object from UserStore is defined (eventually the user was transitioned if(this.state.currentUser && this.state.currentUser.email) {
// to the login form via the slider and successfully logged in), we can direct him back to the
// register_piece slide
if(state.currentUser && state.currentUser.email || this.state.currentUser && this.state.currentUser.email) {
this.refs.slidesContainer.setSlideNum(0);
// we should also make the fineuploader component editable again // we should also make the fineuploader component editable again
this.setState({ this.setState({
isFineUploaderEditable: true isFineUploaderActive: true
}); });
} }
}, },
@ -105,7 +101,8 @@ let RegisterPiece = React.createClass( {
this.state.pageSize, this.state.pageSize,
this.state.searchTerm, this.state.searchTerm,
this.state.orderBy, this.state.orderBy,
this.state.orderAsc); this.state.orderAsc
);
this.transitionTo('piece', {pieceId: response.piece.id}); this.transitionTo('piece', {pieceId: response.piece.id});
}, },
@ -160,11 +157,25 @@ let RegisterPiece = React.createClass( {
changeSlide() { changeSlide() {
// only transition to the login store, if user is not logged in // only transition to the login store, if user is not logged in
// ergo the currentUser object is not properly defined // ergo the currentUser object is not properly defined
if(!this.state.currentUser.email) { if(this.state.currentUser && !this.state.currentUser.email) {
this.refs.slidesContainer.setSlideNum(1); this.refs.slidesContainer.setSlideNum(1);
} }
}, },
// basically redirects to the second slide (index: 1), when the user is not logged in
onLoggedOut() {
this.refs.slidesContainer.setSlideNum(1);
},
onLogin() {
// once the currentUser object from UserStore is defined (eventually the user was transitioned
// to the login form via the slider and successfully logged in), we can direct him back to the
// register_piece slide
if(this.state.currentUser && this.state.currentUser.email) {
window.history.back();
}
},
render() { render() {
return ( return (
<SlidesContainer ref="slidesContainer"> <SlidesContainer ref="slidesContainer">
@ -175,8 +186,9 @@ let RegisterPiece = React.createClass( {
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}> <Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
<RegisterPieceForm <RegisterPieceForm
{...this.props} {...this.props}
isFineUploaderEditable={this.state.isFineUploaderEditable} isFineUploaderActive={this.state.isFineUploaderActive}
handleSuccess={this.handleSuccess}> handleSuccess={this.handleSuccess}
onLoggedOut={this.onLoggedOut}>
{this.props.children} {this.props.children}
{this.getLicenses()} {this.getLicenses()}
{this.getSpecifyEditions()} {this.getSpecifyEditions()}
@ -188,7 +200,8 @@ let RegisterPiece = React.createClass( {
<LoginContainer <LoginContainer
message={getLangText('Please login before ascribing your work%s', '...')} message={getLangText('Please login before ascribing your work%s', '...')}
redirectOnLoggedIn={false} redirectOnLoggedIn={false}
redirectOnLoginSuccess={false}/> redirectOnLoginSuccess={false}
onLogin={this.onLogin}/>
</div> </div>
</SlidesContainer> </SlidesContainer>
); );

View File

@ -43,6 +43,7 @@ html {
.ascribe-default-app { .ascribe-default-app {
max-width: 90%; max-width: 90%;
padding-top: 70px; padding-top: 70px;
overflow-x: hidden;
} }
hr { hr {