Merge pull request #4784 from benjiwheeler/fix-save-on-see-project-page
Fix auto-save when clicking See Project Page
This commit is contained in:
4 files changed
+236
-54
No files matched your search
@@ -1,50 +0,0 @@
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import React from 'react';
|
||||
|
||||
const ConfirmReplaceHOC = function (WrappedComponent) {
|
||||
class ConfirmReplaceProject extends React.PureComponent {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
bindAll(this, [
|
||||
'confirmReadyToReplaceProject'
|
||||
]);
|
||||
}
|
||||
|
||||
confirmReadyToReplaceProject (message) {
|
||||
let readyToReplaceProject = true;
|
||||
if (this.props.projectChanged && !this.props.canCreateNew) {
|
||||
readyToReplaceProject = confirm(message); // eslint-disable-line no-alert
|
||||
}
|
||||
return readyToReplaceProject;
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
/* eslint-disable no-unused-vars */
|
||||
projectChanged,
|
||||
/* eslint-enable no-unused-vars */
|
||||
...props
|
||||
} = this.props;
|
||||
return (<WrappedComponent
|
||||
confirmReadyToReplaceProject={this.confirmReadyToReplaceProject}
|
||||
{...props}
|
||||
/>);
|
||||
}
|
||||
}
|
||||
|
||||
ConfirmReplaceProject.propTypes = {
|
||||
canCreateNew: PropTypes.bool,
|
||||
projectChanged: PropTypes.bool
|
||||
};
|
||||
|
||||
const _mapStateToProps = state => ({
|
||||
projectChanged: state.scratchGui.projectChanged
|
||||
});
|
||||
|
||||
return connect(_mapStateToProps)(ConfirmReplaceProject);
|
||||
};
|
||||
|
||||
export default ConfirmReplaceHOC;
|
||||
@@ -28,7 +28,7 @@ import LoginDropdown from './login-dropdown.jsx';
|
||||
import SB3Downloader from '../../containers/sb3-downloader.jsx';
|
||||
import DeletionRestorer from '../../containers/deletion-restorer.jsx';
|
||||
import TurboMode from '../../containers/turbo-mode.jsx';
|
||||
import ConfirmReplaceHOC from './confirm-replace-hoc.jsx';
|
||||
import MenuBarHOC from '../../containers/menu-bar-hoc.jsx';
|
||||
|
||||
import {openTipsLibrary} from '../../reducers/modals';
|
||||
import {setPlayer} from '../../reducers/mode';
|
||||
@@ -192,8 +192,8 @@ class MenuBar extends React.Component {
|
||||
this.props.onRequestCloseFile();
|
||||
}
|
||||
handleClickSeeCommunity (waitForUpdate) {
|
||||
if (this.props.canSave && this.props.projectChanged) { // save before transitioning to project page
|
||||
this.props.autoUpdateProject();
|
||||
if (this.props.shouldSaveBeforeTransition()) {
|
||||
this.props.autoUpdateProject(); // save before transitioning to project page
|
||||
waitForUpdate(true); // queue the transition to project page
|
||||
} else {
|
||||
waitForUpdate(false); // immediately transition to project page
|
||||
@@ -705,6 +705,7 @@ MenuBar.propTypes = {
|
||||
canSave: PropTypes.bool,
|
||||
canShare: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
confirmReadyToReplaceProject: PropTypes.func,
|
||||
editMenuOpen: PropTypes.bool,
|
||||
enableCommunity: PropTypes.bool,
|
||||
fileMenuOpen: PropTypes.bool,
|
||||
@@ -741,6 +742,7 @@ MenuBar.propTypes = {
|
||||
projectTitle: PropTypes.string,
|
||||
renderLogin: PropTypes.func,
|
||||
sessionExists: PropTypes.bool,
|
||||
shouldSaveBeforeTransition: PropTypes.func,
|
||||
showComingSoon: PropTypes.bool,
|
||||
username: PropTypes.string,
|
||||
vm: PropTypes.instanceOf(VM).isRequired
|
||||
@@ -794,7 +796,7 @@ const mapDispatchToProps = dispatch => ({
|
||||
|
||||
export default compose(
|
||||
injectIntl,
|
||||
ConfirmReplaceHOC,
|
||||
MenuBarHOC,
|
||||
connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import React from 'react';
|
||||
|
||||
const MenuBarHOC = function (WrappedComponent) {
|
||||
class MenuBarContainer extends React.PureComponent {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
bindAll(this, [
|
||||
'confirmReadyToReplaceProject',
|
||||
'shouldSaveBeforeTransition'
|
||||
]);
|
||||
}
|
||||
confirmReadyToReplaceProject (message) {
|
||||
let readyToReplaceProject = true;
|
||||
if (this.props.projectChanged && !this.props.canCreateNew) {
|
||||
readyToReplaceProject = this.props.confirmWithMessage(message);
|
||||
}
|
||||
return readyToReplaceProject;
|
||||
}
|
||||
shouldSaveBeforeTransition () {
|
||||
return (this.props.canSave && this.props.projectChanged);
|
||||
}
|
||||
render () {
|
||||
const {
|
||||
/* eslint-disable no-unused-vars */
|
||||
projectChanged,
|
||||
/* eslint-enable no-unused-vars */
|
||||
...props
|
||||
} = this.props;
|
||||
return (<WrappedComponent
|
||||
confirmReadyToReplaceProject={this.confirmReadyToReplaceProject}
|
||||
shouldSaveBeforeTransition={this.shouldSaveBeforeTransition}
|
||||
{...props}
|
||||
/>);
|
||||
}
|
||||
}
|
||||
|
||||
MenuBarContainer.propTypes = {
|
||||
canCreateNew: PropTypes.bool,
|
||||
canSave: PropTypes.bool,
|
||||
confirmWithMessage: PropTypes.func,
|
||||
projectChanged: PropTypes.bool
|
||||
};
|
||||
MenuBarContainer.defaultProps = {
|
||||
// default to using standard js confirm
|
||||
confirmWithMessage: message => (confirm(message)) // eslint-disable-line no-alert
|
||||
};
|
||||
const mapStateToProps = state => ({
|
||||
projectChanged: state.scratchGui.projectChanged
|
||||
});
|
||||
const mapDispatchToProps = () => ({});
|
||||
// Allow incoming props to override redux-provided props. Used to mock in tests.
|
||||
const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign(
|
||||
{}, stateProps, dispatchProps, ownProps
|
||||
);
|
||||
return connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
mergeProps
|
||||
)(MenuBarContainer);
|
||||
};
|
||||
|
||||
export default MenuBarHOC;
|
||||
@@ -0,0 +1,164 @@
|
||||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import MenuBarHOC from '../../../src/containers/menu-bar-hoc.jsx';
|
||||
|
||||
describe('Menu Bar HOC', () => {
|
||||
const mockStore = configureStore();
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
store = mockStore({
|
||||
scratchGui: {
|
||||
projectChanged: true
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Logged in user who IS owner and HAS changed project will NOT be prompted to save', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
canCreateNew
|
||||
canSave
|
||||
projectChanged
|
||||
// assume the user will click "cancel" on the confirm dialog
|
||||
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
|
||||
});
|
||||
|
||||
test('Logged in user who IS owner and has NOT changed project will NOT be prompted to save', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
canCreateNew
|
||||
canSave
|
||||
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
|
||||
projectChanged={false}
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
|
||||
});
|
||||
|
||||
test('Logged in user who is NOT owner and HAS changed project will NOT be prompted to save', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
canCreateNew
|
||||
projectChanged
|
||||
canSave={false}
|
||||
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
|
||||
});
|
||||
|
||||
test('Logged OUT user who HAS changed project WILL be prompted to save', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
projectChanged
|
||||
canCreateNew={false}
|
||||
canSave={false}
|
||||
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().confirmReadyToReplaceProject('message')).toBe(false);
|
||||
});
|
||||
|
||||
test('Logged OUT user who has NOT changed project WILL NOT be prompted to save', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
canCreateNew={false}
|
||||
canSave={false}
|
||||
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
|
||||
projectChanged={false}
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
|
||||
});
|
||||
|
||||
test('Logged in user who IS owner and HAS changed project SHOULD save before transition to project page', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
canSave
|
||||
projectChanged
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().shouldSaveBeforeTransition()).toBe(true);
|
||||
});
|
||||
|
||||
test('Logged in user who IS owner and has NOT changed project should NOT save before transition', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
canSave
|
||||
projectChanged={false}
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().shouldSaveBeforeTransition()).toBe(false);
|
||||
});
|
||||
|
||||
test('Logged in user who is NOT owner and HAS changed project should NOT save before transition', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
projectChanged
|
||||
canSave={false}
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().shouldSaveBeforeTransition()).toBe(false);
|
||||
});
|
||||
|
||||
test('Logged in user who is NOT owner and has NOT changed project should NOT save before transition', () => {
|
||||
const Component = () => (<div />);
|
||||
const WrappedComponent = MenuBarHOC(Component);
|
||||
const wrapper = mount(
|
||||
<WrappedComponent
|
||||
canSave={false}
|
||||
projectChanged={false}
|
||||
store={store}
|
||||
/>
|
||||
);
|
||||
const child = wrapper.find(Component);
|
||||
expect(child.props().projectChanged).toBeUndefined();
|
||||
expect(child.props().shouldSaveBeforeTransition()).toBe(false);
|
||||
});
|
||||
|
||||
});
|
||||
Reference in new issue
Block a user