diff --git a/.env.example b/.env.example index 9887bf701..740f234ce 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ CLIENT_ID= CLIENT_SECRET= SESSION_SECRET= -TARGET_APP= \ No newline at end of file +TARGET_APP= +CUSTOM_MUNICIPALITY_OPTIONS=[] diff --git a/README.md b/README.md index bb48a8772..e8bf86149 100644 --- a/README.md +++ b/README.md @@ -62,14 +62,27 @@ By default the running app can be found at `localhost:3000`. ``` OR prepare .env with default content: - + ``` CLIENT_ID CLIENT_SECRET SESSION_SECRET TARGET_APP + API_URL + CUSTOM_MUNICIPALITY_OPTIONS ``` + Environment's variable guideline: + + - `API_URL`: + Custom config to replace global application's api URL. Expected value is valid URL string. + + - `CUSTOM_MUNICIPALITY_OPTIONS`: + Config for custom municipalities. Expected value should be array of cities: `['Tampere','Jyväskylä','Oulu']`. + + Without this config, default to use 3 central cities Helsinki, Espoo, Vantaa as options. + + 3. Then, start the development server: ``` @@ -144,7 +157,7 @@ OR enable `eslint --fix` onSave config in your code editor config. ``` $ docker-compose exec web sh ``` -- Remove docker container if needed: +- Remove docker container if needed: ``` $ docker rm -f varaamo-frontend ``` @@ -185,17 +198,17 @@ Running Vscode debugger All setting was included under .vscode directory. - On Chrome: - [Guideline](https://code.visualstudio.com/blogs/2016/02/23/introducing-chrome-debugger-for-vs-code). Setting was under `Vscode debugger` name + [Guideline](https://code.visualstudio.com/blogs/2016/02/23/introducing-chrome-debugger-for-vs-code). Setting was under `Vscode debugger` name - On Jest test: [Guideline](https://jestjs.io/docs/en/troubleshooting#debugging-in-vs-code). Setting was under `Vscode Jest debugger` name. - + - Put breakpoint in test file `(*.spec.js)` - + - Run command: ``` $ yarn test:debug - ``` + ``` License ------- diff --git a/app/constants/AppConstants.js b/app/constants/AppConstants.js index d8c11f3ea..97b99f5fb 100644 --- a/app/constants/AppConstants.js +++ b/app/constants/AppConstants.js @@ -45,7 +45,7 @@ export default { }, }, SEARCH_PAGE_SIZE: 30, - SEARCH_MUNICIPALITY_OPTIONS: ['Helsinki', 'Espoo', 'Vantaa'], + DEFAULT_MUNICIPALITY_OPTIONS: ['Helsinki', 'Espoo', 'Vantaa'], SHOW_TEST_SITE_MESSAGE: SETTINGS.SHOW_TEST_SITE_MESSAGE, SUPPORTED_LANGUAGES: ['en', 'fi', 'sv'], SUPPORTED_SEARCH_FILTERS: { diff --git a/app/pages/search/controls/SearchControlsContainer.js b/app/pages/search/controls/SearchControlsContainer.js index 8f590d0a1..46f2aa695 100644 --- a/app/pages/search/controls/SearchControlsContainer.js +++ b/app/pages/search/controls/SearchControlsContainer.js @@ -1,6 +1,7 @@ import constants from 'constants/AppConstants'; import range from 'lodash/range'; +import capitalize from 'lodash/capitalize'; import moment from 'moment'; import PropTypes from 'prop-types'; import queryString from 'query-string'; @@ -53,10 +54,23 @@ class UnconnectedSearchControlsContainer extends Component { return options; } - getMunicipalityOptions = () => constants.SEARCH_MUNICIPALITY_OPTIONS.map(municipality => ({ - value: municipality.toLowerCase(), - label: municipality, - })); + getMunicipalityOptions = () => { + let municipalities = constants.DEFAULT_MUNICIPALITY_OPTIONS; + + if (Array.isArray(SETTINGS.CUSTOM_MUNICIPALITY_OPTIONS) + && SETTINGS.CUSTOM_MUNICIPALITY_OPTIONS.length) { + municipalities = SETTINGS.CUSTOM_MUNICIPALITY_OPTIONS; + } + + return municipalities.map((municipality) => { + const municipalityStr = typeof municipality === 'string' ? municipality : municipality.toString(); + + return { + value: municipalityStr.toLowerCase(), + label: capitalize(municipalityStr), + }; + }); + }; handleDateChange = ({ date }) => { const dateInCorrectFormat = moment(date, 'L').format(constants.DATE_FORMAT); diff --git a/app/pages/search/controls/SearchControlsContainer.spec.js b/app/pages/search/controls/SearchControlsContainer.spec.js index 4d039b0a8..aa7b21aae 100644 --- a/app/pages/search/controls/SearchControlsContainer.spec.js +++ b/app/pages/search/controls/SearchControlsContainer.spec.js @@ -483,4 +483,78 @@ describe('pages/search/controls/SearchControlsContainer', () => { expect(actions.fetchPurposes.callCount).toBe(1); }); }); + + describe('getMunicipalityOptions', () => { + test('return options default from 3 central cities', () => { + const instance = getWrapper().instance(); + const options = instance.getMunicipalityOptions(); + + expect(options[0].label).toEqual(constants.DEFAULT_MUNICIPALITY_OPTIONS[0]); + }); + + test('return options custom from env', () => { + const instance = getWrapper().instance(); + + global.SETTINGS = { + CUSTOM_MUNICIPALITY_OPTIONS: ['Foo', 'Bar'] + }; + + const options = instance.getMunicipalityOptions(); + + expect(options[0].label).toEqual('Foo'); + }); + + test('doesnt work with empty array', () => { + const instance = getWrapper().instance(); + + global.SETTINGS = { + CUSTOM_MUNICIPALITY_OPTIONS: [] + }; + + const options = instance.getMunicipalityOptions(); + + expect(options[0].label).toEqual(constants.DEFAULT_MUNICIPALITY_OPTIONS[0]); + }); + + test('use default in case of error, bad env var', () => { + const instance = getWrapper().instance(); + + global.SETTINGS = { + CUSTOM_MUNICIPALITY_OPTIONS: 'fooo' + }; + + const options = instance.getMunicipalityOptions(); + + expect(options[0].label).toEqual(constants.DEFAULT_MUNICIPALITY_OPTIONS[0]); + }); + + test('still work if value is number instead of string', () => { + const instance = getWrapper().instance(); + + global.SETTINGS = { + CUSTOM_MUNICIPALITY_OPTIONS: [123, 456] + }; + + const options = instance.getMunicipalityOptions(); + + expect(options[0].label).toEqual('123'); + }); + + test('label is capitalized, value is in lowercase', () => { + const instance = getWrapper().instance(); + + global.SETTINGS = { + CUSTOM_MUNICIPALITY_OPTIONS: ['foo'] + }; + + const options = instance.getMunicipalityOptions(); + + expect(options[0].label).toEqual('Foo'); + expect(options[0].value).toEqual('foo'); + }); + + afterAll(() => { + delete global.SETTINGS; + }); + }); }); diff --git a/config/webpack.development.js b/config/webpack.development.js index 6c95c725f..6b1f95cf9 100755 --- a/config/webpack.development.js +++ b/config/webpack.development.js @@ -69,6 +69,7 @@ module.exports = merge(common, { API_URL: JSON.stringify(process.env.API_URL || 'https://api.hel.fi/respa-test/v1'), SHOW_TEST_SITE_MESSAGE: Boolean(process.env.SHOW_TEST_SITE_MESSAGE), TRACKING: Boolean(process.env.PIWIK_SITE_ID), + CUSTOM_MUNICIPALITY_OPTIONS: process.env.CUSTOM_MUNICIPALITY_OPTIONS }, }), new webpack.HotModuleReplacementPlugin(), diff --git a/config/webpack.production.js b/config/webpack.production.js index 0ebf2af80..50acfdbf0 100755 --- a/config/webpack.production.js +++ b/config/webpack.production.js @@ -57,6 +57,7 @@ module.exports = merge(common, { API_URL: JSON.stringify(process.env.API_URL || 'https://api.hel.fi/respa/v1'), SHOW_TEST_SITE_MESSAGE: Boolean(process.env.SHOW_TEST_SITE_MESSAGE), TRACKING: Boolean(process.env.PIWIK_SITE_ID), + CUSTOM_MUNICIPALITY_OPTIONS: process.env.CUSTOM_MUNICIPALITY_OPTIONS, }, }), new MiniCssExtractPlugin({