diff options
Diffstat (limited to 'front/odiparpack/internals/generators/container')
15 files changed, 578 insertions, 0 deletions
| diff --git a/front/odiparpack/internals/generators/container/actions.js.hbs b/front/odiparpack/internals/generators/container/actions.js.hbs new file mode 100644 index 0000000..f48b10b --- /dev/null +++ b/front/odiparpack/internals/generators/container/actions.js.hbs @@ -0,0 +1,13 @@ +/* + * + * {{ properCase name }} actions + * + */ + +import { DEFAULT_ACTION } from './constants'; + +export function defaultAction() { +  return { +    type: DEFAULT_ACTION, +  }; +} diff --git a/front/odiparpack/internals/generators/container/actions.test.js.hbs b/front/odiparpack/internals/generators/container/actions.test.js.hbs new file mode 100644 index 0000000..89ca2c7 --- /dev/null +++ b/front/odiparpack/internals/generators/container/actions.test.js.hbs @@ -0,0 +1,13 @@ +import { defaultAction } from '../actions'; +import { DEFAULT_ACTION } from '../constants'; + +describe('{{ properCase name }} actions', () => { +  describe('Default Action', () => { +    it('has a type of DEFAULT_ACTION', () => { +      const expected = { +        type: DEFAULT_ACTION, +      }; +      expect(defaultAction()).toEqual(expected); +    }); +  }); +}); diff --git a/front/odiparpack/internals/generators/container/class.js.hbs b/front/odiparpack/internals/generators/container/class.js.hbs new file mode 100644 index 0000000..95e265c --- /dev/null +++ b/front/odiparpack/internals/generators/container/class.js.hbs @@ -0,0 +1,93 @@ +/** + * + * {{properCase name }} + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +{{#if wantHeaders}} +import { Helmet } from 'react-helmet'; +{{/if}} +{{#if wantMessages}} +import { FormattedMessage } from 'react-intl'; +{{/if}} +{{#if wantActionsAndReducer}} +import { createStructuredSelector } from 'reselect'; +{{/if}} +import { compose } from 'redux'; + +{{#if wantSaga}} +import injectSaga from 'utils/injectSaga'; +{{/if}} +{{#if wantActionsAndReducer}} +import injectReducer from 'utils/injectReducer'; +import makeSelect{{properCase name}} from './selectors'; +import reducer from './reducer'; +{{/if}} +{{#if wantSaga}} +import saga from './saga'; +{{/if}} +{{#if wantMessages}} +import messages from './messages'; +{{/if}} + +/* eslint-disable react/prefer-stateless-function */ +export class {{ properCase name }} extends {{{ type }}} { +  render() { +    return ( +      <div> +      {{#if wantHeaders}} +        <Helmet> +          <title>{{properCase name}}</title> +          <meta name="description" content="Description of {{properCase name}}" /> +        </Helmet> +      {{/if}} +      {{#if wantMessages}} +        <FormattedMessage {...messages.header} /> +      {{/if}} +      </div> +    ); +  } +} + +{{ properCase name }}.propTypes = { +  dispatch: PropTypes.func.isRequired, +}; + +{{#if wantActionsAndReducer}} +const mapStateToProps = createStructuredSelector({ +  {{ lowerCase name }}: makeSelect{{properCase name}}(), +}); +{{/if}} + +function mapDispatchToProps(dispatch) { +  return { +    dispatch, +  }; +} + +{{#if wantActionsAndReducer}} +const withConnect = connect( +  mapStateToProps, +  mapDispatchToProps +); + +const withReducer = injectReducer({ key: '{{ camelCase name }}', reducer }); +{{else}} +const withConnect = connect(null, mapDispatchToProps); +{{/if}} +{{#if wantSaga}} +const withSaga = injectSaga({ key: '{{ camelCase name }}', saga }); +{{/if}} + +export default compose( +{{#if wantActionsAndReducer}} +  withReducer, +{{/if}} +{{#if wantSaga}} +  withSaga, +{{/if}} +  withConnect +)({{ properCase name }}); diff --git a/front/odiparpack/internals/generators/container/constants.js.hbs b/front/odiparpack/internals/generators/container/constants.js.hbs new file mode 100644 index 0000000..0a37bd1 --- /dev/null +++ b/front/odiparpack/internals/generators/container/constants.js.hbs @@ -0,0 +1,7 @@ +/* + * + * {{ properCase name }} constants + * + */ + +export const DEFAULT_ACTION = 'app/{{ properCase name }}/DEFAULT_ACTION'; diff --git a/front/odiparpack/internals/generators/container/index.js b/front/odiparpack/internals/generators/container/index.js new file mode 100644 index 0000000..572a161 --- /dev/null +++ b/front/odiparpack/internals/generators/container/index.js @@ -0,0 +1,194 @@ +/** + * Container Generator + */ + +const componentExists = require('../utils/componentExists'); + +module.exports = { +  description: 'Add a container component', +  prompts: [ +    { +      type: 'list', +      name: 'type', +      message: 'Select the base component type:', +      default: 'Stateless Function', +      choices: () => [ +        'Stateless Function', +        'React.PureComponent', +        'React.Component', +      ], +    }, +    { +      type: 'input', +      name: 'name', +      message: 'What should it be called?', +      default: 'Form', +      validate: value => { +        if (/.+/.test(value)) { +          return componentExists(value) +            ? 'A component or container with this name already exists' +            : true; +        } + +        return 'The name is required'; +      }, +    }, +    { +      type: 'confirm', +      name: 'wantHeaders', +      default: false, +      message: 'Do you want headers?', +    }, +    { +      type: 'confirm', +      name: 'wantActionsAndReducer', +      default: true, +      message: +        'Do you want an actions/constants/selectors/reducer tuple for this container?', +    }, +    { +      type: 'confirm', +      name: 'wantSaga', +      default: true, +      message: 'Do you want sagas for asynchronous flows? (e.g. fetching data)', +    }, +    { +      type: 'confirm', +      name: 'wantMessages', +      default: true, +      message: 'Do you want i18n messages (i.e. will this component use text)?', +    }, +    { +      type: 'confirm', +      name: 'wantLoadable', +      default: true, +      message: 'Do you want to load resources asynchronously?', +    }, +  ], +  actions: data => { +    // Generate index.js and index.test.js +    var componentTemplate; // eslint-disable-line no-var + +    switch (data.type) { +      case 'Stateless Function': { +        componentTemplate = './container/stateless.js.hbs'; +        break; +      } +      default: { +        componentTemplate = './container/class.js.hbs'; +      } +    } + +    const actions = [ +      { +        type: 'add', +        path: '../../app/containers/{{properCase name}}/index.js', +        templateFile: componentTemplate, +        abortOnFail: true, +      }, +      { +        type: 'add', +        path: '../../app/containers/{{properCase name}}/tests/index.test.js', +        templateFile: './container/test.js.hbs', +        abortOnFail: true, +      }, +    ]; + +    // If component wants messages +    if (data.wantMessages) { +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/messages.js', +        templateFile: './container/messages.js.hbs', +        abortOnFail: true, +      }); +    } + +    // If they want actions and a reducer, generate actions.js, constants.js, +    // reducer.js and the corresponding tests for actions and the reducer +    if (data.wantActionsAndReducer) { +      // Actions +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/actions.js', +        templateFile: './container/actions.js.hbs', +        abortOnFail: true, +      }); +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/tests/actions.test.js', +        templateFile: './container/actions.test.js.hbs', +        abortOnFail: true, +      }); + +      // Constants +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/constants.js', +        templateFile: './container/constants.js.hbs', +        abortOnFail: true, +      }); + +      // Selectors +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/selectors.js', +        templateFile: './container/selectors.js.hbs', +        abortOnFail: true, +      }); +      actions.push({ +        type: 'add', +        path: +          '../../app/containers/{{properCase name}}/tests/selectors.test.js', +        templateFile: './container/selectors.test.js.hbs', +        abortOnFail: true, +      }); + +      // Reducer +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/reducer.js', +        templateFile: './container/reducer.js.hbs', +        abortOnFail: true, +      }); +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/tests/reducer.test.js', +        templateFile: './container/reducer.test.js.hbs', +        abortOnFail: true, +      }); +    } + +    // Sagas +    if (data.wantSaga) { +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/saga.js', +        templateFile: './container/saga.js.hbs', +        abortOnFail: true, +      }); +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/tests/saga.test.js', +        templateFile: './container/saga.test.js.hbs', +        abortOnFail: true, +      }); +    } + +    if (data.wantLoadable) { +      actions.push({ +        type: 'add', +        path: '../../app/containers/{{properCase name}}/Loadable.js', +        templateFile: './component/loadable.js.hbs', +        abortOnFail: true, +      }); +    } + +    actions.push({ +      type: 'prettify', +      path: '/containers/', +    }); + +    return actions; +  }, +}; diff --git a/front/odiparpack/internals/generators/container/index.js.hbs b/front/odiparpack/internals/generators/container/index.js.hbs new file mode 100644 index 0000000..39117a1 --- /dev/null +++ b/front/odiparpack/internals/generators/container/index.js.hbs @@ -0,0 +1,66 @@ +/* + * + * {{properCase name }} + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +{{#if wantHeaders}} +import { Helmet } from 'react-helmet'; +{{/if}} +{{#if wantMessages}} +import { FormattedMessage } from 'react-intl'; +{{/if}} +{{#if wantActionsAndReducer}} +import { createStructuredSelector } from 'reselect'; +import makeSelect{{properCase name}} from './selectors'; +{{/if}} +{{#if wantMessages}} +import messages from './messages'; +{{/if}} + +/* eslint-disable react/prefer-stateless-function */ +export class {{ properCase name }} extends React.{{{ component }}} { +  render() { +    return ( +      <div> +      {{#if wantHeaders}} +        <Helmet> +          <title>{{properCase name}}</title> +          <meta +            name="description" +            content="Description of {{properCase name}}" +          /> +        </Helmet> +      {{/if}} +      {{#if wantMessages}} +        <FormattedMessage {...messages.header} /> +      {{/if}} +      </div> +    ); +  } +} + +{{ properCase name }}.propTypes = { +  dispatch: PropTypes.func.isRequired, +}; + +{{#if wantActionsAndReducer}} +const mapStateToProps = createStructuredSelector({ +  {{name}}: makeSelect{{properCase name}}(), +}); +{{/if}} + +function mapDispatchToProps(dispatch) { +  return { +    dispatch, +  }; +} + +{{#if wantActionsAndReducer}} +export default connect(mapStateToProps, mapDispatchToProps)({{ properCase name }}); +{{else}} +export default connect(null, mapDispatchToProps)({{ properCase name }}); +{{/if}} diff --git a/front/odiparpack/internals/generators/container/messages.js.hbs b/front/odiparpack/internals/generators/container/messages.js.hbs new file mode 100644 index 0000000..9500820 --- /dev/null +++ b/front/odiparpack/internals/generators/container/messages.js.hbs @@ -0,0 +1,14 @@ +/* + * {{properCase name }} Messages + * + * This contains all the text for the {{properCase name }} component. + */ + +import { defineMessages } from 'react-intl'; + +export default defineMessages({ +  header: { +    id: 'app.containers.{{properCase name }}.header', +    defaultMessage: 'This is {{properCase name}} container !', +  }, +}); diff --git a/front/odiparpack/internals/generators/container/reducer.js.hbs b/front/odiparpack/internals/generators/container/reducer.js.hbs new file mode 100644 index 0000000..5af9e12 --- /dev/null +++ b/front/odiparpack/internals/generators/container/reducer.js.hbs @@ -0,0 +1,21 @@ +/* + * + * {{ properCase name }} reducer + * + */ + +import { fromJS } from 'immutable'; +import { DEFAULT_ACTION } from './constants'; + +export const initialState = fromJS({}); + +function {{ camelCase name }}Reducer(state = initialState, action) { +  switch (action.type) { +    case DEFAULT_ACTION: +      return state; +    default: +      return state; +  } +} + +export default {{ camelCase name }}Reducer; diff --git a/front/odiparpack/internals/generators/container/reducer.test.js.hbs b/front/odiparpack/internals/generators/container/reducer.test.js.hbs new file mode 100644 index 0000000..5ac10e3 --- /dev/null +++ b/front/odiparpack/internals/generators/container/reducer.test.js.hbs @@ -0,0 +1,8 @@ +import { fromJS } from 'immutable'; +import {{ camelCase name }}Reducer from '../reducer'; + +describe('{{ camelCase name }}Reducer', () => { +  it('returns the initial state', () => { +    expect({{ camelCase name }}Reducer(undefined, {})).toEqual(fromJS({})); +  }); +}); diff --git a/front/odiparpack/internals/generators/container/saga.js.hbs b/front/odiparpack/internals/generators/container/saga.js.hbs new file mode 100644 index 0000000..fc475fd --- /dev/null +++ b/front/odiparpack/internals/generators/container/saga.js.hbs @@ -0,0 +1,6 @@ +// import { take, call, put, select } from 'redux-saga/effects'; + +// Individual exports for testing +export default function* defaultSaga() { +  // See example in containers/HomePage/saga.js +} diff --git a/front/odiparpack/internals/generators/container/saga.test.js.hbs b/front/odiparpack/internals/generators/container/saga.test.js.hbs new file mode 100644 index 0000000..9fcf7f5 --- /dev/null +++ b/front/odiparpack/internals/generators/container/saga.test.js.hbs @@ -0,0 +1,15 @@ +/** + * Test sagas + */ + +/* eslint-disable redux-saga/yield-effects */ +// import { take, call, put, select } from 'redux-saga/effects'; +// import { defaultSaga } from '../saga'; + +// const generator = defaultSaga(); + +describe('defaultSaga Saga', () => { +  it('Expect to have unit tests specified', () => { +    expect(true).toEqual(false); +  }); +}); diff --git a/front/odiparpack/internals/generators/container/selectors.js.hbs b/front/odiparpack/internals/generators/container/selectors.js.hbs new file mode 100644 index 0000000..55e5a04 --- /dev/null +++ b/front/odiparpack/internals/generators/container/selectors.js.hbs @@ -0,0 +1,23 @@ +import { createSelector } from 'reselect'; +import { initialState } from './reducer'; + +/** + * Direct selector to the {{ camelCase name }} state domain + */ + +const select{{ properCase name }}Domain = state => +  state.get('{{ camelCase name }}', initialState); + +/** + * Other specific selectors + */ + +/** + * Default selector used by {{ properCase name }} + */ + +const makeSelect{{ properCase name }} = () => +  createSelector(select{{ properCase name }}Domain, substate => substate.toJS()); + +export default makeSelect{{ properCase name }}; +export { select{{ properCase name }}Domain }; diff --git a/front/odiparpack/internals/generators/container/selectors.test.js.hbs b/front/odiparpack/internals/generators/container/selectors.test.js.hbs new file mode 100644 index 0000000..4ad7530 --- /dev/null +++ b/front/odiparpack/internals/generators/container/selectors.test.js.hbs @@ -0,0 +1,8 @@ +// import { fromJS } from 'immutable'; +// import { select{{ properCase name }}Domain } from '../selectors'; + +describe('select{{ properCase name }}Domain', () => { +  it('Expect to have unit tests specified', () => { +    expect(true).toEqual(false); +  }); +}); diff --git a/front/odiparpack/internals/generators/container/stateless.js.hbs b/front/odiparpack/internals/generators/container/stateless.js.hbs new file mode 100644 index 0000000..2f7994a --- /dev/null +++ b/front/odiparpack/internals/generators/container/stateless.js.hbs @@ -0,0 +1,87 @@ +/** + * + * {{properCase name }} + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +{{#if wantHeaders}} +import { Helmet } from 'react-helmet'; +{{/if}} +{{#if wantMessages}} +import { FormattedMessage } from 'react-intl'; +{{/if}} +{{#if wantActionsAndReducer}} +import { createStructuredSelector } from 'reselect'; +{{/if}} +import { compose } from 'redux'; + +{{#if wantSaga}} +import injectSaga from 'utils/injectSaga'; +{{/if}} +{{#if wantActionsAndReducer}} +import injectReducer from 'utils/injectReducer'; +import makeSelect{{properCase name}} from './selectors'; +import reducer from './reducer'; +{{/if}} +{{#if wantSaga}} +import saga from './saga'; +{{/if}} +{{#if wantMessages}} +import messages from './messages'; +{{/if}} + +function {{ properCase name }}() { +  return ( +    <div> +    {{#if wantHeaders}} +      <Helmet> +        <title>{{properCase name}}</title> +        <meta name="description" content="Description of {{properCase name}}" /> +      </Helmet> +    {{/if}} +    {{#if wantMessages}} +      <FormattedMessage {...messages.header} /> +    {{/if}} +    </div> +  ); +} + +{{ properCase name }}.propTypes = { +  dispatch: PropTypes.func.isRequired, +}; + +{{#if wantActionsAndReducer}} +const mapStateToProps = createStructuredSelector({ +  {{ lowerCase name }}: makeSelect{{properCase name}}(), +}); +{{/if}} + +function mapDispatchToProps(dispatch) { +  return { +    dispatch, +  }; +} + +{{#if wantActionsAndReducer}} +const withConnect = connect(mapStateToProps, mapDispatchToProps); + +const withReducer = injectReducer({ key: '{{ lowerCase name }}', reducer }); +{{else}} +const withConnect = connect(null, mapDispatchToProps); +{{/if}} +{{#if wantSaga}} +const withSaga = injectSaga({ key: '{{ lowerCase name }}', saga }); +{{/if}} + +export default compose( +{{#if wantActionsAndReducer}} +  withReducer, +{{/if}} +{{#if wantSaga}} +  withSaga, +{{/if}} +  withConnect, +)({{ properCase name }}); diff --git a/front/odiparpack/internals/generators/container/test.js.hbs b/front/odiparpack/internals/generators/container/test.js.hbs new file mode 100644 index 0000000..8427a4a --- /dev/null +++ b/front/odiparpack/internals/generators/container/test.js.hbs @@ -0,0 +1,10 @@ +// import React from 'react'; +// import { shallow } from 'enzyme'; + +// import { {{ properCase name }} } from '../index'; + +describe('<{{ properCase name }} />', () => { +  it('Expect to have unit tests specified', () => { +    expect(true).toEqual(false); +  }); +}); | 
