feat: clear save failed status when closing error (#266)
This commit is contained in:
@@ -112,7 +112,6 @@ exports[`EditorFooter render snapshot: save failed. Show error message 1`] = `
|
||||
className="editor-footer fixed-bottom"
|
||||
>
|
||||
<Toast
|
||||
onClose={[MockFunction hooks.nullMethod]}
|
||||
show={true}
|
||||
>
|
||||
<FormattedMessage
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
@@ -10,14 +11,13 @@ import {
|
||||
Hyperlink,
|
||||
} from '@edx/paragon';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { selectors } from '../../../../data/redux';
|
||||
import { blockTypes } from '../../../../data/constants/app';
|
||||
|
||||
import { nullMethod } from '../../hooks';
|
||||
import messages from './messages';
|
||||
|
||||
export const EditorFooter = ({
|
||||
clearSaveFailed,
|
||||
disableSave,
|
||||
onCancel,
|
||||
onSave,
|
||||
@@ -30,9 +30,9 @@ export const EditorFooter = ({
|
||||
return (
|
||||
<div className="editor-footer fixed-bottom">
|
||||
{saveFailed && (
|
||||
<Toast show onClose={nullMethod}>
|
||||
<FormattedMessage {...messages.contentSaveFailed} />
|
||||
</Toast>
|
||||
<Toast show onClose={clearSaveFailed}>
|
||||
<FormattedMessage {...messages.contentSaveFailed} />
|
||||
</Toast>
|
||||
)}
|
||||
|
||||
<ModalDialog.Footer className="shadow-sm">
|
||||
@@ -69,6 +69,7 @@ export const EditorFooter = ({
|
||||
);
|
||||
};
|
||||
EditorFooter.propTypes = {
|
||||
clearSaveFailed: PropTypes.func.isRequired,
|
||||
disableSave: PropTypes.bool.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onSave: PropTypes.func.isRequired,
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { useState } from 'react';
|
||||
import analyticsEvt from '../../data/constants/analyticsEvt';
|
||||
import { RequestKeys } from '../../data/constants/requests';
|
||||
import { selectors } from '../../data/redux';
|
||||
import { StrictDict } from '../../utils';
|
||||
import * as appHooks from '../../hooks';
|
||||
import * as module from './hooks';
|
||||
import analyticsEvt from '../../data/constants/analyticsEvt';
|
||||
import { StrictDict } from '../../utils';
|
||||
|
||||
export const {
|
||||
clearSaveError,
|
||||
navigateCallback,
|
||||
nullMethod,
|
||||
saveBlock,
|
||||
@@ -30,6 +31,7 @@ export const handleSaveClicked = ({ dispatch, getContent, validateEntry }) => {
|
||||
validateEntry,
|
||||
});
|
||||
};
|
||||
|
||||
export const cancelConfirmModalToggle = () => {
|
||||
const [isCancelConfirmOpen, setIsOpen] = module.state.isCancelConfirmModalOpen(false);
|
||||
return {
|
||||
@@ -49,7 +51,9 @@ export const handleCancel = ({ onClose }) => {
|
||||
analytics: useSelector(selectors.app.analytics),
|
||||
});
|
||||
};
|
||||
|
||||
export const isInitialized = () => useSelector(selectors.app.isInitialized);
|
||||
|
||||
export const saveFailed = () => useSelector((rootState) => (
|
||||
selectors.requests.isFailed(rootState, { requestKey: RequestKeys.saveBlock })
|
||||
));
|
||||
|
||||
@@ -30,6 +30,9 @@ jest.mock('../../hooks', () => ({
|
||||
const dispatch = jest.fn();
|
||||
describe('EditorContainer hooks', () => {
|
||||
describe('forwarded hooks', () => {
|
||||
it('forwards clearSaveError from app hooks', () => {
|
||||
expect(hooks.clearSaveError).toEqual(appHooks.clearSaveError);
|
||||
});
|
||||
it('forwards navigateCallback from app hooks', () => {
|
||||
expect(hooks.navigateCallback).toEqual(appHooks.navigateCallback);
|
||||
});
|
||||
|
||||
@@ -6,12 +6,12 @@ import {
|
||||
Icon, ModalDialog, IconButton, Button,
|
||||
} from '@edx/paragon';
|
||||
import { Close } from '@edx/paragon/icons';
|
||||
|
||||
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import BaseModal from '../../sharedComponents/BaseModal';
|
||||
import EditorFooter from './components/EditorFooter';
|
||||
import TitleHeader from './components/TitleHeader';
|
||||
import * as hooks from './hooks';
|
||||
import BaseModal from '../../sharedComponents/BaseModal';
|
||||
import messages from './messages';
|
||||
|
||||
export const EditorContainer = ({
|
||||
@@ -65,9 +65,10 @@ export const EditorContainer = ({
|
||||
{isInitialized && children}
|
||||
</ModalDialog.Body>
|
||||
<EditorFooter
|
||||
clearSaveFailed={hooks.clearSaveError({ dispatch })}
|
||||
disableSave={!isInitialized}
|
||||
onCancel={openCancelConfirmModal}
|
||||
onSave={hooks.handleSaveClicked({ dispatch, getContent, validateEntry })}
|
||||
disableSave={!isInitialized}
|
||||
saveFailed={hooks.saveFailed()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,7 @@ const props = {
|
||||
};
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
clearSaveError: jest.fn().mockName('hooks.clearSaveError'),
|
||||
isInitialized: jest.fn().mockReturnValue(true),
|
||||
handleCancel: (args) => ({ handleCancel: args }),
|
||||
handleSaveClicked: (args) => ({ handleSaveClicked: args }),
|
||||
@@ -45,7 +46,6 @@ describe('EditorContainer component', () => {
|
||||
beforeEach(() => {
|
||||
el = shallow(<EditorContainer {...props}>{testContent}</EditorContainer>);
|
||||
});
|
||||
|
||||
test('save behavior is linked to footer onSave', () => {
|
||||
const expected = hooks.handleSaveClicked({
|
||||
dispatch: useDispatch(),
|
||||
@@ -55,6 +55,11 @@ describe('EditorContainer component', () => {
|
||||
expect(el.children().at(3)
|
||||
.props().onSave).toEqual(expected);
|
||||
});
|
||||
test('behavior is linked to clearSaveError', () => {
|
||||
const expected = hooks.clearSaveError({ dispatch: useDispatch() });
|
||||
expect(el.children().at(3)
|
||||
.props().clearSaveFailed).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,8 +3,9 @@ import { useEffect } from 'react';
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import analyticsEvt from './data/constants/analyticsEvt';
|
||||
|
||||
import { thunkActions } from './data/redux';
|
||||
import { actions, thunkActions } from './data/redux';
|
||||
import * as module from './hooks';
|
||||
import { RequestKeys } from './data/constants/requests';
|
||||
|
||||
export const initializeApp = ({ dispatch, data }) => useEffect(
|
||||
() => dispatch(thunkActions.app.initialize(data)),
|
||||
@@ -54,3 +55,7 @@ export const saveBlock = ({
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
export const clearSaveError = ({
|
||||
dispatch,
|
||||
}) => () => dispatch(actions.requests.clearRequest({ requestKey: RequestKeys.saveBlock }));
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import analyticsEvt from './data/constants/analyticsEvt';
|
||||
|
||||
import analyticsEvt from './data/constants/analyticsEvt';
|
||||
import { RequestKeys } from './data/constants/requests';
|
||||
import { actions, thunkActions } from './data/redux';
|
||||
import { keyStore } from './utils';
|
||||
import { thunkActions } from './data/redux';
|
||||
import * as hooks from './hooks';
|
||||
|
||||
jest.mock('react', () => ({
|
||||
@@ -15,17 +16,17 @@ jest.mock('react', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('./data/redux', () => ({
|
||||
actions: {
|
||||
requests: {
|
||||
clearRequest: (args) => ({ clearRequest: args }),
|
||||
},
|
||||
},
|
||||
thunkActions: {
|
||||
app: {
|
||||
initialize: (args) => ({ initializeApp: args }),
|
||||
saveBlock: (args) => ({ saveBlock: args }),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
app: {
|
||||
returnUrl: jest.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@edx/frontend-platform/analytics', () => ({
|
||||
@@ -131,4 +132,14 @@ describe('hooks', () => {
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearSaveError', () => {
|
||||
it('dispatches actions.requests.clearRequest with saveBlock requestKey', () => {
|
||||
const dispatch = jest.fn();
|
||||
hooks.clearSaveError({ dispatch })();
|
||||
expect(dispatch).toHaveBeenCalledWith(actions.requests.clearRequest({
|
||||
requestKey: RequestKeys.saveBlock,
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user