diff options
| author | Dayana31 <[email protected]> | 2022-04-21 17:27:08 -0500 |
|---|---|---|
| committer | Dayana31 <[email protected]> | 2022-04-21 17:27:08 -0500 |
| commit | 67c50667678dd0ce4709b29a854f6a47093a1ac5 (patch) | |
| tree | b6f9f39092ad54bf6b815984d32b37d7c7ca67ab /front/odiparpack/internals/generators | |
| parent | 91140b24f0d49a9f89a080ee063e9eb023a4b73a (diff) | |
| parent | e13e630cd6e4fc0b1ff92098a28a770794c7bb9a (diff) | |
| download | DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.tar.gz DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.tar.bz2 DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.zip | |
Merge branch 'gabshr' into dayana
Diffstat (limited to 'front/odiparpack/internals/generators')
31 files changed, 943 insertions, 0 deletions
diff --git a/front/odiparpack/internals/generators/component/class.js.hbs b/front/odiparpack/internals/generators/component/class.js.hbs new file mode 100644 index 0000000..310239a --- /dev/null +++ b/front/odiparpack/internals/generators/component/class.js.hbs @@ -0,0 +1,31 @@ +/** + * + * {{ properCase name }} + * + */ + +import React from 'react'; +// import PropTypes from 'prop-types'; +// import styled from 'styled-components'; + +{{#if wantMessages}} +import { FormattedMessage } from 'react-intl'; +import messages from './messages'; +{{/if}} + +/* eslint-disable react/prefer-stateless-function */ +class {{ properCase name }} extends {{{ type }}} { + render() { + return ( + <div> + {{#if wantMessages}} + <FormattedMessage {...messages.header} /> + {{/if}} + </div> + ); + } +} + +{{ properCase name }}.propTypes = {}; + +export default {{ properCase name }}; diff --git a/front/odiparpack/internals/generators/component/index.js b/front/odiparpack/internals/generators/component/index.js new file mode 100644 index 0000000..4ac51d9 --- /dev/null +++ b/front/odiparpack/internals/generators/component/index.js @@ -0,0 +1,109 @@ +/** + * Component Generator + */ + +/* eslint strict: ["off"] */ + +'use strict'; + +const componentExists = require('../utils/componentExists'); + +module.exports = { + description: 'Add an unconnected component', + prompts: [ + { + type: 'list', + name: 'type', + message: 'Select the type of component', + default: 'Stateless Function', + choices: () => [ + 'Stateless Function', + 'React.PureComponent', + 'React.Component', + ], + }, + { + type: 'input', + name: 'name', + message: 'What should it be called?', + default: 'Button', + 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: 'wantMessages', + default: true, + message: 'Do you want i18n messages (i.e. will this component use text)?', + }, + { + type: 'confirm', + name: 'wantLoadable', + default: false, + message: 'Do you want to load the component asynchronously?', + }, + ], + actions: data => { + // Generate index.js and index.test.js + let componentTemplate; + + switch (data.type) { + case 'Stateless Function': { + componentTemplate = './component/stateless.js.hbs'; + break; + } + default: { + componentTemplate = './component/class.js.hbs'; + } + } + + const actions = [ + { + type: 'add', + path: '../../app/components/{{properCase name}}/index.js', + templateFile: componentTemplate, + abortOnFail: true, + }, + { + type: 'add', + path: '../../app/components/{{properCase name}}/tests/index.test.js', + templateFile: './component/test.js.hbs', + abortOnFail: true, + }, + ]; + + // If they want a i18n messages file + if (data.wantMessages) { + actions.push({ + type: 'add', + path: '../../app/components/{{properCase name}}/messages.js', + templateFile: './component/messages.js.hbs', + abortOnFail: true, + }); + } + + // If want Loadable.js to load the component asynchronously + if (data.wantLoadable) { + actions.push({ + type: 'add', + path: '../../app/components/{{properCase name}}/Loadable.js', + templateFile: './component/loadable.js.hbs', + abortOnFail: true, + }); + } + + actions.push({ + type: 'prettify', + path: '/components/', + }); + + return actions; + }, +}; diff --git a/front/odiparpack/internals/generators/component/loadable.js.hbs b/front/odiparpack/internals/generators/component/loadable.js.hbs new file mode 100644 index 0000000..889bbf6 --- /dev/null +++ b/front/odiparpack/internals/generators/component/loadable.js.hbs @@ -0,0 +1,12 @@ +/** + * + * Asynchronously loads the component for {{ properCase name }} + * + */ + +import Loadable from 'react-loadable'; + +export default Loadable({ + loader: () => import('./index'), + loading: () => null, +}); diff --git a/front/odiparpack/internals/generators/component/messages.js.hbs b/front/odiparpack/internals/generators/component/messages.js.hbs new file mode 100644 index 0000000..f73ee90 --- /dev/null +++ b/front/odiparpack/internals/generators/component/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.components.{{ properCase name }}.header', + defaultMessage: 'This is the {{ properCase name}} component !', + }, +}); diff --git a/front/odiparpack/internals/generators/component/stateless.js.hbs b/front/odiparpack/internals/generators/component/stateless.js.hbs new file mode 100644 index 0000000..04ba918 --- /dev/null +++ b/front/odiparpack/internals/generators/component/stateless.js.hbs @@ -0,0 +1,28 @@ +/** + * + * {{ properCase name }} + * + */ + +import React from 'react'; +// import PropTypes from 'prop-types'; +// import styled from 'styled-components'; + +{{#if wantMessages}} +import { FormattedMessage } from 'react-intl'; +import messages from './messages'; +{{/if}} + +function {{ properCase name }}() { + return ( + <div> + {{#if wantMessages}} + <FormattedMessage {...messages.header} /> + {{/if}} + </div> + ); +} + +{{ properCase name }}.propTypes = {}; + +export default {{ properCase name }}; diff --git a/front/odiparpack/internals/generators/component/test.js.hbs b/front/odiparpack/internals/generators/component/test.js.hbs new file mode 100644 index 0000000..42c0e37 --- /dev/null +++ b/front/odiparpack/internals/generators/component/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); + }); +}); 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); + }); +}); diff --git a/front/odiparpack/internals/generators/index.js b/front/odiparpack/internals/generators/index.js new file mode 100644 index 0000000..e00eeea --- /dev/null +++ b/front/odiparpack/internals/generators/index.js @@ -0,0 +1,41 @@ +/** + * generator/index.js + * + * Exports the generators so plop knows them + */ + +const fs = require('fs'); +const path = require('path'); +const { exec } = require('child_process'); +const componentGenerator = require('./component/index.js'); +const containerGenerator = require('./container/index.js'); +const languageGenerator = require('./language/index.js'); + +module.exports = plop => { + plop.setGenerator('component', componentGenerator); + plop.setGenerator('container', containerGenerator); + plop.setGenerator('language', languageGenerator); + plop.addHelper('directory', comp => { + try { + fs.accessSync( + path.join(__dirname, `../../app/containers/${comp}`), + fs.F_OK, + ); + return `containers/${comp}`; + } catch (e) { + return `components/${comp}`; + } + }); + plop.addHelper('curly', (object, open) => (open ? '{' : '}')); + plop.setActionType('prettify', (answers, config) => { + const folderPath = `${path.join( + __dirname, + '/../../app/', + config.path, + plop.getHelper('properCase')(answers.name), + '**.js', + )}`; + exec(`npm run prettify -- "${folderPath}"`); + return folderPath; + }); +}; diff --git a/front/odiparpack/internals/generators/language/add-locale-data.hbs b/front/odiparpack/internals/generators/language/add-locale-data.hbs new file mode 100644 index 0000000..80727c7 --- /dev/null +++ b/front/odiparpack/internals/generators/language/add-locale-data.hbs @@ -0,0 +1 @@ +$1addLocaleData({{language}}LocaleData); diff --git a/front/odiparpack/internals/generators/language/app-locale.hbs b/front/odiparpack/internals/generators/language/app-locale.hbs new file mode 100644 index 0000000..08753eb --- /dev/null +++ b/front/odiparpack/internals/generators/language/app-locale.hbs @@ -0,0 +1 @@ +$1 '{{language}}', diff --git a/front/odiparpack/internals/generators/language/format-translation-messages.hbs b/front/odiparpack/internals/generators/language/format-translation-messages.hbs new file mode 100644 index 0000000..143601f --- /dev/null +++ b/front/odiparpack/internals/generators/language/format-translation-messages.hbs @@ -0,0 +1 @@ +$1 {{language}}: formatTranslationMessages('{{language}}', {{language}}TranslationMessages), diff --git a/front/odiparpack/internals/generators/language/index.js b/front/odiparpack/internals/generators/language/index.js new file mode 100644 index 0000000..aaf91e8 --- /dev/null +++ b/front/odiparpack/internals/generators/language/index.js @@ -0,0 +1,92 @@ +/** + * Language Generator + */ +const fs = require('fs'); +const { exec } = require('child_process'); + +function languageIsSupported(language) { + try { + fs.accessSync(`app/translations/${language}.json`, fs.F_OK); + return true; + } catch (e) { + return false; + } +} + +module.exports = { + description: 'Add a language', + prompts: [ + { + type: 'input', + name: 'language', + message: + 'What is the language you want to add i18n support for (e.g. "fr", "de")?', + default: 'fr', + validate: value => { + if (/.+/.test(value) && value.length === 2) { + return languageIsSupported(value) + ? `The language "${value}" is already supported.` + : true; + } + + return '2 character language specifier is required'; + }, + }, + ], + + actions: () => { + const actions = []; + actions.push({ + type: 'modify', + path: '../../app/i18n.js', + pattern: /(const ..LocaleData = require\('react-intl\/locale-data\/..'\);\n)+/g, + templateFile: './language/intl-locale-data.hbs', + }); + actions.push({ + type: 'modify', + path: '../../app/i18n.js', + pattern: /(\s+'[a-z]+',\n)(?!.*\s+'[a-z]+',)/g, + templateFile: './language/app-locale.hbs', + }); + actions.push({ + type: 'modify', + path: '../../app/i18n.js', + pattern: /(const ..TranslationMessages = require\('\.\/translations\/..\.json'\);\n)(?!const ..TranslationMessages = require\('\.\/translations\/..\.json'\);\n)/g, + templateFile: './language/translation-messages.hbs', + }); + actions.push({ + type: 'modify', + path: '../../app/i18n.js', + pattern: /(addLocaleData\([a-z]+LocaleData\);\n)(?!.*addLocaleData\([a-z]+LocaleData\);)/g, + templateFile: './language/add-locale-data.hbs', + }); + actions.push({ + type: 'modify', + path: '../../app/i18n.js', + pattern: /([a-z]+:\sformatTranslationMessages\('[a-z]+',\s[a-z]+TranslationMessages\),\n)(?!.*[a-z]+:\sformatTranslationMessages\('[a-z]+',\s[a-z]+TranslationMessages\),)/g, + templateFile: './language/format-translation-messages.hbs', + }); + actions.push({ + type: 'add', + path: '../../app/translations/{{language}}.json', + templateFile: './language/translations-json.hbs', + abortOnFail: true, + }); + actions.push({ + type: 'modify', + path: '../../app/app.js', + pattern: /(import\('intl\/locale-data\/jsonp\/[a-z]+\.js'\),\n)(?!.*import\('intl\/locale-data\/jsonp\/[a-z]+\.js'\),)/g, + templateFile: './language/polyfill-intl-locale.hbs', + }); + actions.push(() => { + const cmd = 'npm run extract-intl'; + exec(cmd, (err, result) => { + if (err) throw err; + process.stdout.write(result); + }); + return 'modify translation messages'; + }); + + return actions; + }, +}; diff --git a/front/odiparpack/internals/generators/language/intl-locale-data.hbs b/front/odiparpack/internals/generators/language/intl-locale-data.hbs new file mode 100644 index 0000000..7114f82 --- /dev/null +++ b/front/odiparpack/internals/generators/language/intl-locale-data.hbs @@ -0,0 +1 @@ +$&const {{language}}LocaleData = require('react-intl/locale-data/{{language}}'); diff --git a/front/odiparpack/internals/generators/language/polyfill-intl-locale.hbs b/front/odiparpack/internals/generators/language/polyfill-intl-locale.hbs new file mode 100644 index 0000000..139b74c --- /dev/null +++ b/front/odiparpack/internals/generators/language/polyfill-intl-locale.hbs @@ -0,0 +1 @@ +$1 import('intl/locale-data/jsonp/{{language}}.js'), diff --git a/front/odiparpack/internals/generators/language/translation-messages.hbs b/front/odiparpack/internals/generators/language/translation-messages.hbs new file mode 100644 index 0000000..6764c6c --- /dev/null +++ b/front/odiparpack/internals/generators/language/translation-messages.hbs @@ -0,0 +1 @@ +$1const {{language}}TranslationMessages = require('./translations/{{language}}.json'); diff --git a/front/odiparpack/internals/generators/language/translations-json.hbs b/front/odiparpack/internals/generators/language/translations-json.hbs new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/front/odiparpack/internals/generators/language/translations-json.hbs @@ -0,0 +1 @@ +[] diff --git a/front/odiparpack/internals/generators/utils/componentExists.js b/front/odiparpack/internals/generators/utils/componentExists.js new file mode 100644 index 0000000..8cd13d9 --- /dev/null +++ b/front/odiparpack/internals/generators/utils/componentExists.js @@ -0,0 +1,21 @@ +/** + * componentExists + * + * Check whether the given component exist in either the components or containers directory + */ + +const fs = require('fs'); +const path = require('path'); +const pageComponents = fs.readdirSync( + path.join(__dirname, '../../../app/components'), +); +const pageContainers = fs.readdirSync( + path.join(__dirname, '../../../app/containers'), +); +const components = pageComponents.concat(pageContainers); + +function componentExists(comp) { + return components.indexOf(comp) >= 0; +} + +module.exports = componentExists; |
