diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index 08f698cbc..238a02ee0 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -81,6 +81,7 @@ const GUIComponent = props => {
enableCommunity,
importInfoVisible,
intl,
+ isCreating,
isPlayerOnly,
isRtl,
isShared,
@@ -152,6 +153,9 @@ const GUIComponent = props => {
{loading ? (
) : null}
+ {isCreating ? (
+
+ ) : null}
{importInfoVisible ? (
) : null}
@@ -357,6 +361,7 @@ GUIComponent.propTypes = {
enableCommunity: PropTypes.bool,
importInfoVisible: PropTypes.bool,
intl: intlShape.isRequired,
+ isCreating: PropTypes.bool,
isPlayerOnly: PropTypes.bool,
isRtl: PropTypes.bool,
isShared: PropTypes.bool,
@@ -397,7 +402,9 @@ GUIComponent.defaultProps = {
canShare: false,
canUseCloud: false,
enableCommunity: false,
+ isCreating: false,
isShared: false,
+ loading: false,
onUpdateProjectTitle: () => {},
showComingSoon: false,
stageSizeMode: STAGE_SIZE_MODES.large
diff --git a/src/components/loader/loader.jsx b/src/components/loader/loader.jsx
index dea1ff311..e06b8bb35 100644
--- a/src/components/loader/loader.jsx
+++ b/src/components/loader/loader.jsx
@@ -1,6 +1,7 @@
import React from 'react';
import {FormattedMessage} from 'react-intl';
import styles from './loader.css';
+import PropTypes from 'prop-types';
import topBlock from './top-block.svg';
import middleBlock from './middle-block.svg';
@@ -97,6 +98,22 @@ const messages = [
weight: 1
}
];
+const mainMessages = {
+ 'gui.loader.headline': (
+
+ ),
+ 'gui.loader.creating': (
+
+ )
+};
class LoaderComponent extends React.Component {
constructor (props) {
@@ -148,11 +165,7 @@ class LoaderComponent extends React.Component {
/>
@@ -33,12 +34,45 @@ const alerts = [
maxDisplaySecs: 5
},
{
- alertId: 'creating',
+ alertId: 'createCopySuccess',
alertType: AlertTypes.STANDARD,
- clearList: ['createSuccess', 'creating', 'saveSuccess', 'saving'],
+ clearList: ['createSuccess', 'creating', 'createCopySuccess', 'creatingCopy',
+ 'createRemixSuccess', 'creatingRemix', 'saveSuccess', 'saving'],
content: (
+ ),
+ iconURL: successImage,
+ level: AlertLevels.SUCCESS,
+ maxDisplaySecs: 5
+ },
+ {
+ alertId: 'createRemixSuccess',
+ alertType: AlertTypes.STANDARD,
+ clearList: ['createSuccess', 'creating', 'createCopySuccess', 'creatingCopy',
+ 'createRemixSuccess', 'creatingRemix', 'saveSuccess', 'saving'],
+ content: (
+
+ ),
+ iconURL: successImage,
+ level: AlertLevels.SUCCESS,
+ maxDisplaySecs: 5
+ },
+ {
+ alertId: 'creating',
+ alertType: AlertTypes.STANDARD,
+ clearList: ['createSuccess', 'creating', 'createCopySuccess', 'creatingCopy',
+ 'createRemixSuccess', 'creatingRemix', 'saveSuccess', 'saving'],
+ content: (
+
@@ -46,9 +80,40 @@ const alerts = [
iconSpinner: true,
level: AlertLevels.SUCCESS
},
+ {
+ alertId: 'creatingCopy',
+ alertType: AlertTypes.STANDARD,
+ clearList: ['createSuccess', 'creating', 'createCopySuccess', 'creatingCopy',
+ 'createRemixSuccess', 'creatingRemix', 'saveSuccess', 'saving'],
+ content: (
+
+ ),
+ iconSpinner: true,
+ level: AlertLevels.SUCCESS
+ },
+ {
+ alertId: 'creatingRemix',
+ alertType: AlertTypes.STANDARD,
+ clearList: ['createSuccess', 'creating', 'createCopySuccess', 'creatingCopy',
+ 'createRemixSuccess', 'creatingRemix', 'saveSuccess', 'saving'],
+ content: (
+
+ ),
+ iconSpinner: true,
+ level: AlertLevels.SUCCESS
+ },
{
alertId: 'creatingError',
- clearList: ['creating', 'createSuccess'],
+ clearList: ['createSuccess', 'creating', 'createCopySuccess', 'creatingCopy',
+ 'createRemixSuccess', 'creatingRemix', 'saveSuccess', 'saving'],
closeButton: true,
content: (
@@ -92,10 +158,10 @@ const alerts = [
{
alertId: 'saving',
alertType: AlertTypes.INLINE,
- clearList: ['createSuccess', 'creating', 'saveSuccess', 'saving', 'savingError'],
+ clearList: ['saveSuccess', 'saving', 'savingError'],
content: (
diff --git a/src/lib/project-saver-hoc.jsx b/src/lib/project-saver-hoc.jsx
index f3a1c2c16..cff3db1f5 100644
--- a/src/lib/project-saver-hoc.jsx
+++ b/src/lib/project-saver-hoc.jsx
@@ -20,6 +20,7 @@ import {
createProject,
doneCreatingProject,
doneUpdatingProject,
+ getIsAnyCreatingNewState,
getIsCreatingCopy,
getIsCreatingNew,
getIsManualUpdating,
@@ -128,11 +129,9 @@ const ProjectSaverHOC = function (WrappedComponent) {
});
}
createNewProjectToStorage () {
- this.props.onShowCreatingAlert();
return this.storeProject(null)
.then(response => {
this.props.onCreatedProject(response.id.toString(), this.props.loadingState);
- this.props.onShowCreateSuccessAlert();
})
.catch(err => {
this.props.onShowAlert('creatingError');
@@ -140,7 +139,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
});
}
createCopyToStorage () {
- this.props.onShowCreatingAlert();
+ this.props.onShowCreatingCopyAlert();
return this.storeProject(null, {
original_id: this.props.reduxProjectId,
is_copy: 1,
@@ -148,7 +147,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
})
.then(response => {
this.props.onCreatedProject(response.id.toString(), this.props.loadingState);
- this.props.onShowCreateSuccessAlert();
+ this.props.onShowCopySuccessAlert();
})
.catch(err => {
this.props.onShowAlert('creatingError');
@@ -156,7 +155,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
});
}
createRemixToStorage () {
- this.props.onShowCreatingAlert();
+ this.props.onShowCreatingRemixAlert();
return this.storeProject(null, {
original_id: this.props.reduxProjectId,
is_remix: 1,
@@ -164,7 +163,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
})
.then(response => {
this.props.onCreatedProject(response.id.toString(), this.props.loadingState);
- this.props.onShowCreateSuccessAlert();
+ this.props.onShowRemixSuccessAlert();
})
.catch(err => {
this.props.onShowAlert('creatingError');
@@ -247,6 +246,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
isCreatingCopy,
isCreatingNew,
projectChanged,
+ isAnyCreatingNewState,
isManualUpdating,
isRemixing,
isShowingSaveable,
@@ -260,8 +260,10 @@ const ProjectSaverHOC = function (WrappedComponent) {
onProjectError,
onRemixing,
onShowAlert,
- onShowCreateSuccessAlert,
- onShowCreatingAlert,
+ onShowCopySuccessAlert,
+ onShowRemixSuccessAlert,
+ onShowCreatingCopyAlert,
+ onShowCreatingRemixAlert,
onShowSaveSuccessAlert,
onShowSavingAlert,
onUpdatedProject,
@@ -274,6 +276,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
} = this.props;
return (
);
@@ -284,6 +287,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
autoSaveTimeoutId: PropTypes.number,
canCreateNew: PropTypes.bool,
canSave: PropTypes.bool,
+ isAnyCreatingNewState: PropTypes.bool,
isCreatingCopy: PropTypes.bool,
isCreatingNew: PropTypes.bool,
isManualUpdating: PropTypes.bool,
@@ -300,8 +304,10 @@ const ProjectSaverHOC = function (WrappedComponent) {
onProjectError: PropTypes.func,
onRemixing: PropTypes.func,
onShowAlert: PropTypes.func,
- onShowCreateSuccessAlert: PropTypes.func,
- onShowCreatingAlert: PropTypes.func,
+ onShowCopySuccessAlert: PropTypes.func,
+ onShowCreatingCopyAlert: PropTypes.func,
+ onShowCreatingRemixAlert: PropTypes.func,
+ onShowRemixSuccessAlert: PropTypes.func,
onShowSaveSuccessAlert: PropTypes.func,
onShowSavingAlert: PropTypes.func,
onUpdateProjectThumbnail: PropTypes.func,
@@ -320,6 +326,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
const isShowingWithId = getIsShowingWithId(loadingState);
return {
autoSaveTimeoutId: state.scratchGui.timeout.autoSaveTimeoutId,
+ isAnyCreatingNewState: getIsAnyCreatingNewState(loadingState),
isCreatingCopy: getIsCreatingCopy(loadingState),
isCreatingNew: getIsCreatingNew(loadingState),
isRemixing: getIsRemixing(loadingState),
@@ -342,8 +349,10 @@ const ProjectSaverHOC = function (WrappedComponent) {
onProjectError: error => dispatch(projectError(error)),
onSetProjectUnchanged: () => dispatch(setProjectUnchanged()),
onShowAlert: alertType => dispatch(showStandardAlert(alertType)),
- onShowCreateSuccessAlert: () => showAlertWithTimeout(dispatch, 'createSuccess'),
- onShowCreatingAlert: () => showAlertWithTimeout(dispatch, 'creating'),
+ onShowCopySuccessAlert: () => showAlertWithTimeout(dispatch, 'createCopySuccess'),
+ onShowRemixSuccessAlert: () => showAlertWithTimeout(dispatch, 'createRemixSuccess'),
+ onShowCreatingCopyAlert: () => showAlertWithTimeout(dispatch, 'creatingCopy'),
+ onShowCreatingRemixAlert: () => showAlertWithTimeout(dispatch, 'creatingRemix'),
onShowSaveSuccessAlert: () => showAlertWithTimeout(dispatch, 'saveSuccess'),
onShowSavingAlert: () => showAlertWithTimeout(dispatch, 'saving'),
onUpdatedProject: (projectId, loadingState) => dispatch(doneUpdatingProject(projectId, loadingState)),
diff --git a/src/reducers/project-state.js b/src/reducers/project-state.js
index 0679a8c37..edec52a53 100644
--- a/src/reducers/project-state.js
+++ b/src/reducers/project-state.js
@@ -61,6 +61,11 @@ const getIsLoadingWithId = loadingState => (
const getIsCreatingNew = loadingState => (
loadingState === LoadingState.CREATING_NEW
);
+const getIsAnyCreatingNewState = loadingState => (
+ loadingState === LoadingState.FETCHING_NEW_DEFAULT ||
+ loadingState === LoadingState.LOADING_VM_NEW_DEFAULT ||
+ loadingState === LoadingState.CREATING_NEW
+);
const getIsCreatingCopy = loadingState => (
loadingState === LoadingState.CREATING_COPY
);
@@ -477,6 +482,7 @@ export {
defaultProjectId,
doneCreatingProject,
doneUpdatingProject,
+ getIsAnyCreatingNewState,
getIsCreatingCopy,
getIsCreatingNew,
getIsError,
diff --git a/test/unit/reducers/alerts-reducer.test.js b/test/unit/reducers/alerts-reducer.test.js
index 0ebe41875..1a9db5138 100644
--- a/test/unit/reducers/alerts-reducer.test.js
+++ b/test/unit/reducers/alerts-reducer.test.js
@@ -107,8 +107,9 @@ test('related alerts can clear each other', () => {
};
const action = showStandardAlert('saveSuccess');
const resultState = alertsReducer(initialState, action);
- expect(resultState.alertsList.length).toBe(1);
- expect(resultState.alertsList[0].alertId).toBe('saveSuccess');
+ expect(resultState.alertsList.length).toBe(2);
+ expect(resultState.alertsList[0].alertId).toBe('creating');
+ expect(resultState.alertsList[1].alertId).toBe('saveSuccess');
});
test('several related alerts can be cleared at once', () => {
diff --git a/test/unit/util/project-saver-hoc.test.jsx b/test/unit/util/project-saver-hoc.test.jsx
index a9cecade5..e9d6e3b95 100644
--- a/test/unit/util/project-saver-hoc.test.jsx
+++ b/test/unit/util/project-saver-hoc.test.jsx
@@ -178,7 +178,7 @@ describe('projectSaverHOC', () => {
});
test('if we enter remixing state, vm project should be requested, and alert should show', () => {
- const mockedShowCreatingAlert = jest.fn();
+ const mockedShowCreatingRemixAlert = jest.fn();
const Component = () =>
;
const WrappedComponent = projectSaverHOC(Component);
const mockedStoreProject = jest.fn(() => Promise.resolve());
@@ -197,7 +197,7 @@ describe('projectSaverHOC', () => {
reduxProjectId={'100'}
store={store}
vm={vm}
- onShowCreatingAlert={mockedShowCreatingAlert}
+ onShowCreatingRemixAlert={mockedShowCreatingRemixAlert}
/>
);
mounted.setProps({
@@ -205,11 +205,11 @@ describe('projectSaverHOC', () => {
loadingState: LoadingState.REMIXING
});
expect(mockedStoreProject).toHaveBeenCalled();
- expect(mockedShowCreatingAlert).toHaveBeenCalled();
+ expect(mockedShowCreatingRemixAlert).toHaveBeenCalled();
});
test('if we enter creating copy state, vm project should be requested, and alert should show', () => {
- const mockedShowCreatingAlert = jest.fn();
+ const mockedShowCreatingCopyAlert = jest.fn();
const Component = () =>
;
const WrappedComponent = projectSaverHOC(Component);
const mockedStoreProject = jest.fn(() => Promise.resolve());
@@ -228,7 +228,7 @@ describe('projectSaverHOC', () => {
reduxProjectId={'100'}
store={store}
vm={vm}
- onShowCreatingAlert={mockedShowCreatingAlert}
+ onShowCreatingCopyAlert={mockedShowCreatingCopyAlert}
/>
);
mounted.setProps({
@@ -236,7 +236,7 @@ describe('projectSaverHOC', () => {
loadingState: LoadingState.CREATING_COPY
});
expect(mockedStoreProject).toHaveBeenCalled();
- expect(mockedShowCreatingAlert).toHaveBeenCalled();
+ expect(mockedShowCreatingCopyAlert).toHaveBeenCalled();
});
test('if we enter updating/saving state, vm project should be requested', () => {