diff --git a/src/components/ui/popup/PopupStack.jsx b/src/components/ui/popup/PopupStack.jsx index dc5de6b..1d72239 100644 --- a/src/components/ui/popup/PopupStack.jsx +++ b/src/components/ui/popup/PopupStack.jsx @@ -7,24 +7,19 @@ export class PopupStack extends Component { static propTypes = { popups: PropTypes.arrayOf(PropTypes.shape({ - type: PropTypes.string.isRequired, + type: PropTypes.func, props: PropTypes.oneOfType([PropTypes.object, PropTypes.func]) })), - pool: PropTypes.object.isRequired, destroy: PropTypes.func.isRequired }; render() { - const {popups, pool} = this.props; + const {popups} = this.props; return (
{popups.map((popup, index) => { - const Popup = pool[popup.type]; - - if (!Popup) { - throw new Error(`Unknown popup type: ${popup.type}`); - } + const Popup = popup.type; const defaultProps = { onClose: this.onClose(popup) diff --git a/src/components/ui/popup/actions.js b/src/components/ui/popup/actions.js index 948b48f..becf247 100644 --- a/src/components/ui/popup/actions.js +++ b/src/components/ui/popup/actions.js @@ -1,14 +1,3 @@ -export const POPUP_REGISTER = 'POPUP_REGISTER'; -export function register(type, component) { - return { - type: POPUP_REGISTER, - payload: { - type, - component - } - }; -} - export const POPUP_CREATE = 'POPUP_CREATE'; export function create(type, props = {}) { return { diff --git a/src/components/ui/popup/reducer.js b/src/components/ui/popup/reducer.js index cf45fff..9c34c6a 100644 --- a/src/components/ui/popup/reducer.js +++ b/src/components/ui/popup/reducer.js @@ -1,27 +1,11 @@ import { combineReducers } from 'redux'; -import { POPUP_REGISTER, POPUP_CREATE, POPUP_DESTROY } from './actions'; +import { POPUP_CREATE, POPUP_DESTROY } from './actions'; export default combineReducers({ - pool, popups }); -function pool(pool = {}, {type, payload}) { - if (type === POPUP_REGISTER) { - if (!payload.type || !payload.component) { - throw new Error('Type and component are required'); - } - - return { - ...pool, - [payload.type]: payload.component - }; - } - - return pool; -} - function popups(popups = [], {type, payload}) { switch (type) { case POPUP_CREATE: diff --git a/src/pages/profile/ChangePasswordPage.jsx b/src/pages/profile/ChangePasswordPage.jsx index dcb4cc9..21cfd92 100644 --- a/src/pages/profile/ChangePasswordPage.jsx +++ b/src/pages/profile/ChangePasswordPage.jsx @@ -27,7 +27,7 @@ class ChangePasswordPage extends Component { import { connect } from 'react-redux'; import { routeActions } from 'react-router-redux'; -import { register as registerPopup, create as createPopup } from 'components/ui/popup/actions'; +import { create as createPopup } from 'components/ui/popup/actions'; import { updateUser } from 'components/user/actions'; function goToProfile() { @@ -53,10 +53,7 @@ export default connect(null, { return Promise.resolve(); }) .then(() => { - // TODO: судя по всему registerPopup было явно лишним. Надо еще раз - // обдумать API и переписать - dispatch(registerPopup('requestPassword', PasswordRequestForm)); - dispatch(createPopup('requestPassword', (props) => ({ + dispatch(createPopup(PasswordRequestForm, (props) => ({ form, onSubmit: () => { // TODO: hide this logic in action diff --git a/src/pages/profile/ChangeUsernamePage.jsx b/src/pages/profile/ChangeUsernamePage.jsx index da2f046..bc71f3c 100644 --- a/src/pages/profile/ChangeUsernamePage.jsx +++ b/src/pages/profile/ChangeUsernamePage.jsx @@ -51,7 +51,7 @@ class ChangeUsernamePage extends Component { import { connect } from 'react-redux'; import { routeActions } from 'react-router-redux'; -import { register as registerPopup, create as createPopup } from 'components/ui/popup/actions'; +import { create as createPopup } from 'components/ui/popup/actions'; import { updateUser } from 'components/user/actions'; function goToProfile() { @@ -82,10 +82,7 @@ export default connect((state) => ({ }) .then(() => { return new Promise((resolve) => { - // TODO: судя по всему registerPopup было явно лишним. Надо еще раз - // обдумать API и переписать - dispatch(registerPopup('requestPassword', PasswordRequestForm)); - dispatch(createPopup('requestPassword', (props) => ({ + dispatch(createPopup(PasswordRequestForm, (props) => ({ form, onSubmit: () => { // TODO: hide this logic in action diff --git a/src/pages/profile/ProfileChangeEmailPage.jsx b/src/pages/profile/ProfileChangeEmailPage.jsx index a1c0f8c..592c1ea 100644 --- a/src/pages/profile/ProfileChangeEmailPage.jsx +++ b/src/pages/profile/ProfileChangeEmailPage.jsx @@ -41,7 +41,7 @@ class ProfileChangeEmailPage extends Component { import { connect } from 'react-redux'; import { routeActions } from 'react-router-redux'; -import { register as registerPopup, create as createPopup } from 'components/ui/popup/actions'; +import { create as createPopup } from 'components/ui/popup/actions'; import { updateUser } from 'components/user/actions'; function goToProfile() { @@ -72,10 +72,7 @@ export default connect((state) => ({ }) .then(() => { return new Promise((resolve) => { - // TODO: судя по всему registerPopup было явно лишним. Надо еще раз - // обдумать API и переписать - dispatch(registerPopup('requestPassword', PasswordRequestForm)); - dispatch(createPopup('requestPassword', (props) => ({ + dispatch(createPopup(PasswordRequestForm, (props) => ({ form, onSubmit: () => { // TODO: hide this logic in action diff --git a/tests/components/ui/popup/PopupStack.test.jsx b/tests/components/ui/popup/PopupStack.test.jsx index 657b13a..70182d1 100644 --- a/tests/components/ui/popup/PopupStack.test.jsx +++ b/tests/components/ui/popup/PopupStack.test.jsx @@ -9,16 +9,13 @@ function DummyPopup() {} describe('', () => { it('renders all popup components', () => { const props = { - pool: { - dummy: DummyPopup - }, destroy: () => {}, popups: [ { - type: 'dummy' + type: DummyPopup }, { - type: 'dummy' + type: DummyPopup } ] }; @@ -33,13 +30,10 @@ describe('', () => { }; const props = { - pool: { - dummy: DummyPopup - }, destroy: () => {}, popups: [ { - type: 'dummy', + type: DummyPopup, props: expectedProps } ] @@ -55,13 +49,10 @@ describe('', () => { }; const props = { - pool: { - dummy: DummyPopup - }, destroy: () => {}, popups: [ { - type: 'dummy', + type: DummyPopup, props: (props) => { expect(props).to.have.property('onClose'); @@ -77,15 +68,12 @@ describe('', () => { it('should hide popup, when onClose called', () => { const props = { - pool: { - dummy: DummyPopup - }, popups: [ { - type: 'dummy' + type: DummyPopup }, { - type: 'dummy' + type: DummyPopup } ], destroy: sinon.stub() @@ -97,22 +85,4 @@ describe('', () => { sinon.assert.calledOnce(props.destroy); sinon.assert.calledWith(props.destroy, sinon.match.same(props.popups[1])); }); - - it('throws when there is no popup component in pool', () => { - const props = { - pool: { - dummy: DummyPopup - }, - destroy: () => {}, - popups: [ - { - type: 'notExists' - } - ] - }; - - expect(() => { - shallow(); - }).to.throw('Unknown popup type: notExists'); - }); }); diff --git a/tests/components/ui/popup/reducer.test.js b/tests/components/ui/popup/reducer.test.js index b3ef8bd..7ae2d68 100644 --- a/tests/components/ui/popup/reducer.test.js +++ b/tests/components/ui/popup/reducer.test.js @@ -1,14 +1,7 @@ import reducer from 'components/ui/popup/reducer'; -import {create, destroy, register} from 'components/ui/popup/actions'; +import {create, destroy} from 'components/ui/popup/actions'; describe('popup/reducer', () => { - it('should have empty pool by default', () => { - const actual = reducer(undefined, {}); - - expect(actual.pool).to.be.an('object'); - expect(actual.pool).to.be.empty; - }); - it('should have no popups by default', () => { const actual = reducer(undefined, {}); @@ -16,45 +9,32 @@ describe('popup/reducer', () => { expect(actual.popups).to.be.empty; }); - describe('#register', () => { - it('should add popup components into pool', () => { - const actual = reducer(undefined, register('foo', function() {})); - - expect(actual.pool.foo).to.be.a('function'); - }); - - it('throws when no type or component provided', () => { - expect(() => reducer(undefined, register()), 'type').to.throw('Type and component are required'); - expect(() => reducer(undefined, register('foo')), 'component').to.throw('Type and component are required'); - }); - }); - describe('#create', () => { it('should create popup', () => { - const actual = reducer(undefined, create('foo')); + const actual = reducer(undefined, create(FakeComponent)); expect(actual.popups[0]).to.be.deep.equal({ - type: 'foo', + type: FakeComponent, props: {} }); }); it('should store props', () => { const expectedProps = {foo: 'bar'}; - const actual = reducer(undefined, create('foo', expectedProps)); + const actual = reducer(undefined, create(FakeComponent, expectedProps)); expect(actual.popups[0]).to.be.deep.equal({ - type: 'foo', + type: FakeComponent, props: expectedProps }); }); it('should not remove existed popups', () => { - let actual = reducer(undefined, create('foo')); - actual = reducer(actual, create('foo2')); + let actual = reducer(undefined, create(FakeComponent)); + actual = reducer(actual, create(FakeComponent)); expect(actual.popups[1]).to.be.deep.equal({ - type: 'foo2', + type: FakeComponent, props: {} }); }); @@ -69,8 +49,7 @@ describe('popup/reducer', () => { let popup; beforeEach(() => { - state = reducer(undefined, register('foo', () => {})); - state = reducer(state, create('foo')); + state = reducer(state, create(FakeComponent)); popup = state.popups[0]; }); @@ -96,3 +75,5 @@ describe('popup/reducer', () => { }); }); }); + +function FakeComponent() {}