├── .eslintrc.json ├── .gitignore ├── .prettierrc.js ├── .travis.yml ├── LICENSE ├── README.md ├── babel.config.js ├── config ├── config.default.json └── config.js ├── docs ├── 715.7dd94fe17002b841b25c.css ├── 896.7dd94fe17002b841b25c.css ├── 956.7dd94fe17002b841b25c.css ├── components-Sections-ReactRouter-Routes-DecrementRoute.b39cfef421931f6623fe.js ├── components-Sections-ReactRouter-Routes-IncrementRoute.b39cfef421931f6623fe.js ├── components-Sections-ReactRouter-Routes-ResetRoute.b39cfef421931f6623fe.js ├── favicon.ico ├── index.html ├── main.b39cfef421931f6623fe.js ├── main.e6747817a710beefd9ef.css ├── manifest.b39cfef421931f6623fe.js ├── vendor.b39cfef421931f6623fe.js └── vendor.b39cfef421931f6623fe.js.LICENSE.txt ├── package-lock.json ├── package.json ├── postcss.config.js ├── scripts └── buildInfo.js ├── server.js ├── src ├── Bootstrap.tsx ├── Root.tsx ├── assets │ ├── favicon.ico │ └── logo.png ├── components │ ├── App.tsx │ ├── Footer │ │ ├── Footer.tsx │ │ ├── GithubButtons │ │ │ ├── GithubButton.tsx │ │ │ ├── GithubButtons.tsx │ │ │ ├── index.ts │ │ │ └── styles │ │ │ │ ├── GithubButton.scss │ │ │ │ └── GithubButtons.scss │ │ └── index.ts │ ├── Sections │ │ ├── GenericSection.tsx │ │ ├── ReactRouter │ │ │ ├── AsyncTabbedRouter.js │ │ │ ├── ChunkLoadingIcon.tsx │ │ │ ├── ReactRouter.tsx │ │ │ ├── Routes │ │ │ │ ├── DecrementRoute.tsx │ │ │ │ ├── IncrementRoute.tsx │ │ │ │ ├── ResetRoute.tsx │ │ │ │ ├── RouteContent.tsx │ │ │ │ └── styles │ │ │ │ │ └── RouteContent.scss │ │ │ ├── index.ts │ │ │ └── styles │ │ │ │ └── ChunkLoadingIcon.scss │ │ ├── ReduxEntity │ │ │ ├── Entities.tsx │ │ │ ├── Entity.tsx │ │ │ ├── Entity │ │ │ │ ├── EntityData.tsx │ │ │ │ ├── EntityFailure.tsx │ │ │ │ ├── EntityLoading.tsx │ │ │ │ ├── EntityMissing.tsx │ │ │ │ └── EntityReset.tsx │ │ │ ├── ReduxEntity.tsx │ │ │ ├── index.ts │ │ │ └── styles │ │ │ │ └── ReduxEntity.scss │ │ └── ReduxState │ │ │ ├── ReduxState.tsx │ │ │ └── index.ts │ ├── common │ │ ├── Button.tsx │ │ ├── Icon.tsx │ │ ├── Link.tsx │ │ ├── bulma │ │ │ ├── NavBar.tsx │ │ │ └── styles │ │ │ │ └── NavBar.scss │ │ └── index.ts │ └── styles │ │ └── App.scss ├── const │ └── index.ts ├── global.ts ├── index.html ├── reducers │ ├── counter │ │ ├── actions.ts │ │ └── reducer.ts │ ├── entities │ │ ├── actions.ts │ │ ├── reducer.ts │ │ └── types.ts │ ├── index.ts │ └── store │ │ ├── configure-store.dev.ts │ │ ├── configure-store.prod.ts │ │ └── index.ts ├── services │ ├── common │ │ ├── config-service.js │ │ └── node-service.js │ ├── data │ │ ├── ajax-service.ts │ │ └── data-access-service.ts │ ├── domain │ │ └── domain-service.ts │ └── util │ │ └── index.ts └── styles │ ├── global.scss │ └── mixins.scss ├── tsconfig.json └── webpack.config.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "jest": true, 6 | "es6": true 7 | }, 8 | "globals": { 9 | "_": true 10 | }, 11 | "parser": "@typescript-eslint/parser", 12 | "parserOptions": { 13 | "ecmaVersion": 7, 14 | "sourceType": "module", 15 | "ecmaFeatures": { 16 | "jsx": true 17 | } 18 | }, 19 | "plugins": ["react", "@typescript-eslint"], 20 | "extends": ["eslint:recommended", "plugin:react/recommended", "plugin:@typescript-eslint/recommended"], 21 | "settings": { 22 | "react": { 23 | "pragma": "React", 24 | "version": "16.6.3" 25 | } 26 | }, 27 | "overrides": [ 28 | { 29 | "files": ["*.js"], 30 | "rules": { 31 | "@typescript-eslint/no-var-requires": "off" 32 | } 33 | } 34 | ], 35 | "rules": { 36 | "eqeqeq": [2, "always"], 37 | "no-console": ["error", { "allow": ["log", "warn", "error"] }], 38 | "no-debugger": 2, 39 | "no-var": 1, 40 | "quotes": [2, "single"], 41 | "semi": [2, "always"], 42 | "space-before-function-paren": ["off"], 43 | "max-len": ["error", { "code": 120 }], 44 | "comma-dangle": ["off"] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .jekyll-metadata 2 | .htaccess 3 | .DS_Store 4 | .sass-cache 5 | Gemfile.lock 6 | _site/ 7 | _drafts/ 8 | 9 | # Logs 10 | logs 11 | *.log 12 | 13 | # Dependency directory 14 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 15 | node_modules 16 | 17 | # Build 18 | dist 19 | 20 | # IntelliJ 21 | .idea 22 | /*.iml 23 | 24 | # Coverage reports 25 | /.nyc-coverage 26 | /.nyc-coverage-temp 27 | /lint-report.html 28 | /.nyc_output/ 29 | 30 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: 'es5', 3 | tabWidth: 2, 4 | singleQuote: true, 5 | printWidth: 120, 6 | }; 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | - '12' 5 | after_success: npm run coverage 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Mike Chabot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # logo 2 | 3 | A slightly opinionated yet dead simple boilerplate for ReactJS, Webpack 4, and React Router v4. 4 | 5 | :heart: Async chunk loading 6 |
7 | :heart: Typescript 8 |
9 | :heart: React 17 10 |
11 | :heart: Webpack 5 12 |
13 | :heart: React Router v5 14 |
15 | :heart: Redux v4 16 |
17 | :heart: Code splitting 18 |
19 | 20 |
21 | 22 | build status 23 | 24 | 25 | dependency status 26 | 27 | 28 | prs welcome 29 | 30 |
31 | 32 | --- 33 | 34 | ## Table of Contents 35 | 36 | - [Live Demo](#live-demo) 37 | - [Features](#features) 38 | - [Getting Started](#getting-started) 39 | - [Custom Configuration](#custom-config) 40 | 41 | ## Live Demo 42 | 43 | http://mikechabot.github.io/react-boilerplate 44 | 45 | --- 46 | 47 | ## Features 48 | 49 | #### Build Process 50 | 51 | - [Typescript](https://www.typescriptlang.org/) support 52 | - Bundled with [webpack 5](https://webpack.js.org/configuration/) 53 | - Implements async chunk loading via [@loadable/react](https://loadable-components.com/) 54 | - Supports ES6 via [Babel](https://babeljs.io/) transpiling 55 | 56 | #### State Management 57 | 58 | - [redux-entity](https://github.com/mikechabot/redux-entity) for domain entity management 59 | - [redux-thunk](https://github.com/gaearon/redux-thunk) for [asynchronous actions](https://github.com/mikechabot/react-boilerplate/blob/master/src/reducers/entities/actions.ts) 60 | - [redux-logger](https://github.com/theaqua/redux-logger) for capturing actions 61 | 62 | #### Routing 63 | 64 | - [react-router v5](https://github.com/reactjs/react-router) for client-side [routing](https://github.com/mikechabot/react-boilerplate/blob/master/src/Root.tsx#L12) 65 | - [Async chunk loading](https://github.com/mikechabot/react-boilerplate/blob/master/src/components/Sections/ReactRouter/AsyncTabbedRouter.js#L15) at the `react-router` level 66 | 67 | #### HTTP 68 | 69 | - [Customizable](https://github.com/mikechabot/react-boilerplate/blob/master/src/services/data/ajax-service.js#L8), [Promise-based](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) HTTP support via [Axios](https://github.com/mzabriskie/axios) 70 | - Utilizes a [a generic data service](https://github.com/mikechabot/react-boilerplate/blob/master/src/services/data/data-access-service.ts#L30) to easily fetch data 71 | - Example of [implementing the data service](https://github.com/mikechabot/react-boilerplate/blob/master/src/services/domain/domain-service.ts#L7) 72 | 73 | #### Styling 74 | 75 | - Supports [SCSS & SASS](http://sass-lang.com/) syntax 76 | - Browser compatibility via [autoprefixing](https://github.com/postcss/autoprefixer) 77 | - [Bulma](https://bulma.io/documentation/overview/start/) for out-of-the-box styling 78 | 79 | #### Develop & Deploy 80 | 81 | - Environmental configurations for both webpack and redux 82 | - **Dev**: [webpack-dev-server](https://webpack.js.org/configuration/dev-server/) with [react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin). `redux-logger` enabled 83 | - **Prod**: [Express](http://expressjs.com/) server with `redux-logger` disabled 84 | 85 | --- 86 | 87 | ## Getting Started 88 | 89 | 1. `$ git clone https://github.com/mikechabot/react-boilerplate.git` 90 | 2. `$ npm install` 91 | 3. Launch environment: 92 | - **Production**: `$ npm start` 93 | - **Development**: `$ npm run dev` 94 | - Available at http://localhost:3060 95 | > Update port via [config.default.json](https://github.com/mikechabot/react-boilerplate/blob/master/config/config.default.json#L3), or override via [Custom Configuration](#custom-config) 96 | 4. Build assets for production: 97 | - `$ npm run build:prod` 98 | 99 | --- 100 | 101 | ## Custom Configuration 102 | 103 | Use [`cross-env`](https://github.com/kentcdodds/cross-env) or a comparable library/command to set the `ENV_CONFIG_PATH` to the path of your JSON configuration file: 104 | 105 | `$ cross-env ENV_CONFIG_PATH=/path/to/config.json npm start` 106 | 107 | > **Note**: This path is made available to Webpack **only**, however the contents of the file are stamped on a global variable during the build process (`process.env.APP_CONFIG`, see [webpack.config.js](https://github.com/mikechabot/react-boilerplate/blob/master/webpack.config.js#L46)), which is then accessible via the [ConfigService](https://github.com/mikechabot/react-boilerplate/blob/master/src/services/common/config-service.js#L19). 108 | 109 | If your configuration is loaded successfully, you can expect to see the following indicator during startup: 110 | 111 | ``` 112 | ** Using custom configuration located at "/path/to/config.json" ** 113 | ``` 114 | 115 | #### Example 116 | 117 | Using configuration file @ `C:\_workspaces\custom-config.json` 118 | 119 | ```bash 120 | $ cross-env ENV_CONFIG_PATH="C:\_workspaces\custom-config.json" npm start 121 | 122 | > react-boilerplate@5.0.0 start C:\_workspaces\react-boilerplate 123 | > npm run build:prod && npm run start-prod-server 124 | 125 | 126 | > react-boilerplate@5.0.0 build:prod C:\_workspaces\react-boilerplate 127 | > npm run clean && cross-env NODE_ENV=production webpack --progress --colors 128 | 129 | 130 | > react-boilerplate@5.0.0 clean C:\_workspaces\react-boilerplate 131 | > rm -rf ./docs 132 | 133 | ** Using custom configuration located at "C:\_workspaces\custom-config.json" ** 134 | __ __ _ __ __ __ 135 | _______ ___ _____/ /_____/ / ___ (_) /__ _______ / /__ _/ /____ 136 | / __/ -_) _ `/ __/ __/___/ _ \/ _ \/ / / -_) __/ _ \/ / _ `/ __/ -_) 137 | /_/ \__/\_,_/\__/\__/ /_.__/\___/_/_/\__/_/ / .__/_/\_,_/\__/\__/ 138 | /_/ 139 | ┌────────────────────────────────────────────────────────────────────┐ 140 | │ │ 141 | │ Mike Chabot | Version 5.0.0 | License MIT │ 142 | │ │ 143 | └────────────────────────────────────────────────────────────────────┘ 144 | [webpack.Progress] 0% compiling 145 | [webpack.Progress] 10% building 0/0 modules 0 active 146 | ``` 147 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | const presets = [ 2 | [ 3 | '@babel/env', 4 | { 5 | targets: { 6 | esmodules: true, 7 | }, 8 | useBuiltIns: 'entry', 9 | corejs: '3', 10 | }, 11 | ], 12 | ['@babel/react'], 13 | ]; 14 | 15 | const plugins = [ 16 | '@babel/plugin-syntax-dynamic-import', 17 | '@babel/plugin-proposal-class-properties', 18 | '@loadable/babel-plugin', 19 | ]; 20 | 21 | module.exports = { presets, plugins }; 22 | -------------------------------------------------------------------------------- /config/config.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "example": { 3 | "port": 3060, 4 | "baseUrl": "http://localhost:3020/", 5 | "publicBasename": "react-boilerplate/" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /config/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const DEFAULT_CONFIG_PATH = './config.default.json'; 4 | 5 | let configPath = DEFAULT_CONFIG_PATH; 6 | const customPath = process.env.ENV_CONFIG_PATH; 7 | 8 | if (customPath) { 9 | console.log(`** Using custom configuration located at "${customPath}" ** `); 10 | configPath = customPath; 11 | } 12 | 13 | module.exports = require(configPath); 14 | -------------------------------------------------------------------------------- /docs/715.7dd94fe17002b841b25c.css: -------------------------------------------------------------------------------- 1 | .route-content--container { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 10px; 5 | } 6 | .route-content--container .route-content--header, 7 | .route-content--container .route-content--counter { 8 | display: flex; 9 | align-content: center; 10 | } 11 | -------------------------------------------------------------------------------- /docs/896.7dd94fe17002b841b25c.css: -------------------------------------------------------------------------------- 1 | .route-content--container { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 10px; 5 | } 6 | .route-content--container .route-content--header, 7 | .route-content--container .route-content--counter { 8 | display: flex; 9 | align-content: center; 10 | } 11 | -------------------------------------------------------------------------------- /docs/956.7dd94fe17002b841b25c.css: -------------------------------------------------------------------------------- 1 | .route-content--container { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 10px; 5 | } 6 | .route-content--container .route-content--header, 7 | .route-content--container .route-content--counter { 8 | display: flex; 9 | align-content: center; 10 | } 11 | -------------------------------------------------------------------------------- /docs/components-Sections-ReactRouter-Routes-DecrementRoute.b39cfef421931f6623fe.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunkreact_boilerplate = self.webpackChunkreact_boilerplate || []).push([ 2 | [896], 3 | { 4 | 3843: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 5 | 'use strict'; 6 | __webpack_require__.r(__webpack_exports__); 7 | }, 8 | 2522: function (__unused_webpack_module, exports, __webpack_require__) { 9 | 'use strict'; 10 | var __importDefault = 11 | (this && this.__importDefault) || 12 | function (mod) { 13 | return mod && mod.__esModule ? mod : { default: mod }; 14 | }; 15 | Object.defineProperty(exports, '__esModule', { value: !0 }); 16 | const react_1 = __importDefault(__webpack_require__(7294)), 17 | RouteContent_1 = __importDefault(__webpack_require__(3672)), 18 | actions_1 = __webpack_require__(750); 19 | exports.default = () => 20 | react_1.default.createElement(RouteContent_1.default, { 21 | icon: 'minus', 22 | path: '/decrement', 23 | label: 'Decrement', 24 | action: actions_1.decrementAction, 25 | }); 26 | }, 27 | 3672: function (__unused_webpack_module, exports, __webpack_require__) { 28 | 'use strict'; 29 | var __importDefault = 30 | (this && this.__importDefault) || 31 | function (mod) { 32 | return mod && mod.__esModule ? mod : { default: mod }; 33 | }; 34 | Object.defineProperty(exports, '__esModule', { value: !0 }); 35 | const react_1 = __importDefault(__webpack_require__(7294)), 36 | bind_1 = __importDefault(__webpack_require__(7166)), 37 | react_redux_1 = __webpack_require__(8629), 38 | Icon_1 = __importDefault(__webpack_require__(8055)), 39 | RouteContent_scss_1 = __importDefault(__webpack_require__(3843)), 40 | cx = bind_1.default.bind(RouteContent_scss_1.default); 41 | exports.default = ({ path, label, action, icon }) => { 42 | const dispatch = react_redux_1.useDispatch(), 43 | counter = react_redux_1.useSelector((state) => state.counter); 44 | return react_1.default.createElement( 45 | 'div', 46 | { className: cx('route-content--container') }, 47 | react_1.default.createElement( 48 | 'div', 49 | { className: cx('route-content--heading') }, 50 | react_1.default.createElement(Icon_1.default, { icon: 'angle-right' }), 51 | ' Connected to the Redux store at the ', 52 | react_1.default.createElement('code', null, path || '/'), 53 | ' route' 54 | ), 55 | react_1.default.createElement( 56 | 'div', 57 | { className: `${cx('route-content--counter')} m-t-xs` }, 58 | react_1.default.createElement(Icon_1.default, { icon: 'angle-right' }), 59 | ' ', 60 | react_1.default.createElement('code', null, 'counter'), 61 | ': ', 62 | react_1.default.createElement('code', null, counter) 63 | ), 64 | react_1.default.createElement('br', null), 65 | react_1.default.createElement( 66 | 'div', 67 | { className: 'm-t-sm' }, 68 | react_1.default.createElement( 69 | 'button', 70 | { className: 'button', onClick: () => dispatch(action()) }, 71 | react_1.default.createElement(Icon_1.default, { icon }), 72 | ' ', 73 | label, 74 | ' counter' 75 | ) 76 | ) 77 | ); 78 | }; 79 | }, 80 | 750: function (__unused_webpack_module, exports, __webpack_require__) { 81 | 'use strict'; 82 | Object.defineProperty(exports, '__esModule', { value: !0 }), 83 | (exports.resetAction = exports.decrementAction = exports.incrementAction = void 0); 84 | const reducer_1 = __webpack_require__(9269); 85 | exports.incrementAction = () => ({ type: reducer_1.INCREMENT_COUNTER }); 86 | exports.decrementAction = () => ({ type: reducer_1.DECREMENT_COUNTER }); 87 | exports.resetAction = () => ({ type: reducer_1.RESET_COUNTER }); 88 | }, 89 | }, 90 | ]); 91 | -------------------------------------------------------------------------------- /docs/components-Sections-ReactRouter-Routes-IncrementRoute.b39cfef421931f6623fe.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunkreact_boilerplate = self.webpackChunkreact_boilerplate || []).push([ 2 | [715], 3 | { 4 | 3843: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 5 | 'use strict'; 6 | __webpack_require__.r(__webpack_exports__); 7 | }, 8 | 6769: function (__unused_webpack_module, exports, __webpack_require__) { 9 | 'use strict'; 10 | var __importDefault = 11 | (this && this.__importDefault) || 12 | function (mod) { 13 | return mod && mod.__esModule ? mod : { default: mod }; 14 | }; 15 | Object.defineProperty(exports, '__esModule', { value: !0 }); 16 | const react_1 = __importDefault(__webpack_require__(7294)), 17 | RouteContent_1 = __importDefault(__webpack_require__(3672)), 18 | actions_1 = __webpack_require__(750); 19 | exports.default = () => 20 | react_1.default.createElement(RouteContent_1.default, { 21 | icon: 'plus', 22 | path: '/', 23 | label: 'Increment', 24 | action: actions_1.incrementAction, 25 | }); 26 | }, 27 | 3672: function (__unused_webpack_module, exports, __webpack_require__) { 28 | 'use strict'; 29 | var __importDefault = 30 | (this && this.__importDefault) || 31 | function (mod) { 32 | return mod && mod.__esModule ? mod : { default: mod }; 33 | }; 34 | Object.defineProperty(exports, '__esModule', { value: !0 }); 35 | const react_1 = __importDefault(__webpack_require__(7294)), 36 | bind_1 = __importDefault(__webpack_require__(7166)), 37 | react_redux_1 = __webpack_require__(8629), 38 | Icon_1 = __importDefault(__webpack_require__(8055)), 39 | RouteContent_scss_1 = __importDefault(__webpack_require__(3843)), 40 | cx = bind_1.default.bind(RouteContent_scss_1.default); 41 | exports.default = ({ path, label, action, icon }) => { 42 | const dispatch = react_redux_1.useDispatch(), 43 | counter = react_redux_1.useSelector((state) => state.counter); 44 | return react_1.default.createElement( 45 | 'div', 46 | { className: cx('route-content--container') }, 47 | react_1.default.createElement( 48 | 'div', 49 | { className: cx('route-content--heading') }, 50 | react_1.default.createElement(Icon_1.default, { icon: 'angle-right' }), 51 | ' Connected to the Redux store at the ', 52 | react_1.default.createElement('code', null, path || '/'), 53 | ' route' 54 | ), 55 | react_1.default.createElement( 56 | 'div', 57 | { className: `${cx('route-content--counter')} m-t-xs` }, 58 | react_1.default.createElement(Icon_1.default, { icon: 'angle-right' }), 59 | ' ', 60 | react_1.default.createElement('code', null, 'counter'), 61 | ': ', 62 | react_1.default.createElement('code', null, counter) 63 | ), 64 | react_1.default.createElement('br', null), 65 | react_1.default.createElement( 66 | 'div', 67 | { className: 'm-t-sm' }, 68 | react_1.default.createElement( 69 | 'button', 70 | { className: 'button', onClick: () => dispatch(action()) }, 71 | react_1.default.createElement(Icon_1.default, { icon }), 72 | ' ', 73 | label, 74 | ' counter' 75 | ) 76 | ) 77 | ); 78 | }; 79 | }, 80 | 750: function (__unused_webpack_module, exports, __webpack_require__) { 81 | 'use strict'; 82 | Object.defineProperty(exports, '__esModule', { value: !0 }), 83 | (exports.resetAction = exports.decrementAction = exports.incrementAction = void 0); 84 | const reducer_1 = __webpack_require__(9269); 85 | exports.incrementAction = () => ({ type: reducer_1.INCREMENT_COUNTER }); 86 | exports.decrementAction = () => ({ type: reducer_1.DECREMENT_COUNTER }); 87 | exports.resetAction = () => ({ type: reducer_1.RESET_COUNTER }); 88 | }, 89 | }, 90 | ]); 91 | -------------------------------------------------------------------------------- /docs/components-Sections-ReactRouter-Routes-ResetRoute.b39cfef421931f6623fe.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunkreact_boilerplate = self.webpackChunkreact_boilerplate || []).push([ 2 | [956], 3 | { 4 | 3843: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 5 | 'use strict'; 6 | __webpack_require__.r(__webpack_exports__); 7 | }, 8 | 9021: function (__unused_webpack_module, exports, __webpack_require__) { 9 | 'use strict'; 10 | var __importDefault = 11 | (this && this.__importDefault) || 12 | function (mod) { 13 | return mod && mod.__esModule ? mod : { default: mod }; 14 | }; 15 | Object.defineProperty(exports, '__esModule', { value: !0 }); 16 | const react_1 = __importDefault(__webpack_require__(7294)), 17 | RouteContent_1 = __importDefault(__webpack_require__(3672)), 18 | actions_1 = __webpack_require__(750); 19 | exports.default = () => 20 | react_1.default.createElement(RouteContent_1.default, { 21 | icon: 'history', 22 | path: '/reset', 23 | label: 'Reset', 24 | action: actions_1.resetAction, 25 | }); 26 | }, 27 | 3672: function (__unused_webpack_module, exports, __webpack_require__) { 28 | 'use strict'; 29 | var __importDefault = 30 | (this && this.__importDefault) || 31 | function (mod) { 32 | return mod && mod.__esModule ? mod : { default: mod }; 33 | }; 34 | Object.defineProperty(exports, '__esModule', { value: !0 }); 35 | const react_1 = __importDefault(__webpack_require__(7294)), 36 | bind_1 = __importDefault(__webpack_require__(7166)), 37 | react_redux_1 = __webpack_require__(8629), 38 | Icon_1 = __importDefault(__webpack_require__(8055)), 39 | RouteContent_scss_1 = __importDefault(__webpack_require__(3843)), 40 | cx = bind_1.default.bind(RouteContent_scss_1.default); 41 | exports.default = ({ path, label, action, icon }) => { 42 | const dispatch = react_redux_1.useDispatch(), 43 | counter = react_redux_1.useSelector((state) => state.counter); 44 | return react_1.default.createElement( 45 | 'div', 46 | { className: cx('route-content--container') }, 47 | react_1.default.createElement( 48 | 'div', 49 | { className: cx('route-content--heading') }, 50 | react_1.default.createElement(Icon_1.default, { icon: 'angle-right' }), 51 | ' Connected to the Redux store at the ', 52 | react_1.default.createElement('code', null, path || '/'), 53 | ' route' 54 | ), 55 | react_1.default.createElement( 56 | 'div', 57 | { className: `${cx('route-content--counter')} m-t-xs` }, 58 | react_1.default.createElement(Icon_1.default, { icon: 'angle-right' }), 59 | ' ', 60 | react_1.default.createElement('code', null, 'counter'), 61 | ': ', 62 | react_1.default.createElement('code', null, counter) 63 | ), 64 | react_1.default.createElement('br', null), 65 | react_1.default.createElement( 66 | 'div', 67 | { className: 'm-t-sm' }, 68 | react_1.default.createElement( 69 | 'button', 70 | { className: 'button', onClick: () => dispatch(action()) }, 71 | react_1.default.createElement(Icon_1.default, { icon }), 72 | ' ', 73 | label, 74 | ' counter' 75 | ) 76 | ) 77 | ); 78 | }; 79 | }, 80 | 750: function (__unused_webpack_module, exports, __webpack_require__) { 81 | 'use strict'; 82 | Object.defineProperty(exports, '__esModule', { value: !0 }), 83 | (exports.resetAction = exports.decrementAction = exports.incrementAction = void 0); 84 | const reducer_1 = __webpack_require__(9269); 85 | exports.incrementAction = () => ({ type: reducer_1.INCREMENT_COUNTER }); 86 | exports.decrementAction = () => ({ type: reducer_1.DECREMENT_COUNTER }); 87 | exports.resetAction = () => ({ type: reducer_1.RESET_COUNTER }); 88 | }, 89 | }, 90 | ]); 91 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikechabot/react-boilerplate/c45505edb9209a9d9ec5dd8b8ba176ba6f85fbee/docs/favicon.ico -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 18 | 19 | 20 | 21 | 24 | react-boilerplate 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/main.b39cfef421931f6623fe.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunkreact_boilerplate = self.webpackChunkreact_boilerplate || []).push([ 2 | [179], 3 | { 4 | 9024: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 5 | 'use strict'; 6 | __webpack_require__.r(__webpack_exports__); 7 | var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7294), 8 | p_min_delay__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2959), 9 | p_min_delay__WEBPACK_IMPORTED_MODULE_1___default = __webpack_require__.n( 10 | p_min_delay__WEBPACK_IMPORTED_MODULE_1__ 11 | ), 12 | _loadable_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2168), 13 | classnames_bind__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7166), 14 | classnames_bind__WEBPACK_IMPORTED_MODULE_3___default = __webpack_require__.n( 15 | classnames_bind__WEBPACK_IMPORTED_MODULE_3__ 16 | ), 17 | react_router_dom__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5977), 18 | react_tabify__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5817), 19 | react_tabify__WEBPACK_IMPORTED_MODULE_4___default = __webpack_require__.n( 20 | react_tabify__WEBPACK_IMPORTED_MODULE_4__ 21 | ), 22 | _components_Sections_ReactRouter_ChunkLoadingIcon__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1746), 23 | _components_Sections_ReactRouter_ChunkLoadingIcon__WEBPACK_IMPORTED_MODULE_5___default = __webpack_require__.n( 24 | _components_Sections_ReactRouter_ChunkLoadingIcon__WEBPACK_IMPORTED_MODULE_5__ 25 | ), 26 | DELAY = 500, 27 | options = { 28 | fallback: react__WEBPACK_IMPORTED_MODULE_0__.createElement( 29 | _components_Sections_ReactRouter_ChunkLoadingIcon__WEBPACK_IMPORTED_MODULE_5___default(), 30 | null 31 | ), 32 | }, 33 | AsyncIncrement = (0, _loadable_component__WEBPACK_IMPORTED_MODULE_2__.ZP)( 34 | { 35 | resolved: {}, 36 | chunkName: () => 'components-Sections-ReactRouter-Routes-IncrementRoute', 37 | isReady(props) { 38 | var key = this.resolve(props); 39 | return !0 === this.resolved[key] && !!__webpack_require__.m[key]; 40 | }, 41 | importAsync: () => 42 | p_min_delay__WEBPACK_IMPORTED_MODULE_1___default()( 43 | __webpack_require__.e(715).then(__webpack_require__.t.bind(__webpack_require__, 6769, 23)), 44 | DELAY 45 | ), 46 | requireAsync(props) { 47 | var key = this.resolve(props); 48 | return ( 49 | (this.resolved[key] = !1), 50 | this.importAsync(props).then((resolved) => ((this.resolved[key] = !0), resolved)) 51 | ); 52 | }, 53 | requireSync(props) { 54 | var id = this.resolve(props); 55 | return __webpack_require__(id); 56 | }, 57 | resolve() { 58 | return 6769; 59 | }, 60 | }, 61 | options 62 | ), 63 | AsyncDecrement = (0, _loadable_component__WEBPACK_IMPORTED_MODULE_2__.ZP)( 64 | { 65 | resolved: {}, 66 | chunkName: () => 'components-Sections-ReactRouter-Routes-DecrementRoute', 67 | isReady(props) { 68 | var key = this.resolve(props); 69 | return !0 === this.resolved[key] && !!__webpack_require__.m[key]; 70 | }, 71 | importAsync: () => 72 | p_min_delay__WEBPACK_IMPORTED_MODULE_1___default()( 73 | __webpack_require__.e(896).then(__webpack_require__.t.bind(__webpack_require__, 2522, 23)), 74 | DELAY 75 | ), 76 | requireAsync(props) { 77 | var key = this.resolve(props); 78 | return ( 79 | (this.resolved[key] = !1), 80 | this.importAsync(props).then((resolved) => ((this.resolved[key] = !0), resolved)) 81 | ); 82 | }, 83 | requireSync(props) { 84 | var id = this.resolve(props); 85 | return __webpack_require__(id); 86 | }, 87 | resolve() { 88 | return 2522; 89 | }, 90 | }, 91 | options 92 | ), 93 | AsyncReset = (0, _loadable_component__WEBPACK_IMPORTED_MODULE_2__.ZP)( 94 | { 95 | resolved: {}, 96 | chunkName: () => 'components-Sections-ReactRouter-Routes-ResetRoute', 97 | isReady(props) { 98 | var key = this.resolve(props); 99 | return !0 === this.resolved[key] && !!__webpack_require__.m[key]; 100 | }, 101 | importAsync: () => 102 | p_min_delay__WEBPACK_IMPORTED_MODULE_1___default()( 103 | __webpack_require__.e(956).then(__webpack_require__.t.bind(__webpack_require__, 9021, 23)), 104 | DELAY 105 | ), 106 | requireAsync(props) { 107 | var key = this.resolve(props); 108 | return ( 109 | (this.resolved[key] = !1), 110 | this.importAsync(props).then((resolved) => ((this.resolved[key] = !0), resolved)) 111 | ); 112 | }, 113 | requireSync(props) { 114 | var id = this.resolve(props); 115 | return __webpack_require__(id); 116 | }, 117 | resolve() { 118 | return 9021; 119 | }, 120 | }, 121 | options 122 | ), 123 | AsyncTabbedRouter = () => { 124 | var location = (0, react_router_dom__WEBPACK_IMPORTED_MODULE_6__.TH)(), 125 | history = (0, react_router_dom__WEBPACK_IMPORTED_MODULE_6__.k6)(); 126 | return react__WEBPACK_IMPORTED_MODULE_0__.createElement( 127 | 'div', 128 | { className: 'notification m-t-sm' }, 129 | react__WEBPACK_IMPORTED_MODULE_0__.createElement( 130 | react_tabify__WEBPACK_IMPORTED_MODULE_4__.Tabs, 131 | { 132 | id: 'router-example-tabs', 133 | activeKey: location.pathname, 134 | onSelect: (eventKey) => history.push(eventKey), 135 | }, 136 | react__WEBPACK_IMPORTED_MODULE_0__.createElement( 137 | react_tabify__WEBPACK_IMPORTED_MODULE_4__.Tab, 138 | { eventKey: '/', label: 'Increment' }, 139 | react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_6__.AW, { 140 | exact: !0, 141 | path: '/', 142 | component: AsyncIncrement, 143 | }) 144 | ), 145 | react__WEBPACK_IMPORTED_MODULE_0__.createElement( 146 | react_tabify__WEBPACK_IMPORTED_MODULE_4__.Tab, 147 | { eventKey: '/decrement', label: 'Decrement' }, 148 | react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_6__.AW, { 149 | exact: !0, 150 | path: '/decrement', 151 | component: AsyncDecrement, 152 | }) 153 | ), 154 | react__WEBPACK_IMPORTED_MODULE_0__.createElement( 155 | react_tabify__WEBPACK_IMPORTED_MODULE_4__.Tab, 156 | { eventKey: '/reset', label: 'Reset' }, 157 | react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_6__.AW, { 158 | exact: !0, 159 | path: '/reset', 160 | component: AsyncReset, 161 | }) 162 | ) 163 | ) 164 | ); 165 | }; 166 | __webpack_exports__.default = AsyncTabbedRouter; 167 | }, 168 | 3018: function (module, __unused_webpack_exports, __webpack_require__) { 169 | var NodeUtils = __webpack_require__(8720), 170 | get = __webpack_require__(7361); 171 | module.exports = { 172 | getConfig: () => ({ 173 | example: { port: 3060, baseUrl: 'http://localhost:3020/', publicBasename: 'react-boilerplate/' }, 174 | }), 175 | getProperty(key) { 176 | if (!key) throw new Error('Key cannot be null/undefined'); 177 | return get(this.getConfig(), key); 178 | }, 179 | getRequiredProperty(key) { 180 | var value = this.getProperty(key); 181 | if (value) return value; 182 | if (!NodeUtils.isTest()) throw new Error('Missing required property: "'.concat(key, '"')); 183 | }, 184 | getPort() { 185 | return this.getRequiredProperty('example.port'); 186 | }, 187 | getBasePath() { 188 | return this.getRequiredProperty('example.basePath'); 189 | }, 190 | getBaseUrl() { 191 | return this.getRequiredProperty('example.baseUrl'); 192 | }, 193 | getPublicBasename() { 194 | return NodeUtils.isGhPages() ? this.getRequiredProperty('example.publicBasename') : '/'; 195 | }, 196 | }; 197 | }, 198 | 8720: function (module) { 199 | 'use strict'; 200 | module.exports = { 201 | getNodeEnv: function getNodeEnv() { 202 | return { 203 | NODE_ENV: 'gh-pages', 204 | APP_CONFIG: { 205 | example: { port: 3060, baseUrl: 'http://localhost:3020/', publicBasename: 'react-boilerplate/' }, 206 | }, 207 | }; 208 | }, 209 | getNodeEnvByKey: function getNodeEnvByKey(key) { 210 | if (!key) throw new Error('Key cannot be null/undefined'); 211 | return { 212 | NODE_ENV: 'gh-pages', 213 | APP_CONFIG: { 214 | example: { port: 3060, baseUrl: 'http://localhost:3020/', publicBasename: 'react-boilerplate/' }, 215 | }, 216 | }[key]; 217 | }, 218 | getNodeEnvMode: function getNodeEnvMode() { 219 | return this.getNodeEnvByKey('NODE_ENV') || 'test'; 220 | }, 221 | isProduction: function isProduction() { 222 | return 'production' === this.getNodeEnvMode(); 223 | }, 224 | isDevelopment: function isDevelopment() { 225 | return 'development' === this.getNodeEnvMode(); 226 | }, 227 | isGhPages: function isGhPages() { 228 | return 'gh-pages' === this.getNodeEnvMode(); 229 | }, 230 | isTest: function isTest() { 231 | return !this.getNodeEnvMode() || 'test' === this.getNodeEnvMode(); 232 | }, 233 | }; 234 | }, 235 | 5834: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 236 | 'use strict'; 237 | __webpack_require__.r(__webpack_exports__), (__webpack_exports__.default = __webpack_require__.p + 'favicon.ico'); 238 | }, 239 | 9234: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 240 | 'use strict'; 241 | __webpack_require__.r(__webpack_exports__); 242 | }, 243 | 8395: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 244 | 'use strict'; 245 | __webpack_require__.r(__webpack_exports__); 246 | }, 247 | 1914: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 248 | 'use strict'; 249 | __webpack_require__.r(__webpack_exports__); 250 | }, 251 | 4689: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 252 | 'use strict'; 253 | __webpack_require__.r(__webpack_exports__); 254 | }, 255 | 9938: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 256 | 'use strict'; 257 | __webpack_require__.r(__webpack_exports__); 258 | }, 259 | 3334: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 260 | 'use strict'; 261 | __webpack_require__.r(__webpack_exports__); 262 | }, 263 | 5094: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 264 | 'use strict'; 265 | __webpack_require__.r(__webpack_exports__); 266 | }, 267 | 3463: function (__unused_webpack_module, exports, __webpack_require__) { 268 | 'use strict'; 269 | var __createBinding = 270 | (this && this.__createBinding) || 271 | (Object.create 272 | ? function (o, m, k, k2) { 273 | void 0 === k2 && (k2 = k), 274 | Object.defineProperty(o, k2, { 275 | enumerable: !0, 276 | get: function () { 277 | return m[k]; 278 | }, 279 | }); 280 | } 281 | : function (o, m, k, k2) { 282 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 283 | }), 284 | __setModuleDefault = 285 | (this && this.__setModuleDefault) || 286 | (Object.create 287 | ? function (o, v) { 288 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 289 | } 290 | : function (o, v) { 291 | o.default = v; 292 | }), 293 | __importStar = 294 | (this && this.__importStar) || 295 | function (mod) { 296 | if (mod && mod.__esModule) return mod; 297 | var result = {}; 298 | if (null != mod) 299 | for (var k in mod) 300 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 301 | return __setModuleDefault(result, mod), result; 302 | }, 303 | __importDefault = 304 | (this && this.__importDefault) || 305 | function (mod) { 306 | return mod && mod.__esModule ? mod : { default: mod }; 307 | }; 308 | Object.defineProperty(exports, '__esModule', { value: !0 }); 309 | const React = __importStar(__webpack_require__(7294)), 310 | react_dom_1 = __importDefault(__webpack_require__(3935)), 311 | react_hot_loader_1 = __webpack_require__(5053), 312 | store_1 = __importDefault(__webpack_require__(5908)), 313 | Root_1 = __importDefault(__webpack_require__(2556)); 314 | __webpack_require__(5094), 315 | __webpack_require__(5834), 316 | react_dom_1.default.render( 317 | React.createElement( 318 | react_hot_loader_1.AppContainer, 319 | null, 320 | React.createElement(Root_1.default, { store: store_1.default }) 321 | ), 322 | document.getElementById('example-app') 323 | ); 324 | }, 325 | 2556: function (__unused_webpack_module, exports, __webpack_require__) { 326 | 'use strict'; 327 | var __createBinding = 328 | (this && this.__createBinding) || 329 | (Object.create 330 | ? function (o, m, k, k2) { 331 | void 0 === k2 && (k2 = k), 332 | Object.defineProperty(o, k2, { 333 | enumerable: !0, 334 | get: function () { 335 | return m[k]; 336 | }, 337 | }); 338 | } 339 | : function (o, m, k, k2) { 340 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 341 | }), 342 | __setModuleDefault = 343 | (this && this.__setModuleDefault) || 344 | (Object.create 345 | ? function (o, v) { 346 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 347 | } 348 | : function (o, v) { 349 | o.default = v; 350 | }), 351 | __importStar = 352 | (this && this.__importStar) || 353 | function (mod) { 354 | if (mod && mod.__esModule) return mod; 355 | var result = {}; 356 | if (null != mod) 357 | for (var k in mod) 358 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 359 | return __setModuleDefault(result, mod), result; 360 | }, 361 | __importDefault = 362 | (this && this.__importDefault) || 363 | function (mod) { 364 | return mod && mod.__esModule ? mod : { default: mod }; 365 | }; 366 | Object.defineProperty(exports, '__esModule', { value: !0 }); 367 | const React = __importStar(__webpack_require__(7294)), 368 | react_redux_1 = __webpack_require__(8629), 369 | react_router_dom_1 = __webpack_require__(3727), 370 | config_service_1 = __importDefault(__webpack_require__(3018)), 371 | App_1 = __importDefault(__webpack_require__(78)); 372 | exports.default = ({ store }) => 373 | React.createElement( 374 | react_redux_1.Provider, 375 | { store }, 376 | React.createElement( 377 | react_router_dom_1.BrowserRouter, 378 | { basename: config_service_1.default.getPublicBasename() }, 379 | React.createElement(App_1.default, null) 380 | ) 381 | ); 382 | }, 383 | 78: function (__unused_webpack_module, exports, __webpack_require__) { 384 | 'use strict'; 385 | var __importDefault = 386 | (this && this.__importDefault) || 387 | function (mod) { 388 | return mod && mod.__esModule ? mod : { default: mod }; 389 | }; 390 | Object.defineProperty(exports, '__esModule', { value: !0 }); 391 | const react_1 = __importDefault(__webpack_require__(7294)), 392 | bind_1 = __importDefault(__webpack_require__(7166)), 393 | Navbar_1 = __importDefault(__webpack_require__(975)), 394 | Footer_1 = __importDefault(__webpack_require__(2181)), 395 | ReactRouter_1 = __importDefault(__webpack_require__(6231)), 396 | ReduxEntity_1 = __importDefault(__webpack_require__(2323)), 397 | ReduxState_1 = __importDefault(__webpack_require__(1198)), 398 | App_scss_1 = __importDefault(__webpack_require__(3334)), 399 | cx = bind_1.default.bind(App_scss_1.default); 400 | exports.default = () => 401 | react_1.default.createElement( 402 | 'section', 403 | { className: cx('react-boilerplate') }, 404 | react_1.default.createElement(Navbar_1.default, null), 405 | react_1.default.createElement( 406 | 'section', 407 | { className: `section ${cx('section--body')}` }, 408 | react_1.default.createElement( 409 | 'div', 410 | { className: 'container' }, 411 | react_1.default.createElement( 412 | 'div', 413 | { className: 'columns' }, 414 | react_1.default.createElement( 415 | 'div', 416 | { className: 'column' }, 417 | react_1.default.createElement(ReactRouter_1.default, null) 418 | ) 419 | ), 420 | react_1.default.createElement( 421 | 'div', 422 | { className: 'columns' }, 423 | react_1.default.createElement( 424 | 'div', 425 | { className: 'column' }, 426 | react_1.default.createElement(ReduxEntity_1.default, null) 427 | ), 428 | react_1.default.createElement( 429 | 'div', 430 | { className: 'column' }, 431 | react_1.default.createElement(ReduxState_1.default, null) 432 | ) 433 | ) 434 | ) 435 | ), 436 | react_1.default.createElement(Footer_1.default, null) 437 | ); 438 | }, 439 | 6418: function (__unused_webpack_module, exports, __webpack_require__) { 440 | 'use strict'; 441 | var __createBinding = 442 | (this && this.__createBinding) || 443 | (Object.create 444 | ? function (o, m, k, k2) { 445 | void 0 === k2 && (k2 = k), 446 | Object.defineProperty(o, k2, { 447 | enumerable: !0, 448 | get: function () { 449 | return m[k]; 450 | }, 451 | }); 452 | } 453 | : function (o, m, k, k2) { 454 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 455 | }), 456 | __setModuleDefault = 457 | (this && this.__setModuleDefault) || 458 | (Object.create 459 | ? function (o, v) { 460 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 461 | } 462 | : function (o, v) { 463 | o.default = v; 464 | }), 465 | __importStar = 466 | (this && this.__importStar) || 467 | function (mod) { 468 | if (mod && mod.__esModule) return mod; 469 | var result = {}; 470 | if (null != mod) 471 | for (var k in mod) 472 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 473 | return __setModuleDefault(result, mod), result; 474 | }, 475 | __importDefault = 476 | (this && this.__importDefault) || 477 | function (mod) { 478 | return mod && mod.__esModule ? mod : { default: mod }; 479 | }; 480 | Object.defineProperty(exports, '__esModule', { value: !0 }); 481 | const React = __importStar(__webpack_require__(7294)), 482 | common_1 = __webpack_require__(1256), 483 | GithubButtons_1 = __importDefault(__webpack_require__(6707)), 484 | const_1 = __webpack_require__(5365), 485 | Repository = () => 486 | React.createElement( 487 | 'strong', 488 | { className: 'has-text-grey-light' }, 489 | React.createElement(common_1.Icon, { icon: 'cloud' }), 490 | ' react-boilerplate' 491 | ), 492 | DemoLink = () => React.createElement(common_1.Link, { url: const_1.URL.DEMO }, 'source code'), 493 | GithubLink = () => React.createElement(common_1.Link, { url: const_1.URL.GITHUB }, 'Mike Chabot'), 494 | LicenseLink = () => React.createElement(common_1.Link, { url: const_1.URL.LICENSE }, 'MIT'); 495 | exports.default = () => 496 | React.createElement( 497 | 'footer', 498 | { className: 'footer has-text-grey-light' }, 499 | React.createElement( 500 | 'div', 501 | { className: 'container has-text-centered' }, 502 | React.createElement( 503 | 'div', 504 | null, 505 | React.createElement(Repository, null), 506 | ' by ', 507 | React.createElement(GithubLink, null) 508 | ), 509 | React.createElement( 510 | 'div', 511 | { className: 'm-t-xs' }, 512 | 'The ', 513 | React.createElement(DemoLink, null), 514 | ' is licensed under ', 515 | React.createElement(LicenseLink, null) 516 | ), 517 | React.createElement(GithubButtons_1.default, null) 518 | ) 519 | ); 520 | }, 521 | 7695: function (__unused_webpack_module, exports, __webpack_require__) { 522 | 'use strict'; 523 | var __createBinding = 524 | (this && this.__createBinding) || 525 | (Object.create 526 | ? function (o, m, k, k2) { 527 | void 0 === k2 && (k2 = k), 528 | Object.defineProperty(o, k2, { 529 | enumerable: !0, 530 | get: function () { 531 | return m[k]; 532 | }, 533 | }); 534 | } 535 | : function (o, m, k, k2) { 536 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 537 | }), 538 | __setModuleDefault = 539 | (this && this.__setModuleDefault) || 540 | (Object.create 541 | ? function (o, v) { 542 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 543 | } 544 | : function (o, v) { 545 | o.default = v; 546 | }), 547 | __importStar = 548 | (this && this.__importStar) || 549 | function (mod) { 550 | if (mod && mod.__esModule) return mod; 551 | var result = {}; 552 | if (null != mod) 553 | for (var k in mod) 554 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 555 | return __setModuleDefault(result, mod), result; 556 | }, 557 | __importDefault = 558 | (this && this.__importDefault) || 559 | function (mod) { 560 | return mod && mod.__esModule ? mod : { default: mod }; 561 | }; 562 | Object.defineProperty(exports, '__esModule', { value: !0 }); 563 | const React = __importStar(__webpack_require__(7294)), 564 | bind_1 = __importDefault(__webpack_require__(7166)), 565 | GithubButton_scss_1 = __importDefault(__webpack_require__(9234)), 566 | cx = bind_1.default.bind(GithubButton_scss_1.default); 567 | exports.default = ({ label, icon, href, ariaLabel }) => 568 | React.createElement( 569 | 'div', 570 | { className: cx('github-button--container') }, 571 | React.createElement( 572 | 'a', 573 | { 574 | className: 'github-button', 575 | href: `https://github.com/${href}`, 576 | 'data-icon': icon, 577 | 'data-size': 'large', 578 | 'data-show-count': !0, 579 | 'aria-label': ariaLabel, 580 | }, 581 | label 582 | ) 583 | ); 584 | }, 585 | 969: function (__unused_webpack_module, exports, __webpack_require__) { 586 | 'use strict'; 587 | var __createBinding = 588 | (this && this.__createBinding) || 589 | (Object.create 590 | ? function (o, m, k, k2) { 591 | void 0 === k2 && (k2 = k), 592 | Object.defineProperty(o, k2, { 593 | enumerable: !0, 594 | get: function () { 595 | return m[k]; 596 | }, 597 | }); 598 | } 599 | : function (o, m, k, k2) { 600 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 601 | }), 602 | __setModuleDefault = 603 | (this && this.__setModuleDefault) || 604 | (Object.create 605 | ? function (o, v) { 606 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 607 | } 608 | : function (o, v) { 609 | o.default = v; 610 | }), 611 | __importStar = 612 | (this && this.__importStar) || 613 | function (mod) { 614 | if (mod && mod.__esModule) return mod; 615 | var result = {}; 616 | if (null != mod) 617 | for (var k in mod) 618 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 619 | return __setModuleDefault(result, mod), result; 620 | }, 621 | __importDefault = 622 | (this && this.__importDefault) || 623 | function (mod) { 624 | return mod && mod.__esModule ? mod : { default: mod }; 625 | }; 626 | Object.defineProperty(exports, '__esModule', { value: !0 }); 627 | const React = __importStar(__webpack_require__(7294)), 628 | bind_1 = __importDefault(__webpack_require__(7166)), 629 | GithubButton_1 = __importDefault(__webpack_require__(7695)), 630 | GithubButtons_scss_1 = __importDefault(__webpack_require__(8395)), 631 | cx = bind_1.default.bind(GithubButtons_scss_1.default); 632 | exports.default = () => 633 | React.createElement( 634 | 'div', 635 | { className: `${cx('github-buttons')} m-t-sm` }, 636 | React.createElement(GithubButton_1.default, { 637 | label: 'Star', 638 | icon: 'octicon-star', 639 | href: 'mikechabot/react-boilerplate', 640 | ariaLabel: 'Star mikechabot/react-boilerplate on GitHub', 641 | }), 642 | React.createElement(GithubButton_1.default, { 643 | label: 'Fork', 644 | icon: 'octicon-repo-forked', 645 | href: 'mikechabot/react-boilerplate/fork', 646 | ariaLabel: 'Fork mikechabot/react-boilerplate on GitHub', 647 | }), 648 | React.createElement(GithubButton_1.default, { 649 | label: 'Watch', 650 | icon: 'octicon-eye', 651 | href: 'mikechabot/react-boilerplate/subscription', 652 | ariaLabel: 'Watch mikechabot/react-boilerplate on GitHub', 653 | }) 654 | ); 655 | }, 656 | 6707: function (__unused_webpack_module, exports, __webpack_require__) { 657 | 'use strict'; 658 | var __importDefault = 659 | (this && this.__importDefault) || 660 | function (mod) { 661 | return mod && mod.__esModule ? mod : { default: mod }; 662 | }; 663 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.default = void 0); 664 | var GithubButtons_1 = __webpack_require__(969); 665 | Object.defineProperty(exports, 'default', { 666 | enumerable: !0, 667 | get: function () { 668 | return __importDefault(GithubButtons_1).default; 669 | }, 670 | }); 671 | }, 672 | 2181: function (__unused_webpack_module, exports, __webpack_require__) { 673 | 'use strict'; 674 | var __importDefault = 675 | (this && this.__importDefault) || 676 | function (mod) { 677 | return mod && mod.__esModule ? mod : { default: mod }; 678 | }; 679 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.default = void 0); 680 | var Footer_1 = __webpack_require__(6418); 681 | Object.defineProperty(exports, 'default', { 682 | enumerable: !0, 683 | get: function () { 684 | return __importDefault(Footer_1).default; 685 | }, 686 | }); 687 | }, 688 | 347: function (__unused_webpack_module, exports, __webpack_require__) { 689 | 'use strict'; 690 | var __createBinding = 691 | (this && this.__createBinding) || 692 | (Object.create 693 | ? function (o, m, k, k2) { 694 | void 0 === k2 && (k2 = k), 695 | Object.defineProperty(o, k2, { 696 | enumerable: !0, 697 | get: function () { 698 | return m[k]; 699 | }, 700 | }); 701 | } 702 | : function (o, m, k, k2) { 703 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 704 | }), 705 | __setModuleDefault = 706 | (this && this.__setModuleDefault) || 707 | (Object.create 708 | ? function (o, v) { 709 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 710 | } 711 | : function (o, v) { 712 | o.default = v; 713 | }), 714 | __importStar = 715 | (this && this.__importStar) || 716 | function (mod) { 717 | if (mod && mod.__esModule) return mod; 718 | var result = {}; 719 | if (null != mod) 720 | for (var k in mod) 721 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 722 | return __setModuleDefault(result, mod), result; 723 | }, 724 | __importDefault = 725 | (this && this.__importDefault) || 726 | function (mod) { 727 | return mod && mod.__esModule ? mod : { default: mod }; 728 | }; 729 | Object.defineProperty(exports, '__esModule', { value: !0 }); 730 | const React = __importStar(__webpack_require__(7294)), 731 | Icon_1 = __importDefault(__webpack_require__(8055)); 732 | exports.default = ({ title, subtitle, icon, children }) => 733 | React.createElement( 734 | React.Fragment, 735 | null, 736 | React.createElement( 737 | 'div', 738 | null, 739 | React.createElement( 740 | 'h1', 741 | { className: 'title' }, 742 | React.createElement(Icon_1.default, { icon, className: 'has-text-info' }), 743 | ' ', 744 | title 745 | ), 746 | React.createElement( 747 | 'h2', 748 | { className: 'subtitle ' }, 749 | React.createElement(Icon_1.default, { icon: 'angle-right' }), 750 | ' ', 751 | subtitle 752 | ) 753 | ), 754 | children 755 | ); 756 | }, 757 | 1746: function (__unused_webpack_module, exports, __webpack_require__) { 758 | 'use strict'; 759 | var __importDefault = 760 | (this && this.__importDefault) || 761 | function (mod) { 762 | return mod && mod.__esModule ? mod : { default: mod }; 763 | }; 764 | Object.defineProperty(exports, '__esModule', { value: !0 }); 765 | const react_1 = __importDefault(__webpack_require__(7294)), 766 | bind_1 = __importDefault(__webpack_require__(7166)), 767 | Icon_1 = __webpack_require__(8055), 768 | ChunkLoadingIcon_scss_1 = __importDefault(__webpack_require__(1914)), 769 | cx = bind_1.default.bind(ChunkLoadingIcon_scss_1.default); 770 | exports.default = () => 771 | react_1.default.createElement( 772 | 'div', 773 | { className: `p-t-md ${cx('chunk-loading--icon')}` }, 774 | react_1.default.createElement(Icon_1.CogIcon, { size: 'fa-2x', className: 'has-text-info' }) 775 | ); 776 | }, 777 | 1860: function (__unused_webpack_module, exports, __webpack_require__) { 778 | 'use strict'; 779 | var __createBinding = 780 | (this && this.__createBinding) || 781 | (Object.create 782 | ? function (o, m, k, k2) { 783 | void 0 === k2 && (k2 = k), 784 | Object.defineProperty(o, k2, { 785 | enumerable: !0, 786 | get: function () { 787 | return m[k]; 788 | }, 789 | }); 790 | } 791 | : function (o, m, k, k2) { 792 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 793 | }), 794 | __setModuleDefault = 795 | (this && this.__setModuleDefault) || 796 | (Object.create 797 | ? function (o, v) { 798 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 799 | } 800 | : function (o, v) { 801 | o.default = v; 802 | }), 803 | __importStar = 804 | (this && this.__importStar) || 805 | function (mod) { 806 | if (mod && mod.__esModule) return mod; 807 | var result = {}; 808 | if (null != mod) 809 | for (var k in mod) 810 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 811 | return __setModuleDefault(result, mod), result; 812 | }, 813 | __importDefault = 814 | (this && this.__importDefault) || 815 | function (mod) { 816 | return mod && mod.__esModule ? mod : { default: mod }; 817 | }; 818 | Object.defineProperty(exports, '__esModule', { value: !0 }); 819 | const React = __importStar(__webpack_require__(7294)), 820 | GenericSection_1 = __importDefault(__webpack_require__(347)), 821 | AsyncTabbedRouter_1 = __importDefault(__webpack_require__(9024)), 822 | const_1 = __webpack_require__(5365); 823 | exports.default = () => 824 | React.createElement( 825 | GenericSection_1.default, 826 | { 827 | icon: 'link', 828 | title: 'Router', 829 | subtitle: React.createElement( 830 | 'span', 831 | null, 832 | 'Utilizes ', 833 | React.createElement('a', { href: const_1.URL.REACT_ROUTER }, 'react-router'), 834 | ' v5 for client-side routing' 835 | ), 836 | }, 837 | React.createElement(AsyncTabbedRouter_1.default, null) 838 | ); 839 | }, 840 | 6231: function (__unused_webpack_module, exports, __webpack_require__) { 841 | 'use strict'; 842 | var __importDefault = 843 | (this && this.__importDefault) || 844 | function (mod) { 845 | return mod && mod.__esModule ? mod : { default: mod }; 846 | }; 847 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.default = void 0); 848 | var ReactRouter_1 = __webpack_require__(1860); 849 | Object.defineProperty(exports, 'default', { 850 | enumerable: !0, 851 | get: function () { 852 | return __importDefault(ReactRouter_1).default; 853 | }, 854 | }); 855 | }, 856 | 3187: function (__unused_webpack_module, exports, __webpack_require__) { 857 | 'use strict'; 858 | var __importDefault = 859 | (this && this.__importDefault) || 860 | function (mod) { 861 | return mod && mod.__esModule ? mod : { default: mod }; 862 | }; 863 | Object.defineProperty(exports, '__esModule', { value: !0 }); 864 | const react_1 = __importDefault(__webpack_require__(7294)), 865 | bind_1 = __importDefault(__webpack_require__(7166)), 866 | react_redux_1 = __webpack_require__(8629), 867 | Entity_1 = __importDefault(__webpack_require__(3670)), 868 | actions_1 = __webpack_require__(6186), 869 | types_1 = __webpack_require__(55), 870 | ReduxEntity_scss_1 = __importDefault(__webpack_require__(4689)), 871 | cx = bind_1.default.bind(ReduxEntity_scss_1.default); 872 | exports.default = () => { 873 | const dispatch = react_redux_1.useDispatch(), 874 | entities = react_redux_1.useSelector((state) => state.entities), 875 | getLoadEntityThunk = (type) => { 876 | switch (type) { 877 | case types_1.EntityType.Foo: 878 | return () => dispatch(actions_1.fetchFoo()); 879 | case types_1.EntityType.Bar: 880 | return () => dispatch(actions_1.fetchBar()); 881 | case types_1.EntityType.Baz: 882 | return () => dispatch(actions_1.fetchBaz()); 883 | } 884 | }; 885 | return react_1.default.createElement( 886 | 'div', 887 | { className: `${cx('redux-entity--container')} notification is-light m-t-sm` }, 888 | Object.values(types_1.EntityType).map((key) => 889 | react_1.default.createElement(Entity_1.default, { 890 | key, 891 | name: key, 892 | append: key === types_1.EntityType.Bar, 893 | entity: entities[key], 894 | fetchEntity: getLoadEntityThunk(key), 895 | }) 896 | ) 897 | ); 898 | }; 899 | }, 900 | 3670: function (__unused_webpack_module, exports, __webpack_require__) { 901 | 'use strict'; 902 | var __createBinding = 903 | (this && this.__createBinding) || 904 | (Object.create 905 | ? function (o, m, k, k2) { 906 | void 0 === k2 && (k2 = k), 907 | Object.defineProperty(o, k2, { 908 | enumerable: !0, 909 | get: function () { 910 | return m[k]; 911 | }, 912 | }); 913 | } 914 | : function (o, m, k, k2) { 915 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 916 | }), 917 | __setModuleDefault = 918 | (this && this.__setModuleDefault) || 919 | (Object.create 920 | ? function (o, v) { 921 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 922 | } 923 | : function (o, v) { 924 | o.default = v; 925 | }), 926 | __importStar = 927 | (this && this.__importStar) || 928 | function (mod) { 929 | if (mod && mod.__esModule) return mod; 930 | var result = {}; 931 | if (null != mod) 932 | for (var k in mod) 933 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 934 | return __setModuleDefault(result, mod), result; 935 | }, 936 | __importDefault = 937 | (this && this.__importDefault) || 938 | function (mod) { 939 | return mod && mod.__esModule ? mod : { default: mod }; 940 | }; 941 | Object.defineProperty(exports, '__esModule', { value: !0 }); 942 | const react_1 = __importStar(__webpack_require__(7294)), 943 | react_redux_1 = __webpack_require__(8629), 944 | isEmpty_1 = __importDefault(__webpack_require__(1609)), 945 | common_1 = __webpack_require__(1256), 946 | EntityData_1 = __importDefault(__webpack_require__(9857)), 947 | EntityReset_1 = __importDefault(__webpack_require__(1065)), 948 | EntityMissing_1 = __importDefault(__webpack_require__(9197)), 949 | EntityFailure_1 = __importDefault(__webpack_require__(467)), 950 | EntityLoading_1 = __importDefault(__webpack_require__(3387)), 951 | redux_entity_1 = __webpack_require__(7694); 952 | exports.default = ({ name, append, entity, fetchEntity }) => { 953 | const dispatch = react_redux_1.useDispatch(); 954 | if ( 955 | (react_1.useEffect(() => { 956 | fetchEntity(); 957 | }, []), 958 | isEmpty_1.default(entity)) 959 | ) 960 | return react_1.default.createElement(EntityMissing_1.default, { name, fetchEntity }); 961 | const { isFetching, data, error, lastUpdated } = entity; 962 | let body; 963 | return ( 964 | (body = error 965 | ? react_1.default.createElement(EntityFailure_1.default, { name, error }) 966 | : isFetching 967 | ? react_1.default.createElement(EntityLoading_1.default, null) 968 | : isEmpty_1.default(data) 969 | ? react_1.default.createElement(EntityReset_1.default, { name }) 970 | : react_1.default.createElement(EntityData_1.default, { name, append, lastUpdated })), 971 | react_1.default.createElement( 972 | 'div', 973 | { className: 'm-b-sm' }, 974 | body, 975 | react_1.default.createElement( 976 | 'div', 977 | { className: 'field has-addons' }, 978 | react_1.default.createElement( 979 | common_1.Button, 980 | { icon: 'download', onClick: fetchEntity, disabled: isFetching, loading: isFetching, theme: 'is-info' }, 981 | 'Fetch' 982 | ), 983 | react_1.default.createElement( 984 | common_1.Button, 985 | { icon: 'history', onClick: () => dispatch(redux_entity_1.ResetEntity(name)), disabled: isFetching }, 986 | 'Reset' 987 | ), 988 | react_1.default.createElement( 989 | common_1.Button, 990 | { 991 | icon: 'trash', 992 | onClick: () => dispatch(redux_entity_1.DeleteEntity(name)), 993 | disabled: isFetching, 994 | theme: 'is-danger', 995 | }, 996 | 'Delete' 997 | ) 998 | ) 999 | ) 1000 | ); 1001 | }; 1002 | }, 1003 | 9857: function (__unused_webpack_module, exports, __webpack_require__) { 1004 | 'use strict'; 1005 | var __createBinding = 1006 | (this && this.__createBinding) || 1007 | (Object.create 1008 | ? function (o, m, k, k2) { 1009 | void 0 === k2 && (k2 = k), 1010 | Object.defineProperty(o, k2, { 1011 | enumerable: !0, 1012 | get: function () { 1013 | return m[k]; 1014 | }, 1015 | }); 1016 | } 1017 | : function (o, m, k, k2) { 1018 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 1019 | }), 1020 | __setModuleDefault = 1021 | (this && this.__setModuleDefault) || 1022 | (Object.create 1023 | ? function (o, v) { 1024 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 1025 | } 1026 | : function (o, v) { 1027 | o.default = v; 1028 | }), 1029 | __importStar = 1030 | (this && this.__importStar) || 1031 | function (mod) { 1032 | if (mod && mod.__esModule) return mod; 1033 | var result = {}; 1034 | if (null != mod) 1035 | for (var k in mod) 1036 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 1037 | return __setModuleDefault(result, mod), result; 1038 | }; 1039 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1040 | const React = __importStar(__webpack_require__(7294)), 1041 | date_fns_1 = __webpack_require__(1613), 1042 | Icon_1 = __webpack_require__(8055); 1043 | exports.default = ({ name, append, lastUpdated }) => { 1044 | const action = append ? 'Appending to ' : 'Fetch for ', 1045 | date = lastUpdated && date_fns_1.format(new Date(lastUpdated), 'pp'); 1046 | return React.createElement( 1047 | 'div', 1048 | { className: 'm-t-sm m-b-sm' }, 1049 | React.createElement(Icon_1.CheckIcon, null), 1050 | ' ', 1051 | action, 1052 | ' ', 1053 | React.createElement('code', null, name), 1054 | ' @ ', 1055 | React.createElement('code', null, date) 1056 | ); 1057 | }; 1058 | }, 1059 | 467: function (__unused_webpack_module, exports, __webpack_require__) { 1060 | 'use strict'; 1061 | var __createBinding = 1062 | (this && this.__createBinding) || 1063 | (Object.create 1064 | ? function (o, m, k, k2) { 1065 | void 0 === k2 && (k2 = k), 1066 | Object.defineProperty(o, k2, { 1067 | enumerable: !0, 1068 | get: function () { 1069 | return m[k]; 1070 | }, 1071 | }); 1072 | } 1073 | : function (o, m, k, k2) { 1074 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 1075 | }), 1076 | __setModuleDefault = 1077 | (this && this.__setModuleDefault) || 1078 | (Object.create 1079 | ? function (o, v) { 1080 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 1081 | } 1082 | : function (o, v) { 1083 | o.default = v; 1084 | }), 1085 | __importStar = 1086 | (this && this.__importStar) || 1087 | function (mod) { 1088 | if (mod && mod.__esModule) return mod; 1089 | var result = {}; 1090 | if (null != mod) 1091 | for (var k in mod) 1092 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 1093 | return __setModuleDefault(result, mod), result; 1094 | }; 1095 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1096 | const React = __importStar(__webpack_require__(7294)), 1097 | Icon_1 = __webpack_require__(8055); 1098 | exports.default = ({ name, error }) => 1099 | React.createElement( 1100 | 'div', 1101 | { className: 'm-t-sm m-b-sm' }, 1102 | React.createElement(Icon_1.ExclamationIcon, null), 1103 | ' Failed to fetch ', 1104 | React.createElement('code', null, name), 1105 | ' due to', 1106 | ' ', 1107 | React.createElement('code', { className: 'has-text-danger' }, error.toString()) 1108 | ); 1109 | }, 1110 | 3387: function (__unused_webpack_module, exports, __webpack_require__) { 1111 | 'use strict'; 1112 | var __createBinding = 1113 | (this && this.__createBinding) || 1114 | (Object.create 1115 | ? function (o, m, k, k2) { 1116 | void 0 === k2 && (k2 = k), 1117 | Object.defineProperty(o, k2, { 1118 | enumerable: !0, 1119 | get: function () { 1120 | return m[k]; 1121 | }, 1122 | }); 1123 | } 1124 | : function (o, m, k, k2) { 1125 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 1126 | }), 1127 | __setModuleDefault = 1128 | (this && this.__setModuleDefault) || 1129 | (Object.create 1130 | ? function (o, v) { 1131 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 1132 | } 1133 | : function (o, v) { 1134 | o.default = v; 1135 | }), 1136 | __importStar = 1137 | (this && this.__importStar) || 1138 | function (mod) { 1139 | if (mod && mod.__esModule) return mod; 1140 | var result = {}; 1141 | if (null != mod) 1142 | for (var k in mod) 1143 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 1144 | return __setModuleDefault(result, mod), result; 1145 | }; 1146 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1147 | const React = __importStar(__webpack_require__(7294)); 1148 | exports.default = () => React.createElement('div', { className: 'm-t-sm m-b-sm' }, 'Fetching fresh data!'); 1149 | }, 1150 | 9197: function (__unused_webpack_module, exports, __webpack_require__) { 1151 | 'use strict'; 1152 | var __importDefault = 1153 | (this && this.__importDefault) || 1154 | function (mod) { 1155 | return mod && mod.__esModule ? mod : { default: mod }; 1156 | }; 1157 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1158 | const react_1 = __importDefault(__webpack_require__(7294)), 1159 | Icon_1 = __importDefault(__webpack_require__(8055)), 1160 | common_1 = __webpack_require__(1256); 1161 | exports.default = ({ name, fetchEntity }) => 1162 | react_1.default.createElement( 1163 | react_1.default.Fragment, 1164 | null, 1165 | react_1.default.createElement( 1166 | 'div', 1167 | { className: 'm-t-sm m-b-sm' }, 1168 | react_1.default.createElement(Icon_1.default, { 1169 | icon: 'exclamation-triangle', 1170 | className: 'has-text-danger', 1171 | }), 1172 | ' Entity ', 1173 | react_1.default.createElement('code', null, name), 1174 | ' does not exist on ', 1175 | react_1.default.createElement('code', null, 'entities') 1176 | ), 1177 | react_1.default.createElement( 1178 | common_1.Button, 1179 | { icon: 'download', onClick: fetchEntity, theme: 'is-info' }, 1180 | 'Fetch' 1181 | ) 1182 | ); 1183 | }, 1184 | 1065: function (__unused_webpack_module, exports, __webpack_require__) { 1185 | 'use strict'; 1186 | var __createBinding = 1187 | (this && this.__createBinding) || 1188 | (Object.create 1189 | ? function (o, m, k, k2) { 1190 | void 0 === k2 && (k2 = k), 1191 | Object.defineProperty(o, k2, { 1192 | enumerable: !0, 1193 | get: function () { 1194 | return m[k]; 1195 | }, 1196 | }); 1197 | } 1198 | : function (o, m, k, k2) { 1199 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 1200 | }), 1201 | __setModuleDefault = 1202 | (this && this.__setModuleDefault) || 1203 | (Object.create 1204 | ? function (o, v) { 1205 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 1206 | } 1207 | : function (o, v) { 1208 | o.default = v; 1209 | }), 1210 | __importStar = 1211 | (this && this.__importStar) || 1212 | function (mod) { 1213 | if (mod && mod.__esModule) return mod; 1214 | var result = {}; 1215 | if (null != mod) 1216 | for (var k in mod) 1217 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 1218 | return __setModuleDefault(result, mod), result; 1219 | }; 1220 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1221 | const React = __importStar(__webpack_require__(7294)); 1222 | exports.default = ({ name }) => 1223 | React.createElement( 1224 | 'div', 1225 | { className: 'm-t-sm m-b-sm' }, 1226 | 'Entity ', 1227 | React.createElement('code', null, name), 1228 | ' has been cleared.' 1229 | ); 1230 | }, 1231 | 2961: function (__unused_webpack_module, exports, __webpack_require__) { 1232 | 'use strict'; 1233 | var __createBinding = 1234 | (this && this.__createBinding) || 1235 | (Object.create 1236 | ? function (o, m, k, k2) { 1237 | void 0 === k2 && (k2 = k), 1238 | Object.defineProperty(o, k2, { 1239 | enumerable: !0, 1240 | get: function () { 1241 | return m[k]; 1242 | }, 1243 | }); 1244 | } 1245 | : function (o, m, k, k2) { 1246 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 1247 | }), 1248 | __setModuleDefault = 1249 | (this && this.__setModuleDefault) || 1250 | (Object.create 1251 | ? function (o, v) { 1252 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 1253 | } 1254 | : function (o, v) { 1255 | o.default = v; 1256 | }), 1257 | __importStar = 1258 | (this && this.__importStar) || 1259 | function (mod) { 1260 | if (mod && mod.__esModule) return mod; 1261 | var result = {}; 1262 | if (null != mod) 1263 | for (var k in mod) 1264 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 1265 | return __setModuleDefault(result, mod), result; 1266 | }, 1267 | __importDefault = 1268 | (this && this.__importDefault) || 1269 | function (mod) { 1270 | return mod && mod.__esModule ? mod : { default: mod }; 1271 | }; 1272 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1273 | const React = __importStar(__webpack_require__(7294)), 1274 | GenericSection_1 = __importDefault(__webpack_require__(347)), 1275 | Entities_1 = __importDefault(__webpack_require__(3187)), 1276 | const_1 = __webpack_require__(5365); 1277 | exports.default = () => 1278 | React.createElement( 1279 | GenericSection_1.default, 1280 | { 1281 | icon: 'sitemap', 1282 | title: 'State Management', 1283 | subtitle: React.createElement( 1284 | 'span', 1285 | null, 1286 | 'Utilizes ', 1287 | React.createElement('a', { href: const_1.URL.REDUX_ENTITY }, 'redux-entity'), 1288 | ' for domain entity management' 1289 | ), 1290 | }, 1291 | React.createElement(Entities_1.default, null) 1292 | ); 1293 | }, 1294 | 2323: function (__unused_webpack_module, exports, __webpack_require__) { 1295 | 'use strict'; 1296 | var __importDefault = 1297 | (this && this.__importDefault) || 1298 | function (mod) { 1299 | return mod && mod.__esModule ? mod : { default: mod }; 1300 | }; 1301 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.default = void 0); 1302 | var ReduxEntity_1 = __webpack_require__(2961); 1303 | Object.defineProperty(exports, 'default', { 1304 | enumerable: !0, 1305 | get: function () { 1306 | return __importDefault(ReduxEntity_1).default; 1307 | }, 1308 | }); 1309 | }, 1310 | 6406: function (__unused_webpack_module, exports, __webpack_require__) { 1311 | 'use strict'; 1312 | var __createBinding = 1313 | (this && this.__createBinding) || 1314 | (Object.create 1315 | ? function (o, m, k, k2) { 1316 | void 0 === k2 && (k2 = k), 1317 | Object.defineProperty(o, k2, { 1318 | enumerable: !0, 1319 | get: function () { 1320 | return m[k]; 1321 | }, 1322 | }); 1323 | } 1324 | : function (o, m, k, k2) { 1325 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 1326 | }), 1327 | __setModuleDefault = 1328 | (this && this.__setModuleDefault) || 1329 | (Object.create 1330 | ? function (o, v) { 1331 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 1332 | } 1333 | : function (o, v) { 1334 | o.default = v; 1335 | }), 1336 | __importStar = 1337 | (this && this.__importStar) || 1338 | function (mod) { 1339 | if (mod && mod.__esModule) return mod; 1340 | var result = {}; 1341 | if (null != mod) 1342 | for (var k in mod) 1343 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 1344 | return __setModuleDefault(result, mod), result; 1345 | }, 1346 | __importDefault = 1347 | (this && this.__importDefault) || 1348 | function (mod) { 1349 | return mod && mod.__esModule ? mod : { default: mod }; 1350 | }; 1351 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1352 | const React = __importStar(__webpack_require__(7294)), 1353 | react_json_pretty_1 = __importDefault(__webpack_require__(7262)), 1354 | react_redux_1 = __webpack_require__(8629), 1355 | GenericSection_1 = __importDefault(__webpack_require__(347)), 1356 | themeProps = { keyStyle: 'color: #3298dc;' }, 1357 | replacer = (key, value) => (value instanceof Error ? value.toString() : value); 1358 | exports.default = () => { 1359 | const state = react_redux_1.useSelector((state) => state); 1360 | return React.createElement( 1361 | GenericSection_1.default, 1362 | { 1363 | icon: 'tree', 1364 | title: 'State Tree', 1365 | subtitle: React.createElement('span', null, 'Open Console to view dispatched actions'), 1366 | }, 1367 | React.createElement(react_json_pretty_1.default, Object.assign({}, themeProps, { data: state, replacer })) 1368 | ); 1369 | }; 1370 | }, 1371 | 1198: function (__unused_webpack_module, exports, __webpack_require__) { 1372 | 'use strict'; 1373 | var __importDefault = 1374 | (this && this.__importDefault) || 1375 | function (mod) { 1376 | return mod && mod.__esModule ? mod : { default: mod }; 1377 | }; 1378 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.default = void 0); 1379 | var ReduxState_1 = __webpack_require__(6406); 1380 | Object.defineProperty(exports, 'default', { 1381 | enumerable: !0, 1382 | get: function () { 1383 | return __importDefault(ReduxState_1).default; 1384 | }, 1385 | }); 1386 | }, 1387 | 6253: function (__unused_webpack_module, exports, __webpack_require__) { 1388 | 'use strict'; 1389 | var __importDefault = 1390 | (this && this.__importDefault) || 1391 | function (mod) { 1392 | return mod && mod.__esModule ? mod : { default: mod }; 1393 | }; 1394 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1395 | const react_1 = __importDefault(__webpack_require__(7294)), 1396 | Icon_1 = __importDefault(__webpack_require__(8055)); 1397 | exports.default = ({ icon, disabled, loading, onClick, children, theme = '' }) => 1398 | react_1.default.createElement( 1399 | 'p', 1400 | { key: 'Fetch', className: 'control' }, 1401 | react_1.default.createElement( 1402 | 'a', 1403 | { className: `button ${theme} ${loading && 'is-loading'}`, disabled, onClick }, 1404 | react_1.default.createElement( 1405 | 'span', 1406 | { className: 'icon' }, 1407 | react_1.default.createElement(Icon_1.default, { icon }) 1408 | ), 1409 | react_1.default.createElement('span', null, children) 1410 | ) 1411 | ); 1412 | }, 1413 | 8055: function (__unused_webpack_module, exports, __webpack_require__) { 1414 | 'use strict'; 1415 | var __importDefault = 1416 | (this && this.__importDefault) || 1417 | function (mod) { 1418 | return mod && mod.__esModule ? mod : { default: mod }; 1419 | }; 1420 | Object.defineProperty(exports, '__esModule', { value: !0 }), 1421 | (exports.CogIcon = exports.CheckIcon = exports.ExclamationIcon = void 0); 1422 | const react_1 = __importDefault(__webpack_require__(7294)); 1423 | exports.ExclamationIcon = () => 1424 | react_1.default.createElement(Icon, { icon: 'exclamation-triangle', className: 'has-text-danger' }); 1425 | exports.CheckIcon = () => react_1.default.createElement(Icon, { icon: 'check', className: 'has-text-success' }); 1426 | exports.CogIcon = ({ size, className }) => 1427 | react_1.default.createElement(Icon, { icon: 'cog fa-spin', size, className }); 1428 | const Icon = ({ icon, prefix, className, size = 'fa-1x' }) => { 1429 | const iconPrefix = prefix || 'fa'; 1430 | return react_1.default.createElement( 1431 | 'span', 1432 | null, 1433 | react_1.default.createElement('i', { className: `${iconPrefix} fa-${icon} ${className || ''} ${size}` }) 1434 | ); 1435 | }; 1436 | exports.default = Icon; 1437 | }, 1438 | 3152: function (__unused_webpack_module, exports, __webpack_require__) { 1439 | 'use strict'; 1440 | var __createBinding = 1441 | (this && this.__createBinding) || 1442 | (Object.create 1443 | ? function (o, m, k, k2) { 1444 | void 0 === k2 && (k2 = k), 1445 | Object.defineProperty(o, k2, { 1446 | enumerable: !0, 1447 | get: function () { 1448 | return m[k]; 1449 | }, 1450 | }); 1451 | } 1452 | : function (o, m, k, k2) { 1453 | void 0 === k2 && (k2 = k), (o[k2] = m[k]); 1454 | }), 1455 | __setModuleDefault = 1456 | (this && this.__setModuleDefault) || 1457 | (Object.create 1458 | ? function (o, v) { 1459 | Object.defineProperty(o, 'default', { enumerable: !0, value: v }); 1460 | } 1461 | : function (o, v) { 1462 | o.default = v; 1463 | }), 1464 | __importStar = 1465 | (this && this.__importStar) || 1466 | function (mod) { 1467 | if (mod && mod.__esModule) return mod; 1468 | var result = {}; 1469 | if (null != mod) 1470 | for (var k in mod) 1471 | 'default' !== k && Object.prototype.hasOwnProperty.call(mod, k) && __createBinding(result, mod, k); 1472 | return __setModuleDefault(result, mod), result; 1473 | }; 1474 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1475 | const React = __importStar(__webpack_require__(7294)); 1476 | exports.default = ({ url, children }) => 1477 | React.createElement('a', { href: url, target: '_blank', rel: 'noopener noreferrer' }, children); 1478 | }, 1479 | 975: function (__unused_webpack_module, exports, __webpack_require__) { 1480 | 'use strict'; 1481 | var __importDefault = 1482 | (this && this.__importDefault) || 1483 | function (mod) { 1484 | return mod && mod.__esModule ? mod : { default: mod }; 1485 | }; 1486 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1487 | const react_1 = __importDefault(__webpack_require__(7294)), 1488 | bind_1 = __importDefault(__webpack_require__(7166)), 1489 | common_1 = __webpack_require__(1256), 1490 | logo_png_1 = __importDefault(__webpack_require__(4439)), 1491 | const_1 = __webpack_require__(5365), 1492 | NavBar_scss_1 = __importDefault(__webpack_require__(9938)), 1493 | cx = bind_1.default.bind(NavBar_scss_1.default); 1494 | exports.default = () => 1495 | react_1.default.createElement( 1496 | 'nav', 1497 | { 1498 | className: `navbar is-dark ${cx('nav-bar--container')}`, 1499 | role: 'navigation', 1500 | 'aria-label': 'main navigation', 1501 | }, 1502 | react_1.default.createElement( 1503 | 'div', 1504 | { className: 'navbar-brand' }, 1505 | react_1.default.createElement( 1506 | 'a', 1507 | { href: const_1.URL.REPOSITORY, className: 'navbar-item is-size-3' }, 1508 | react_1.default.createElement('img', { src: logo_png_1.default, height: 64, width: 64 }), 1509 | react_1.default.createElement('span', null, 'react-boilerplate') 1510 | ) 1511 | ), 1512 | react_1.default.createElement( 1513 | 'div', 1514 | { className: 'navbar-end' }, 1515 | react_1.default.createElement( 1516 | 'div', 1517 | { className: 'navbar-item' }, 1518 | react_1.default.createElement( 1519 | 'a', 1520 | { className: 'button is-dark', href: const_1.URL.NPM }, 1521 | react_1.default.createElement( 1522 | 'span', 1523 | { className: 'icon is-small has-text-danger' }, 1524 | react_1.default.createElement(common_1.Icon, { icon: 'npm', prefix: 'fab', size: 'fa-2x' }) 1525 | ) 1526 | ) 1527 | ), 1528 | react_1.default.createElement( 1529 | 'div', 1530 | { className: 'navbar-item' }, 1531 | react_1.default.createElement( 1532 | 'a', 1533 | { className: 'button is-dark', href: const_1.URL.REPOSITORY }, 1534 | react_1.default.createElement( 1535 | 'span', 1536 | { className: 'icon is-small' }, 1537 | react_1.default.createElement(common_1.Icon, { icon: 'github', prefix: 'fab', size: 'fa-2x' }) 1538 | ) 1539 | ) 1540 | ) 1541 | ) 1542 | ); 1543 | }, 1544 | 1256: function (__unused_webpack_module, exports, __webpack_require__) { 1545 | 'use strict'; 1546 | var __importDefault = 1547 | (this && this.__importDefault) || 1548 | function (mod) { 1549 | return mod && mod.__esModule ? mod : { default: mod }; 1550 | }; 1551 | Object.defineProperty(exports, '__esModule', { value: !0 }), 1552 | (exports.Link = exports.Button = exports.Icon = void 0); 1553 | var Icon_1 = __webpack_require__(8055); 1554 | Object.defineProperty(exports, 'Icon', { 1555 | enumerable: !0, 1556 | get: function () { 1557 | return __importDefault(Icon_1).default; 1558 | }, 1559 | }); 1560 | var Button_1 = __webpack_require__(6253); 1561 | Object.defineProperty(exports, 'Button', { 1562 | enumerable: !0, 1563 | get: function () { 1564 | return __importDefault(Button_1).default; 1565 | }, 1566 | }); 1567 | var Link_1 = __webpack_require__(3152); 1568 | Object.defineProperty(exports, 'Link', { 1569 | enumerable: !0, 1570 | get: function () { 1571 | return __importDefault(Link_1).default; 1572 | }, 1573 | }); 1574 | }, 1575 | 5365: function (__unused_webpack_module, exports) { 1576 | 'use strict'; 1577 | Object.defineProperty(exports, '__esModule', { value: !0 }), 1578 | (exports.URL = void 0), 1579 | (exports.URL = { 1580 | GITHUB: 'https://github.com/mikechabot', 1581 | REPOSITORY: 'http://www.github.com/mikechabot/react-boilerplate', 1582 | NPM: 'https://www.npmjs.com/~mikechabot', 1583 | DEMO: 'https://github.com/mikechabot/react-boilerplate', 1584 | LICENSE: 'https://github.com/mikechabot/react-boilerplate/blob/master/LICENSE', 1585 | REDUX_ENTITY: 'https://github.com/mikechabot/redux-entity', 1586 | REACT_ROUTER: 'https://github.com/ReactTraining/react-router', 1587 | }); 1588 | }, 1589 | 9269: function (__unused_webpack_module, exports) { 1590 | 'use strict'; 1591 | Object.defineProperty(exports, '__esModule', { value: !0 }), 1592 | (exports.RESET_COUNTER = exports.DECREMENT_COUNTER = exports.INCREMENT_COUNTER = void 0), 1593 | (exports.INCREMENT_COUNTER = 'react-boilerplate/counter/INCREMENT_COUNTER'), 1594 | (exports.DECREMENT_COUNTER = 'react-boilerplate/counter/DECREMENT_COUNTER'), 1595 | (exports.RESET_COUNTER = 'react-boilerplate/counter/RESET_COUNTER'); 1596 | exports.default = (state = 0, action) => { 1597 | switch (action.type) { 1598 | case exports.INCREMENT_COUNTER: 1599 | return state + 1; 1600 | case exports.DECREMENT_COUNTER: 1601 | return state - 1; 1602 | case exports.RESET_COUNTER: 1603 | return 0; 1604 | default: 1605 | return state; 1606 | } 1607 | }; 1608 | }, 1609 | 6186: function (__unused_webpack_module, exports, __webpack_require__) { 1610 | 'use strict'; 1611 | Object.defineProperty(exports, '__esModule', { value: !0 }), 1612 | (exports.fetchBaz = exports.fetchBar = exports.fetchFoo = void 0); 1613 | const redux_entity_1 = __webpack_require__(7694), 1614 | domain_service_1 = __webpack_require__(2819), 1615 | types_1 = __webpack_require__(55); 1616 | (exports.fetchFoo = function fetchFoo() { 1617 | return redux_entity_1.GetEntity(types_1.EntityType.Foo, domain_service_1.fetchMockData()); 1618 | }), 1619 | (exports.fetchBar = function fetchBar() { 1620 | return redux_entity_1.GetEntity(types_1.EntityType.Bar, domain_service_1.fetchMockData(), { append: !0 }); 1621 | }), 1622 | (exports.fetchBaz = function fetchBaz() { 1623 | return redux_entity_1.GetEntity(types_1.EntityType.Baz, domain_service_1.fetchMockData(!0)); 1624 | }); 1625 | }, 1626 | 5318: function (__unused_webpack_module, exports, __webpack_require__) { 1627 | 'use strict'; 1628 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.default = void 0); 1629 | var lib_1 = __webpack_require__(7694); 1630 | Object.defineProperty(exports, 'default', { 1631 | enumerable: !0, 1632 | get: function () { 1633 | return lib_1.reducer; 1634 | }, 1635 | }); 1636 | }, 1637 | 55: function (__unused_webpack_module, exports) { 1638 | 'use strict'; 1639 | Object.defineProperty(exports, '__esModule', { value: !0 }), 1640 | (exports.EntityType = void 0), 1641 | (function (EntityType) { 1642 | (EntityType.Foo = 'foo'), (EntityType.Bar = 'bar'), (EntityType.Baz = 'baz'); 1643 | })(exports.EntityType || (exports.EntityType = {})); 1644 | }, 1645 | 8262: function (__unused_webpack_module, exports, __webpack_require__) { 1646 | 'use strict'; 1647 | var __importDefault = 1648 | (this && this.__importDefault) || 1649 | function (mod) { 1650 | return mod && mod.__esModule ? mod : { default: mod }; 1651 | }; 1652 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1653 | const redux_1 = __webpack_require__(4890), 1654 | reducer_1 = __importDefault(__webpack_require__(5318)), 1655 | reducer_2 = __importDefault(__webpack_require__(9269)), 1656 | rootReducer = redux_1.combineReducers({ counter: reducer_2.default, entities: reducer_1.default }); 1657 | exports.default = rootReducer; 1658 | }, 1659 | 234: function (__unused_webpack_module, exports, __webpack_require__) { 1660 | 'use strict'; 1661 | var __importDefault = 1662 | (this && this.__importDefault) || 1663 | function (mod) { 1664 | return mod && mod.__esModule ? mod : { default: mod }; 1665 | }; 1666 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1667 | const redux_1 = __webpack_require__(4890), 1668 | redux_thunk_1 = __importDefault(__webpack_require__(3894)), 1669 | redux_logger_1 = __importDefault(__webpack_require__(4500)), 1670 | index_1 = __importDefault(__webpack_require__(8262)); 1671 | exports.default = function configureStore(initialState = {}) { 1672 | return redux_1.createStore( 1673 | index_1.default, 1674 | initialState, 1675 | redux_1.applyMiddleware(redux_thunk_1.default, redux_logger_1.default) 1676 | ); 1677 | }; 1678 | }, 1679 | 169: function (__unused_webpack_module, exports, __webpack_require__) { 1680 | 'use strict'; 1681 | var __importDefault = 1682 | (this && this.__importDefault) || 1683 | function (mod) { 1684 | return mod && mod.__esModule ? mod : { default: mod }; 1685 | }; 1686 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1687 | const redux_1 = __webpack_require__(4890), 1688 | redux_thunk_1 = __importDefault(__webpack_require__(3894)), 1689 | index_1 = __importDefault(__webpack_require__(8262)), 1690 | redux_logger_1 = __importDefault(__webpack_require__(4500)); 1691 | exports.default = function configureStore(initialState = {}) { 1692 | return redux_1.createStore( 1693 | index_1.default, 1694 | initialState, 1695 | redux_1.applyMiddleware(redux_thunk_1.default, redux_logger_1.default) 1696 | ); 1697 | }; 1698 | }, 1699 | 5908: function (__unused_webpack_module, exports, __webpack_require__) { 1700 | 'use strict'; 1701 | var __importDefault = 1702 | (this && this.__importDefault) || 1703 | function (mod) { 1704 | return mod && mod.__esModule ? mod : { default: mod }; 1705 | }; 1706 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1707 | const node_service_1 = __importDefault(__webpack_require__(8720)), 1708 | configure_store_prod_1 = __importDefault(__webpack_require__(169)), 1709 | configure_store_dev_1 = __importDefault(__webpack_require__(234)); 1710 | exports.default = node_service_1.default.isProduction() 1711 | ? configure_store_prod_1.default() 1712 | : configure_store_dev_1.default(); 1713 | }, 1714 | 3521: function (__unused_webpack_module, exports, __webpack_require__) { 1715 | 'use strict'; 1716 | var __importDefault = 1717 | (this && this.__importDefault) || 1718 | function (mod) { 1719 | return mod && mod.__esModule ? mod : { default: mod }; 1720 | }; 1721 | Object.defineProperty(exports, '__esModule', { value: !0 }); 1722 | const axios_1 = __importDefault(__webpack_require__(9669)), 1723 | config_service_1 = __importDefault(__webpack_require__(3018)), 1724 | instance = axios_1.default.create({ baseURL: config_service_1.default.getBaseUrl(), timeout: 4e3 }); 1725 | exports.default = { request: (options) => instance.request(options) }; 1726 | }, 1727 | 5334: function (__unused_webpack_module, exports, __webpack_require__) { 1728 | 'use strict'; 1729 | var __importDefault = 1730 | (this && this.__importDefault) || 1731 | function (mod) { 1732 | return mod && mod.__esModule ? mod : { default: mod }; 1733 | }; 1734 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.post = exports.get = void 0); 1735 | const ajax_service_1 = __importDefault(__webpack_require__(3521)); 1736 | var HttpMethod; 1737 | !(function (HttpMethod) { 1738 | (HttpMethod.GET = 'GET'), (HttpMethod.POST = 'POST'), (HttpMethod.PUT = 'PUT'), (HttpMethod.DELETE = 'DELETE'); 1739 | })(HttpMethod || (HttpMethod = {})); 1740 | const request = (method, url, data, options) => { 1741 | const defaultOptions = { url, method, responseType: 'json' }; 1742 | data && 1743 | ((defaultOptions.data = JSON.stringify(data)), 1744 | (defaultOptions.headers = { 'Content-Type': 'application/json' })); 1745 | let requestOptions = defaultOptions; 1746 | return ( 1747 | options && (requestOptions = Object.assign(Object.assign({}, defaultOptions), options)), 1748 | new Promise((resolve, reject) => { 1749 | ajax_service_1.default 1750 | .request(requestOptions) 1751 | .then(resolve) 1752 | .catch((error) => 1753 | reject( 1754 | (function deriveError(error) { 1755 | return error 1756 | ? error.message 1757 | ? error 1758 | : `${error.status} ${error.statusText}` 1759 | : new Error('An unknown error occurred'); 1760 | })(error) 1761 | ) 1762 | ); 1763 | }) 1764 | ); 1765 | }; 1766 | exports.get = (url, options) => request(HttpMethod.GET, url, void 0, options); 1767 | exports.post = (url, data, options) => request(HttpMethod.POST, url, data, options); 1768 | }, 1769 | 2819: function (__unused_webpack_module, exports, __webpack_require__) { 1770 | 'use strict'; 1771 | Object.defineProperty(exports, '__esModule', { value: !0 }), 1772 | (exports.fetchMockData = exports.postFoo = exports.fetchFoo = void 0); 1773 | const data_access_service_1 = __webpack_require__(5334), 1774 | util_1 = __webpack_require__(4609), 1775 | fakeError = new Error('Fake Error!'); 1776 | exports.fetchFoo = (id) => data_access_service_1.get(`/foo/${id}`); 1777 | exports.postFoo = (id, data) => data_access_service_1.post(`/foo/${id}`, data); 1778 | exports.fetchMockData = (doReject = !1) => { 1779 | const delay = util_1.randomNumber(), 1780 | payload = { delay }; 1781 | return new Promise((resolve, reject) => { 1782 | setTimeout(() => (doReject ? reject(fakeError) : resolve(payload)), 1e3 * delay); 1783 | }); 1784 | }; 1785 | }, 1786 | 4609: function (__unused_webpack_module, exports) { 1787 | 'use strict'; 1788 | Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.randomNumber = void 0); 1789 | exports.randomNumber = function randomNumber() { 1790 | return Number(2 * Math.random() + 1); 1791 | }; 1792 | }, 1793 | 4439: function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 1794 | 'use strict'; 1795 | __webpack_require__.r(__webpack_exports__), 1796 | (__webpack_exports__.default = 1797 | 'data:image/png;base64,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'); 1798 | }, 1799 | }, 1800 | 0, 1801 | [[3463, 700, 736]], 1802 | ]); 1803 | -------------------------------------------------------------------------------- /docs/manifest.b39cfef421931f6623fe.js: -------------------------------------------------------------------------------- 1 | !(function () { 2 | 'use strict'; 3 | var leafPrototypes, 4 | getProto, 5 | inProgress, 6 | loadStylesheet, 7 | installedCssChunks, 8 | __webpack_modules__ = {}, 9 | __webpack_module_cache__ = {}; 10 | function __webpack_require__(moduleId) { 11 | if (__webpack_module_cache__[moduleId]) return __webpack_module_cache__[moduleId].exports; 12 | var module = (__webpack_module_cache__[moduleId] = { id: moduleId, loaded: !1, exports: {} }); 13 | return ( 14 | __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__), 15 | (module.loaded = !0), 16 | module.exports 17 | ); 18 | } 19 | (__webpack_require__.m = __webpack_modules__), 20 | (__webpack_require__.x = function () {}), 21 | (__webpack_require__.n = function (module) { 22 | var getter = 23 | module && module.__esModule 24 | ? function () { 25 | return module.default; 26 | } 27 | : function () { 28 | return module; 29 | }; 30 | return __webpack_require__.d(getter, { a: getter }), getter; 31 | }), 32 | (getProto = Object.getPrototypeOf 33 | ? function (obj) { 34 | return Object.getPrototypeOf(obj); 35 | } 36 | : function (obj) { 37 | return obj.__proto__; 38 | }), 39 | (__webpack_require__.t = function (value, mode) { 40 | if ((1 & mode && (value = this(value)), 8 & mode)) return value; 41 | if ('object' == typeof value && value) { 42 | if (4 & mode && value.__esModule) return value; 43 | if (16 & mode && 'function' == typeof value.then) return value; 44 | } 45 | var ns = Object.create(null); 46 | __webpack_require__.r(ns); 47 | var def = {}; 48 | leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)]; 49 | for ( 50 | var current = 2 & mode && value; 51 | 'object' == typeof current && !~leafPrototypes.indexOf(current); 52 | current = getProto(current) 53 | ) 54 | Object.getOwnPropertyNames(current).forEach(function (key) { 55 | def[key] = function () { 56 | return value[key]; 57 | }; 58 | }); 59 | return ( 60 | (def.default = function () { 61 | return value; 62 | }), 63 | __webpack_require__.d(ns, def), 64 | ns 65 | ); 66 | }), 67 | (__webpack_require__.d = function (exports, definition) { 68 | for (var key in definition) 69 | __webpack_require__.o(definition, key) && 70 | !__webpack_require__.o(exports, key) && 71 | Object.defineProperty(exports, key, { enumerable: !0, get: definition[key] }); 72 | }), 73 | (__webpack_require__.f = {}), 74 | (__webpack_require__.e = function (chunkId) { 75 | return Promise.all( 76 | Object.keys(__webpack_require__.f).reduce(function (promises, key) { 77 | return __webpack_require__.f[key](chunkId, promises), promises; 78 | }, []) 79 | ); 80 | }), 81 | (__webpack_require__.u = function (chunkId) { 82 | return ( 83 | { 84 | 715: 'components-Sections-ReactRouter-Routes-IncrementRoute', 85 | 896: 'components-Sections-ReactRouter-Routes-DecrementRoute', 86 | 956: 'components-Sections-ReactRouter-Routes-ResetRoute', 87 | }[chunkId] + 88 | '.' + 89 | __webpack_require__.h() + 90 | '.js' 91 | ); 92 | }), 93 | (__webpack_require__.miniCssF = function (chunkId) { 94 | return 715 === chunkId 95 | ? '715.7dd94fe17002b841b25c.css' 96 | : 896 === chunkId 97 | ? '896.7dd94fe17002b841b25c.css' 98 | : 956 === chunkId 99 | ? '956.7dd94fe17002b841b25c.css' 100 | : { 179: 'main', 700: 'manifest', 736: 'vendor' }[chunkId] + 101 | '.' + 102 | { 179: 'e6747817a710beefd9ef', 736: '31d6cfe0d16ae931b73c' }[chunkId] + 103 | '.css'; 104 | }), 105 | (__webpack_require__.h = function () { 106 | return 'b39cfef421931f6623fe'; 107 | }), 108 | (__webpack_require__.g = (function () { 109 | if ('object' == typeof globalThis) return globalThis; 110 | try { 111 | return this || new Function('return this')(); 112 | } catch (e) { 113 | if ('object' == typeof window) return window; 114 | } 115 | })()), 116 | (__webpack_require__.hmd = function (module) { 117 | return ( 118 | (module = Object.create(module)).children || (module.children = []), 119 | Object.defineProperty(module, 'exports', { 120 | enumerable: !0, 121 | set: function () { 122 | throw new Error( 123 | 'ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id 124 | ); 125 | }, 126 | }), 127 | module 128 | ); 129 | }), 130 | (__webpack_require__.o = function (obj, prop) { 131 | return Object.prototype.hasOwnProperty.call(obj, prop); 132 | }), 133 | (inProgress = {}), 134 | (__webpack_require__.l = function (url, done, key) { 135 | if (inProgress[url]) inProgress[url].push(done); 136 | else { 137 | var script, needAttach; 138 | if (void 0 !== key) 139 | for (var scripts = document.getElementsByTagName('script'), i = 0; i < scripts.length; i++) { 140 | var s = scripts[i]; 141 | if (s.getAttribute('src') == url || s.getAttribute('data-webpack') == 'react-boilerplate:' + key) { 142 | script = s; 143 | break; 144 | } 145 | } 146 | script || 147 | ((needAttach = !0), 148 | ((script = document.createElement('script')).charset = 'utf-8'), 149 | (script.timeout = 120), 150 | __webpack_require__.nc && script.setAttribute('nonce', __webpack_require__.nc), 151 | script.setAttribute('data-webpack', 'react-boilerplate:' + key), 152 | (script.src = url)), 153 | (inProgress[url] = [done]); 154 | var onScriptComplete = function (prev, event) { 155 | (script.onerror = script.onload = null), clearTimeout(timeout); 156 | var doneFns = inProgress[url]; 157 | if ( 158 | (delete inProgress[url], 159 | script.parentNode && script.parentNode.removeChild(script), 160 | doneFns && 161 | doneFns.forEach(function (fn) { 162 | return fn(event); 163 | }), 164 | prev) 165 | ) 166 | return prev(event); 167 | }, 168 | timeout = setTimeout(onScriptComplete.bind(null, void 0, { type: 'timeout', target: script }), 12e4); 169 | (script.onerror = onScriptComplete.bind(null, script.onerror)), 170 | (script.onload = onScriptComplete.bind(null, script.onload)), 171 | needAttach && document.head.appendChild(script); 172 | } 173 | }), 174 | (__webpack_require__.r = function (exports) { 175 | 'undefined' != typeof Symbol && 176 | Symbol.toStringTag && 177 | Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }), 178 | Object.defineProperty(exports, '__esModule', { value: !0 }); 179 | }), 180 | (__webpack_require__.nmd = function (module) { 181 | return (module.paths = []), module.children || (module.children = []), module; 182 | }), 183 | (function () { 184 | var scriptUrl; 185 | __webpack_require__.g.importScripts && (scriptUrl = __webpack_require__.g.location + ''); 186 | var document = __webpack_require__.g.document; 187 | if (!scriptUrl && document && (document.currentScript && (scriptUrl = document.currentScript.src), !scriptUrl)) { 188 | var scripts = document.getElementsByTagName('script'); 189 | scripts.length && (scriptUrl = scripts[scripts.length - 1].src); 190 | } 191 | if (!scriptUrl) throw new Error('Automatic publicPath is not supported in this browser'); 192 | (scriptUrl = scriptUrl 193 | .replace(/#.*$/, '') 194 | .replace(/\?.*$/, '') 195 | .replace(/\/[^\/]+$/, '/')), 196 | (__webpack_require__.p = scriptUrl); 197 | })(), 198 | (loadStylesheet = function (chunkId) { 199 | return new Promise(function (resolve, reject) { 200 | var href = __webpack_require__.miniCssF(chunkId), 201 | fullhref = __webpack_require__.p + href; 202 | if ( 203 | (function (href, fullhref) { 204 | for ( 205 | var existingLinkTags = document.getElementsByTagName('link'), i = 0; 206 | i < existingLinkTags.length; 207 | i++ 208 | ) { 209 | var dataHref = (tag = existingLinkTags[i]).getAttribute('data-href') || tag.getAttribute('href'); 210 | if ('stylesheet' === tag.rel && (dataHref === href || dataHref === fullhref)) return tag; 211 | } 212 | var existingStyleTags = document.getElementsByTagName('style'); 213 | for (i = 0; i < existingStyleTags.length; i++) { 214 | var tag; 215 | if ((dataHref = (tag = existingStyleTags[i]).getAttribute('data-href')) === href || dataHref === fullhref) 216 | return tag; 217 | } 218 | })(href, fullhref) 219 | ) 220 | return resolve(); 221 | !(function (chunkId, fullhref, resolve, reject) { 222 | var linkTag = document.createElement('link'); 223 | (linkTag.rel = 'stylesheet'), 224 | (linkTag.type = 'text/css'), 225 | (linkTag.onerror = linkTag.onload = function (event) { 226 | if (((linkTag.onerror = linkTag.onload = null), 'load' === event.type)) resolve(); 227 | else { 228 | var errorType = event && ('load' === event.type ? 'missing' : event.type), 229 | realHref = (event && event.target && event.target.href) || fullhref, 230 | err = new Error('Loading CSS chunk ' + chunkId + ' failed.\n(' + realHref + ')'); 231 | (err.code = 'CSS_CHUNK_LOAD_FAILED'), 232 | (err.type = errorType), 233 | (err.request = realHref), 234 | linkTag.parentNode.removeChild(linkTag), 235 | reject(err); 236 | } 237 | }), 238 | (linkTag.href = fullhref), 239 | document.head.appendChild(linkTag); 240 | })(chunkId, fullhref, resolve, reject); 241 | }); 242 | }), 243 | (installedCssChunks = { 700: 0 }), 244 | (__webpack_require__.f.miniCss = function (chunkId, promises) { 245 | installedCssChunks[chunkId] 246 | ? promises.push(installedCssChunks[chunkId]) 247 | : 0 !== installedCssChunks[chunkId] && 248 | { 715: 1, 896: 1, 956: 1 }[chunkId] && 249 | promises.push( 250 | (installedCssChunks[chunkId] = loadStylesheet(chunkId).then( 251 | function () { 252 | installedCssChunks[chunkId] = 0; 253 | }, 254 | function (e) { 255 | throw (delete installedCssChunks[chunkId], e); 256 | } 257 | )) 258 | ); 259 | }), 260 | (function () { 261 | var installedChunks = { 700: 0 }, 262 | deferredModules = []; 263 | __webpack_require__.f.j = function (chunkId, promises) { 264 | var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : void 0; 265 | if (0 !== installedChunkData) 266 | if (installedChunkData) promises.push(installedChunkData[2]); 267 | else { 268 | var promise = new Promise(function (resolve, reject) { 269 | installedChunkData = installedChunks[chunkId] = [resolve, reject]; 270 | }); 271 | promises.push((installedChunkData[2] = promise)); 272 | var url = __webpack_require__.p + __webpack_require__.u(chunkId), 273 | error = new Error(); 274 | __webpack_require__.l( 275 | url, 276 | function (event) { 277 | if ( 278 | __webpack_require__.o(installedChunks, chunkId) && 279 | (0 !== (installedChunkData = installedChunks[chunkId]) && (installedChunks[chunkId] = void 0), 280 | installedChunkData) 281 | ) { 282 | var errorType = event && ('load' === event.type ? 'missing' : event.type), 283 | realSrc = event && event.target && event.target.src; 284 | (error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'), 285 | (error.name = 'ChunkLoadError'), 286 | (error.type = errorType), 287 | (error.request = realSrc), 288 | installedChunkData[1](error); 289 | } 290 | }, 291 | 'chunk-' + chunkId 292 | ); 293 | } 294 | }; 295 | var checkDeferredModules = function () {}, 296 | webpackJsonpCallback = function (parentChunkLoadingFunction, data) { 297 | for ( 298 | var moduleId, 299 | chunkId, 300 | chunkIds = data[0], 301 | moreModules = data[1], 302 | runtime = data[2], 303 | executeModules = data[3], 304 | i = 0, 305 | resolves = []; 306 | i < chunkIds.length; 307 | i++ 308 | ) 309 | (chunkId = chunkIds[i]), 310 | __webpack_require__.o(installedChunks, chunkId) && 311 | installedChunks[chunkId] && 312 | resolves.push(installedChunks[chunkId][0]), 313 | (installedChunks[chunkId] = 0); 314 | for (moduleId in moreModules) 315 | __webpack_require__.o(moreModules, moduleId) && (__webpack_require__.m[moduleId] = moreModules[moduleId]); 316 | for ( 317 | runtime && runtime(__webpack_require__), parentChunkLoadingFunction && parentChunkLoadingFunction(data); 318 | resolves.length; 319 | 320 | ) 321 | resolves.shift()(); 322 | return executeModules && deferredModules.push.apply(deferredModules, executeModules), checkDeferredModules(); 323 | }, 324 | chunkLoadingGlobal = (self.webpackChunkreact_boilerplate = self.webpackChunkreact_boilerplate || []); 325 | function checkDeferredModulesImpl() { 326 | for (var result, i = 0; i < deferredModules.length; i++) { 327 | for (var deferredModule = deferredModules[i], fulfilled = !0, j = 1; j < deferredModule.length; j++) { 328 | var depId = deferredModule[j]; 329 | 0 !== installedChunks[depId] && (fulfilled = !1); 330 | } 331 | fulfilled && 332 | (deferredModules.splice(i--, 1), 333 | (result = __webpack_require__((__webpack_require__.s = deferredModule[0])))); 334 | } 335 | return ( 336 | 0 === deferredModules.length && (__webpack_require__.x(), (__webpack_require__.x = function () {})), result 337 | ); 338 | } 339 | chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)), 340 | (chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal))); 341 | var startup = __webpack_require__.x; 342 | __webpack_require__.x = function () { 343 | return (__webpack_require__.x = startup || function () {}), (checkDeferredModules = checkDeferredModulesImpl)(); 344 | }; 345 | })(), 346 | __webpack_require__.x(); 347 | })(); 348 | -------------------------------------------------------------------------------- /docs/vendor.b39cfef421931f6623fe.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /*! 8 | Copyright (c) 2017 Jed Watson. 9 | Licensed under the MIT License (MIT), see 10 | http://jedwatson.github.io/classnames 11 | */ 12 | 13 | /*! 14 | * isobject 15 | * 16 | * Copyright (c) 2014-2017, Jon Schlinkert. 17 | * Released under the MIT License. 18 | */ 19 | 20 | /** 21 | * Checks if an event is supported in the current execution environment. 22 | * 23 | * NOTE: This will not work correctly for non-generic events such as `change`, 24 | * `reset`, `load`, `error`, and `select`. 25 | * 26 | * Borrows from Modernizr. 27 | * 28 | * @param {string} eventNameSuffix Event name, e.g. "click". 29 | * @return {boolean} True if the event is supported. 30 | * @internal 31 | * @license Modernizr 3.0.0pre (Custom Build) | MIT 32 | */ 33 | 34 | /** @license React v0.20.1 35 | * scheduler-tracing.development.js 36 | * 37 | * Copyright (c) Facebook, Inc. and its affiliates. 38 | * 39 | * This source code is licensed under the MIT license found in the 40 | * LICENSE file in the root directory of this source tree. 41 | */ 42 | 43 | /** @license React v0.20.1 44 | * scheduler.development.js 45 | * 46 | * Copyright (c) Facebook, Inc. and its affiliates. 47 | * 48 | * This source code is licensed under the MIT license found in the 49 | * LICENSE file in the root directory of this source tree. 50 | */ 51 | 52 | /** @license React v16.13.1 53 | * react-is.development.js 54 | * 55 | * Copyright (c) Facebook, Inc. and its affiliates. 56 | * 57 | * This source code is licensed under the MIT license found in the 58 | * LICENSE file in the root directory of this source tree. 59 | */ 60 | 61 | /** @license React v17.0.1 62 | * react-dom.development.js 63 | * 64 | * Copyright (c) Facebook, Inc. and its affiliates. 65 | * 66 | * This source code is licensed under the MIT license found in the 67 | * LICENSE file in the root directory of this source tree. 68 | */ 69 | 70 | /** @license React v17.0.1 71 | * react.development.js 72 | * 73 | * Copyright (c) Facebook, Inc. and its affiliates. 74 | * 75 | * This source code is licensed under the MIT license found in the 76 | * LICENSE file in the root directory of this source tree. 77 | */ 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-boilerplate", 3 | "version": "5.1.0", 4 | "description": "A slightly opinionated yet dead simple boilerplate for ReactJS", 5 | "engines": { 6 | "node": ">= 10.0.0", 7 | "npm": ">= 6.0.0" 8 | }, 9 | "scripts": { 10 | "start": "npm run build:prod && npm run start-prod-server", 11 | "dev": "npm run clean && cross-env NODE_ENV=development webpack serve --progress --color", 12 | "build:prod": "npm run clean && cross-env NODE_ENV=production webpack --progress --color", 13 | "build:gh-pages": "npm run clean && cross-env NODE_ENV=gh-pages webpack --progress --color", 14 | "start-prod-server": "cross-env NODE_ENV=production node server.js", 15 | "clean": "rimraf ./docs" 16 | }, 17 | "author": "Mike Chabot", 18 | "license": "MIT", 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/mikechabot/react-boilerplate.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/mikechabot/react-boilerplate/issues" 25 | }, 26 | "browserslist": [ 27 | "defaults" 28 | ], 29 | "husky": { 30 | "hooks": { 31 | "pre-commit": "pretty-quick --staged" 32 | } 33 | }, 34 | "nyc": { 35 | "include": [ 36 | "src/**/*.js" 37 | ], 38 | "reporter": [ 39 | "text-summary", 40 | "html" 41 | ], 42 | "temp-directory": "./.nyc-coverage-temp", 43 | "report-dir": "./.nyc-coverage" 44 | }, 45 | "dependencies": { 46 | "@loadable/babel-plugin": "^5.13.2", 47 | "@loadable/component": "^5.14.1", 48 | "axios": "^0.21.0", 49 | "bulma": "^0.9.1", 50 | "classnames": "^2.2.6", 51 | "core-js": "^3.8.1", 52 | "cross-env": "^7.0.3", 53 | "date-fns": "^2.16.1", 54 | "express": "^4.17.1", 55 | "lodash": "^4.17.20", 56 | "p-min-delay": "^3.1.0", 57 | "react": "^17.0.1", 58 | "react-dom": "^17.0.1", 59 | "react-json-pretty": "^2.2.0", 60 | "react-redux": "^7.2.2", 61 | "react-router-dom": "^5.2.0", 62 | "react-tabify": "0.1.25", 63 | "redux": "^4.0.5", 64 | "redux-entity": "^8.0.20", 65 | "redux-logger": "^3.0.6", 66 | "redux-thunk": "^2.3.0" 67 | }, 68 | "devDependencies": { 69 | "@babel/cli": "^7.12.10", 70 | "@babel/core": "^7.12.10", 71 | "@babel/plugin-proposal-class-properties": "^7.12.1", 72 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 73 | "@babel/preset-env": "^7.12.10", 74 | "@babel/preset-react": "^7.12.10", 75 | "@babel/register": "^7.12.10", 76 | "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3", 77 | "@types/classnames": "^2.2.11", 78 | "@types/lodash": "^4.14.165", 79 | "@types/react": "^17.0.0", 80 | "@types/react-dom": "^17.0.0", 81 | "@types/react-redux": "^7.1.12", 82 | "@types/react-router-dom": "^5.1.6", 83 | "@types/redux-logger": "^3.0.8", 84 | "@typescript-eslint/eslint-plugin": "^4.9.1", 85 | "@typescript-eslint/parser": "^4.9.1", 86 | "autoprefixer": "^10.1.0", 87 | "babel-eslint": "^10.1.0", 88 | "babel-loader": "^8.2.2", 89 | "boxen": "^4.2.0", 90 | "chalk": "^4.1.0", 91 | "coveralls": "^3.1.0", 92 | "css-loader": "^5.0.1", 93 | "eslint": "^7.15.0", 94 | "eslint-config-standard": "^16.0.2", 95 | "eslint-loader": "^4.0.2", 96 | "eslint-plugin-import": "^2.22.1", 97 | "eslint-plugin-node": "^11.1.0", 98 | "eslint-plugin-promise": "^4.2.1", 99 | "eslint-plugin-react": "^7.21.5", 100 | "figlet": "^1.5.0", 101 | "file-loader": "^6.2.0", 102 | "html-webpack-plugin": "^4.5.0", 103 | "husky": "^4.3.5", 104 | "json-loader": "^0.5.7", 105 | "loadable-ts-transformer": "^1.0.0-alpha.3", 106 | "mini-css-extract-plugin": "^1.3.3", 107 | "node-sass": "^5.0.0", 108 | "postcss-loader": "^4.1.0", 109 | "prettier": "^2.2.1", 110 | "pretty-quick": "^2.0.2", 111 | "react-hot-loader": "^4.13.0", 112 | "react-refresh": "^0.9.0", 113 | "redux-mock-store": "^1.5.4", 114 | "rimraf": "^3.0.2", 115 | "sass-loader": "^10.1.0", 116 | "style-loader": "^2.0.0", 117 | "terser-webpack-plugin": "^5.0.3", 118 | "ts-loader": "^8.0.12", 119 | "typescript": "^4.1.3", 120 | "url-loader": "^4.1.1", 121 | "webpack": "^5.10.1", 122 | "webpack-cli": "^4.2.0", 123 | "webpack-dev-server": "^3.11.0" 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [require('autoprefixer')], 3 | }; 4 | -------------------------------------------------------------------------------- /scripts/buildInfo.js: -------------------------------------------------------------------------------- 1 | const boxen = require('boxen'); 2 | const figlet = require('figlet'); 3 | const chalk = require('chalk'); 4 | 5 | const packageJson = require('../package.json'); 6 | const NodeUtils = require('../src/services/common/node-service'); 7 | 8 | /** 9 | * Boxen options as defined by https://www.npmjs.com/package/boxen 10 | * @type {{padding: {top: number, left: number, bottom: number, right: number}}} 11 | */ 12 | const boxenOptions = { 13 | padding: { 14 | left: 13, 15 | right: 13, 16 | top: 1, 17 | bottom: 1, 18 | }, 19 | }; 20 | 21 | /** 22 | * Figlet options as defined by https://github.com/patorjk/figlet.js 23 | * @type {{horizontalLayout: string, font: string}} 24 | */ 25 | const figletOptions = { 26 | font: 'Small Slant', 27 | horizontalLayout: 'controlled smushing', 28 | }; 29 | 30 | const { name, version, author, license } = packageJson; 31 | const details = chalk.cyan(`${author} | Version ${version} | License ${license} `); 32 | 33 | module.exports = function () { 34 | console.log(chalk.cyan(figlet.textSync(name, figletOptions))); 35 | console.log(boxen(details, boxenOptions)); 36 | }; 37 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = require('./config/config'); 4 | const NodeService = require('./src/services/common/node-service'); 5 | 6 | const { example } = config; 7 | if (!example) throw new Error('configuration cannot be null/undefined'); 8 | 9 | const PORT = example.port; 10 | 11 | const express = require('express'); 12 | const path = require('path'); 13 | 14 | const app = express(); 15 | 16 | // Configure static resources 17 | app.use(express.static(path.join(__dirname, '/docs'))); 18 | 19 | // Configure server-side routing 20 | app.get('*', (req, res) => { 21 | const dist = path.join(__dirname, '/docs/index.html'); 22 | res.sendFile(dist); 23 | }); 24 | 25 | // Open socket 26 | app.listen(PORT, () => { 27 | console.log(`Started Express server on port ${PORT}`); 28 | }); 29 | -------------------------------------------------------------------------------- /src/Bootstrap.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { AppContainer } from 'react-hot-loader'; 4 | 5 | import store from '~reducers/store'; 6 | 7 | import Root from '~app/Root'; 8 | 9 | import '~app/styles/global.scss'; 10 | import '~app/assets/favicon.ico'; 11 | 12 | ReactDOM.render( 13 | 14 | 15 | , 16 | document.getElementById('example-app') 17 | ); 18 | -------------------------------------------------------------------------------- /src/Root.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { Provider } from 'react-redux'; 4 | import { BrowserRouter } from 'react-router-dom'; 5 | 6 | import ConfigService from '~services/common/config-service'; 7 | 8 | import App from '~components/App'; 9 | 10 | const Root = ({ store }: { store: any }) => ( 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | 18 | export default Root; 19 | -------------------------------------------------------------------------------- /src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikechabot/react-boilerplate/c45505edb9209a9d9ec5dd8b8ba176ba6f85fbee/src/assets/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikechabot/react-boilerplate/c45505edb9209a9d9ec5dd8b8ba176ba6f85fbee/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames/bind'; 3 | 4 | import NavBar from '~components/common/bulma/Navbar'; 5 | import Footer from '~components/Footer'; 6 | 7 | import ReactRouter from '~components/Sections/ReactRouter'; 8 | import ReduxEntity from '~components/Sections/ReduxEntity'; 9 | import ReduxState from '~components/Sections/ReduxState'; 10 | 11 | import styles from '~components/styles/App.scss'; 12 | 13 | const cx = classnames.bind(styles); 14 | 15 | const App = () => ( 16 |
17 | 18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 |
34 |
35 |
36 |
37 | ); 38 | 39 | export default App; 40 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { Icon, Link } from '~components/common'; 4 | import GithubButtons from '~components/Footer/GithubButtons'; 5 | 6 | import { URL } from '~app/const'; 7 | 8 | const Repository = () => ( 9 | 10 | react-boilerplate 11 | 12 | ); 13 | 14 | const DemoLink = () => source code; 15 | const GithubLink = () => Mike Chabot; 16 | const LicenseLink = () => MIT; 17 | 18 | const Footer = () => { 19 | return ( 20 |
21 |
22 |
23 | by 24 |
25 |
26 | The is licensed under 27 |
28 | 29 |
30 |
31 | ); 32 | }; 33 | 34 | export default Footer; 35 | -------------------------------------------------------------------------------- /src/components/Footer/GithubButtons/GithubButton.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classnames from 'classnames/bind'; 3 | 4 | import styles from '~components/Footer/GithubButtons/styles/GithubButton.scss'; 5 | 6 | const cx = classnames.bind(styles); 7 | 8 | interface GithubButtonProps { 9 | label: string; 10 | icon: string; 11 | href: string; 12 | ariaLabel: string; 13 | } 14 | 15 | const GithubButton: React.FunctionComponent = ({ 16 | label, 17 | icon, 18 | href, 19 | ariaLabel, 20 | }: GithubButtonProps) => { 21 | return ( 22 |
23 | 31 | {label} 32 | 33 |
34 | ); 35 | }; 36 | 37 | export default GithubButton; 38 | -------------------------------------------------------------------------------- /src/components/Footer/GithubButtons/GithubButtons.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classnames from 'classnames/bind'; 3 | 4 | import GithubButton from '~components/Footer/GithubButtons/GithubButton'; 5 | 6 | import styles from '~components/Footer/GithubButtons/styles/GithubButtons.scss'; 7 | 8 | const cx = classnames.bind(styles); 9 | 10 | const GithubButtons = () => ( 11 |
12 | 18 | 24 | 30 |
31 | ); 32 | 33 | export default GithubButtons; 34 | -------------------------------------------------------------------------------- /src/components/Footer/GithubButtons/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './GithubButtons'; 2 | -------------------------------------------------------------------------------- /src/components/Footer/GithubButtons/styles/GithubButton.scss: -------------------------------------------------------------------------------- 1 | .github-button--container { 2 | margin: 5px; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/Footer/GithubButtons/styles/GithubButtons.scss: -------------------------------------------------------------------------------- 1 | .github-buttons { 2 | display: flex; 3 | justify-content: center; 4 | } 5 | -------------------------------------------------------------------------------- /src/components/Footer/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Footer'; 2 | -------------------------------------------------------------------------------- /src/components/Sections/GenericSection.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Icon from '~components/common/Icon'; 3 | 4 | interface GenericSectionProps { 5 | title: string; 6 | subtitle: string | React.ReactNode; 7 | icon: string; 8 | children?: React.ReactNode; 9 | } 10 | 11 | const GenericSection: React.FunctionComponent = ({ 12 | title, 13 | subtitle, 14 | icon, 15 | children, 16 | }: GenericSectionProps) => ( 17 | <> 18 |
19 |

20 | {title} 21 |

22 |

23 | {subtitle} 24 |

25 |
26 | {children} 27 | 28 | ); 29 | 30 | export default GenericSection; 31 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/AsyncTabbedRouter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import pMinDelay from 'p-min-delay'; 3 | import loadable from '@loadable/component'; 4 | import classNames from 'classnames/bind'; 5 | import { Route, useHistory, useLocation } from 'react-router-dom'; 6 | import { Tab, Tabs } from 'react-tabify'; 7 | 8 | import ChunkLoadingIcon from '~components/Sections/ReactRouter/ChunkLoadingIcon'; 9 | 10 | const DELAY = 500; 11 | const options = { 12 | fallback: , 13 | }; 14 | 15 | const AsyncIncrement = loadable( 16 | () => pMinDelay(import('~components/Sections/ReactRouter/Routes/IncrementRoute'), DELAY), 17 | options 18 | ); 19 | const AsyncDecrement = loadable( 20 | () => pMinDelay(import('~components/Sections/ReactRouter/Routes/DecrementRoute'), DELAY), 21 | options 22 | ); 23 | const AsyncReset = loadable( 24 | () => pMinDelay(import('~components/Sections/ReactRouter/Routes/ResetRoute'), DELAY), 25 | options 26 | ); 27 | 28 | const AsyncTabbedRouter = () => { 29 | const location = useLocation(); 30 | const history = useHistory(); 31 | 32 | return ( 33 |
34 | history.push(eventKey)}> 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 | ); 47 | }; 48 | 49 | export default AsyncTabbedRouter; 50 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/ChunkLoadingIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames/bind'; 3 | 4 | import { CogIcon } from '~components/common/Icon'; 5 | 6 | import styles from '~components/Sections/ReactRouter/styles/ChunkLoadingIcon.scss'; 7 | 8 | const cx = classnames.bind(styles); 9 | 10 | const ChunkLoadingIcon = () => ( 11 |
12 | 13 |
14 | ); 15 | 16 | export default ChunkLoadingIcon; 17 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/ReactRouter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import GenericSection from '~components/Sections/GenericSection'; 4 | import AsyncTabbedRouter from '~components/Sections/ReactRouter/AsyncTabbedRouter'; 5 | 6 | import { URL } from '~app/const'; 7 | 8 | const ReactRouter = () => ( 9 | 14 | Utilizes react-router v5 for client-side routing 15 | 16 | } 17 | > 18 | 19 | 20 | ); 21 | 22 | export default ReactRouter; 23 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/Routes/DecrementRoute.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import RouteContent from '~components/Sections/ReactRouter/Routes/RouteContent'; 4 | 5 | import { decrementAction } from '~reducers/counter/actions'; 6 | 7 | const DecrementRoute = () => ; 8 | 9 | export default DecrementRoute; 10 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/Routes/IncrementRoute.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import RouteContent from '~components/Sections/ReactRouter/Routes/RouteContent'; 4 | 5 | import { incrementAction } from '~reducers/counter/actions'; 6 | 7 | const IncrementRoute = () => ; 8 | 9 | export default IncrementRoute; 10 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/Routes/ResetRoute.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import RouteContent from '~components/Sections/ReactRouter/Routes/RouteContent'; 4 | 5 | import { resetAction } from '~reducers/counter/actions'; 6 | 7 | const ResetRoute = () => ; 8 | 9 | export default ResetRoute; 10 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/Routes/RouteContent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames/bind'; 3 | import { connect, useSelector, useDispatch } from 'react-redux'; 4 | 5 | import Icon from '~components/common/Icon'; 6 | 7 | import { RootState } from '~app/reducers'; 8 | 9 | import styles from '~components/Sections/ReactRouter/Routes/styles/RouteContent.scss'; 10 | 11 | const cx = classnames.bind(styles); 12 | 13 | interface RouteContentProps { 14 | path: string; 15 | label: string; 16 | action: () => void; 17 | icon: string; 18 | } 19 | 20 | const RouteContent: React.FunctionComponent = ({ path, label, action, icon }: RouteContentProps) => { 21 | const dispatch = useDispatch(); 22 | const counter = useSelector((state: RootState) => state.counter); 23 | 24 | return ( 25 |
26 |
27 | 28 |  Connected to the Redux store at the {path || '/'} route 29 |
30 |
31 | 32 |  counter: {counter} 33 |
34 |
35 |
36 | 40 |
41 |
42 | ); 43 | }; 44 | 45 | export default RouteContent; 46 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/Routes/styles/RouteContent.scss: -------------------------------------------------------------------------------- 1 | .route-content--container { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 10px; 5 | 6 | .route-content--header, 7 | .route-content--counter { 8 | display: flex; 9 | align-content: center; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ReactRouter'; 2 | -------------------------------------------------------------------------------- /src/components/Sections/ReactRouter/styles/ChunkLoadingIcon.scss: -------------------------------------------------------------------------------- 1 | .chunk-loading--icon { 2 | height: 60px; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/Entities.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames/bind'; 3 | 4 | import { useDispatch, useSelector } from 'react-redux'; 5 | 6 | import Entity from '~components/Sections/ReduxEntity/Entity'; 7 | 8 | import { fetchBar, fetchBaz, fetchFoo } from '~reducers/entities/actions'; 9 | 10 | import { RootState } from '~app/reducers'; 11 | import { EntityType } from '~reducers/entities/types'; 12 | 13 | import styles from '~components/Sections/ReduxEntity/styles/ReduxEntity.scss'; 14 | 15 | const cx = classnames.bind(styles); 16 | 17 | const Entities = () => { 18 | const dispatch = useDispatch(); 19 | const entities = useSelector((state: RootState) => state.entities); 20 | 21 | /** 22 | * Get the fetch thunk based on the entity type 23 | * @param type 24 | */ 25 | const getLoadEntityThunk = (type: EntityType) => { 26 | switch (type) { 27 | case EntityType.Foo: 28 | return () => dispatch(fetchFoo()); 29 | case EntityType.Bar: 30 | return () => dispatch(fetchBar()); 31 | case EntityType.Baz: 32 | return () => dispatch(fetchBaz()); 33 | } 34 | }; 35 | 36 | return ( 37 |
38 | {Object.values(EntityType).map((key: string) => ( 39 | 46 | ))} 47 |
48 | ); 49 | }; 50 | 51 | export default Entities; 52 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/Entity.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { useDispatch } from 'react-redux'; 3 | 4 | import isEmpty from 'lodash/isEmpty'; 5 | 6 | import { Button } from '~components/common'; 7 | 8 | import EntityData from '~components/Sections/ReduxEntity/Entity/EntityData'; 9 | import EntityReset from '~components/Sections/ReduxEntity/Entity/EntityReset'; 10 | import EntityMissing from '~components/Sections/ReduxEntity/Entity/EntityMissing'; 11 | import EntityFailure from '~components/Sections/ReduxEntity/Entity/EntityFailure'; 12 | import EntityLoading from '~components/Sections/ReduxEntity/Entity/EntityLoading'; 13 | 14 | import { DeleteEntity, ResetEntity, EntityState } from 'redux-entity'; 15 | 16 | interface EntityProps { 17 | name: string; 18 | append: boolean; 19 | entity: EntityState; 20 | fetchEntity: () => void; 21 | } 22 | 23 | const Entity: React.FunctionComponent = ({ name, append, entity, fetchEntity }: EntityProps) => { 24 | const dispatch = useDispatch(); 25 | 26 | useEffect(() => { 27 | fetchEntity(); 28 | }, []); 29 | 30 | if (isEmpty(entity)) { 31 | return ; 32 | } 33 | 34 | const { isFetching, data, error, lastUpdated } = entity; 35 | 36 | let body; 37 | 38 | if (error) { 39 | body = ; 40 | } else if (isFetching) { 41 | body = ; 42 | } else if (isEmpty(data)) { 43 | body = ; 44 | } else { 45 | body = ; 46 | } 47 | 48 | return ( 49 |
50 | {body} 51 |
52 | 55 | 58 | 61 |
62 |
63 | ); 64 | }; 65 | 66 | export default Entity; 67 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/Entity/EntityData.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { format } from 'date-fns'; 3 | 4 | import { Icon } from '~components/common'; 5 | import { CheckIcon } from '~components/common/Icon'; 6 | 7 | interface EntityDataProps { 8 | name: string; 9 | append: boolean; 10 | lastUpdated?: Date; 11 | } 12 | 13 | const EntityData: React.FunctionComponent = ({ name, append, lastUpdated }: EntityDataProps) => { 14 | const action = append ? 'Appending to ' : 'Fetch for '; 15 | const date = lastUpdated && format(new Date(lastUpdated), 'pp'); 16 | return ( 17 |
18 | {action} {name} @ {date} 19 |
20 | ); 21 | }; 22 | 23 | export default EntityData; 24 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/Entity/EntityFailure.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { Icon } from '~components/common'; 4 | import { ExclamationIcon } from '~components/common/Icon'; 5 | 6 | interface EntityFailureProps { 7 | name: string; 8 | error: any; 9 | } 10 | 11 | const EntityFailure: React.FunctionComponent = ({ name, error }: EntityFailureProps) => ( 12 |
13 | Failed to fetch {name} due to{' '} 14 | {error.toString()} 15 |
16 | ); 17 | 18 | export default EntityFailure; 19 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/Entity/EntityLoading.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const EntityLoading = () =>
Fetching fresh data!
; 4 | 5 | export default EntityLoading; 6 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/Entity/EntityMissing.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Icon from '~components/common/Icon'; 4 | import { Button } from '~components/common'; 5 | 6 | interface NoEntityProps { 7 | name: string; 8 | fetchEntity: () => void; 9 | } 10 | 11 | const EntityMissing: React.FunctionComponent = ({ name, fetchEntity }: NoEntityProps) => ( 12 | <> 13 |
14 | 15 |  Entity {name} does not exist on entities 16 |
17 | 20 | 21 | ); 22 | 23 | export default EntityMissing; 24 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/Entity/EntityReset.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | interface EntityReset { 4 | name: string; 5 | } 6 | 7 | const EntityReset: React.FunctionComponent = ({ name }: EntityReset) => ( 8 |
9 | Entity {name} has been cleared. 10 |
11 | ); 12 | 13 | export default EntityReset; 14 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/ReduxEntity.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import GenericSection from '~components/Sections/GenericSection'; 4 | import Entities from '~components/Sections/ReduxEntity/Entities'; 5 | 6 | import { URL } from '~app/const'; 7 | 8 | const ReduxEntity = () => ( 9 | 14 | Utilizes redux-entity for domain entity management 15 | 16 | } 17 | > 18 | 19 | 20 | ); 21 | 22 | export default ReduxEntity; 23 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ReduxEntity'; 2 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxEntity/styles/ReduxEntity.scss: -------------------------------------------------------------------------------- 1 | .redux-entity--container { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxState/ReduxState.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import JSONPretty from 'react-json-pretty'; 3 | import { useSelector } from 'react-redux'; 4 | 5 | import GenericSection from '~components/Sections/GenericSection'; 6 | 7 | const themeProps = { 8 | keyStyle: 'color: #3298dc;', 9 | }; 10 | 11 | /** 12 | * Stringify errors 13 | * @param key 14 | * @param value 15 | */ 16 | const replacer = (key: string, value: any) => { 17 | return value instanceof Error ? value.toString() : value; 18 | }; 19 | 20 | const ReduxState = () => { 21 | const state = useSelector((state) => state); 22 | return ( 23 | Open Console to view dispatched actions}> 24 | 25 | 26 | ); 27 | }; 28 | 29 | export default ReduxState; 30 | -------------------------------------------------------------------------------- /src/components/Sections/ReduxState/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ReduxState'; 2 | -------------------------------------------------------------------------------- /src/components/common/Button.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Icon from '~components/common/Icon'; 4 | 5 | interface ButtonProps { 6 | icon: string; 7 | disabled?: boolean; 8 | loading?: boolean; 9 | theme?: string; 10 | onClick: () => void; 11 | children: React.ReactNode; 12 | } 13 | 14 | const Button: React.FunctionComponent = ({ 15 | icon, 16 | disabled, 17 | loading, 18 | onClick, 19 | children, 20 | theme = '', 21 | }: ButtonProps) => ( 22 |

23 | {/* @ts-ignore */} 24 | 25 | 26 | 27 | 28 | {children} 29 | 30 |

31 | ); 32 | 33 | export default Button; 34 | -------------------------------------------------------------------------------- /src/components/common/Icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface IconProps { 4 | icon: string; 5 | prefix?: string; 6 | className?: string; 7 | size?: string; 8 | } 9 | 10 | export const ExclamationIcon = () => ; 11 | export const CheckIcon = () => ; 12 | export const CogIcon = ({ size, className }: { size?: string; className?: string }) => ( 13 | 14 | ); 15 | 16 | const Icon: React.FunctionComponent = ({ icon, prefix, className, size = 'fa-1x' }: IconProps) => { 17 | const iconPrefix = prefix || 'fa'; 18 | return ( 19 | 20 | 21 | 22 | ); 23 | }; 24 | 25 | export default Icon; 26 | -------------------------------------------------------------------------------- /src/components/common/Link.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | interface LinkProps { 4 | url: string; 5 | children: React.ReactNode; 6 | } 7 | 8 | const Link: React.FunctionComponent = ({ url, children }: LinkProps) => ( 9 | 10 | {children} 11 | 12 | ); 13 | 14 | export default Link; 15 | -------------------------------------------------------------------------------- /src/components/common/bulma/NavBar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classname from 'classnames/bind'; 3 | 4 | import { Icon } from '~components/common'; 5 | 6 | import logo from '~assets/logo.png'; 7 | 8 | import { URL } from '~app/const'; 9 | 10 | import styles from '~components/common/bulma/styles/NavBar.scss'; 11 | 12 | const cx = classname.bind(styles); 13 | 14 | const NavBar = () => { 15 | return ( 16 | 40 | ); 41 | }; 42 | 43 | export default NavBar; 44 | -------------------------------------------------------------------------------- /src/components/common/bulma/styles/NavBar.scss: -------------------------------------------------------------------------------- 1 | .nav-bar--container { 2 | flex-shrink: 0; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/common/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Icon } from './Icon'; 2 | export { default as Button } from './Button'; 3 | export { default as Link } from './Link'; 4 | -------------------------------------------------------------------------------- /src/components/styles/App.scss: -------------------------------------------------------------------------------- 1 | .react-boilerplate { 2 | display: flex; 3 | flex-direction: column; 4 | height: 100%; 5 | } 6 | 7 | .section--body { 8 | height: 100%; 9 | } 10 | -------------------------------------------------------------------------------- /src/const/index.ts: -------------------------------------------------------------------------------- 1 | export const URL = { 2 | GITHUB: 'https://github.com/mikechabot', 3 | REPOSITORY: 'http://www.github.com/mikechabot/react-boilerplate', 4 | NPM: 'https://www.npmjs.com/~mikechabot', 5 | DEMO: 'https://github.com/mikechabot/react-boilerplate', 6 | LICENSE: 'https://github.com/mikechabot/react-boilerplate/blob/master/LICENSE', 7 | REDUX_ENTITY: 'https://github.com/mikechabot/redux-entity', 8 | REACT_ROUTER: 'https://github.com/ReactTraining/react-router', 9 | }; 10 | -------------------------------------------------------------------------------- /src/global.ts: -------------------------------------------------------------------------------- 1 | declare module '*.scss' { 2 | const content: { [className: string]: string }; 3 | export default content; 4 | } 5 | 6 | declare module '*.png'; 7 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | react-boilerplate 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/reducers/counter/actions.ts: -------------------------------------------------------------------------------- 1 | import { INCREMENT_COUNTER, DECREMENT_COUNTER, RESET_COUNTER } from '~reducers/counter/reducer'; 2 | 3 | export const incrementAction = () => ({ type: INCREMENT_COUNTER }); 4 | export const decrementAction = () => ({ type: DECREMENT_COUNTER }); 5 | export const resetAction = () => ({ type: RESET_COUNTER }); 6 | -------------------------------------------------------------------------------- /src/reducers/counter/reducer.ts: -------------------------------------------------------------------------------- 1 | export const INCREMENT_COUNTER = 'react-boilerplate/counter/INCREMENT_COUNTER'; 2 | export const DECREMENT_COUNTER = 'react-boilerplate/counter/DECREMENT_COUNTER'; 3 | export const RESET_COUNTER = 'react-boilerplate/counter/RESET_COUNTER'; 4 | 5 | const INITIAL_STATE = 0; 6 | 7 | /** 8 | * Reducer for the management of the counter 9 | * @param state 10 | * @param action 11 | */ 12 | const reducer = (state = INITIAL_STATE, action: any) => { 13 | switch (action.type) { 14 | case INCREMENT_COUNTER: { 15 | return state + 1; 16 | } 17 | case DECREMENT_COUNTER: { 18 | return state - 1; 19 | } 20 | case RESET_COUNTER: { 21 | return INITIAL_STATE; 22 | } 23 | default: { 24 | return state; 25 | } 26 | } 27 | }; 28 | 29 | export default reducer; 30 | -------------------------------------------------------------------------------- /src/reducers/entities/actions.ts: -------------------------------------------------------------------------------- 1 | import { GetEntity } from 'redux-entity'; 2 | 3 | import { fetchMockData } from '~services/domain/domain-service'; 4 | 5 | import { EntityType } from '~reducers/entities/types'; 6 | 7 | /** 8 | * Thunk action that simulates a delayed API call 9 | * @returns {Function} thunk 10 | */ 11 | export function fetchFoo() { 12 | return GetEntity(EntityType.Foo, fetchMockData()); 13 | } 14 | 15 | /** 16 | * Thunk action that simulates a delayed API call 17 | * @returns {Function} thunk 18 | */ 19 | export function fetchBar() { 20 | return GetEntity(EntityType.Bar, fetchMockData(), { append: true }); 21 | } 22 | 23 | /** 24 | * Thunk action that simulates a delayed, failed API call 25 | * @returns {Function} thunk 26 | */ 27 | export function fetchBaz() { 28 | return GetEntity(EntityType.Baz, fetchMockData(true)); 29 | } 30 | -------------------------------------------------------------------------------- /src/reducers/entities/reducer.ts: -------------------------------------------------------------------------------- 1 | export { reducer as default } from 'redux-entity/lib'; 2 | -------------------------------------------------------------------------------- /src/reducers/entities/types.ts: -------------------------------------------------------------------------------- 1 | export enum EntityType { 2 | Foo = 'foo', 3 | Bar = 'bar', 4 | Baz = 'baz', 5 | } 6 | -------------------------------------------------------------------------------- /src/reducers/index.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import entities from '~reducers/entities/reducer'; 4 | import counter from '~reducers/counter/reducer'; 5 | 6 | const rootReducer = combineReducers({ 7 | counter, 8 | entities, 9 | }); 10 | 11 | export type RootState = ReturnType; 12 | 13 | export default rootReducer; 14 | -------------------------------------------------------------------------------- /src/reducers/store/configure-store.dev.ts: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import logger from 'redux-logger'; 4 | 5 | import rootReducer from '~reducers/index'; 6 | 7 | /** 8 | * Development Redux store 9 | * @param {object} initialState Initial state of the Redux store 10 | * @return {object} Redux store 11 | */ 12 | export default function configureStore(initialState: any = {}) { 13 | return createStore(rootReducer, initialState, applyMiddleware(thunk, logger)); 14 | } 15 | -------------------------------------------------------------------------------- /src/reducers/store/configure-store.prod.ts: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | 4 | import rootReducer from '~reducers/index'; 5 | 6 | /** 7 | * LOGGER IN PROD FOR DEMO PAGES ONLY! 8 | * > Remove this import and the middleware below before going live. 9 | * > https://mikechabot.github.io/react-boilerplate/ 10 | */ 11 | import logger from 'redux-logger'; 12 | 13 | /** 14 | * Production Redux store 15 | * @param {object} initialState Initial state of the Redux store 16 | * @return {object} Redux store 17 | */ 18 | export default function configureStore(initialState: any = {}) { 19 | return createStore( 20 | rootReducer, 21 | initialState, 22 | // applyMiddleware(thunk), // USE ME IN PROD! 23 | applyMiddleware(thunk, logger) // DON'T USE ME IN PROD! 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /src/reducers/store/index.ts: -------------------------------------------------------------------------------- 1 | import NodeService from '~services/common/node-service'; 2 | 3 | import production from './configure-store.prod'; 4 | import development from './configure-store.dev'; 5 | 6 | /** 7 | * Determine which Redux store to provide based on the 8 | * Environment Type of Node.js 9 | * @return {object} Redux store 10 | */ 11 | 12 | export default NodeService.isProduction() ? production() : development(); 13 | -------------------------------------------------------------------------------- /src/services/common/config-service.js: -------------------------------------------------------------------------------- 1 | const NodeUtils = require('./node-service'); 2 | const get = require('lodash/get'); 3 | 4 | module.exports = { 5 | getConfig() { 6 | return process.env.APP_CONFIG; 7 | }, 8 | getProperty(key) { 9 | if (!key) throw new Error('Key cannot be null/undefined'); 10 | return get(this.getConfig(), key); 11 | }, 12 | getRequiredProperty(key) { 13 | const value = this.getProperty(key); 14 | if (value) return value; 15 | if (!NodeUtils.isTest()) { 16 | throw new Error(`Missing required property: "${key}"`); 17 | } 18 | }, 19 | getPort() { 20 | return this.getRequiredProperty('example.port'); 21 | }, 22 | getBasePath() { 23 | return this.getRequiredProperty('example.basePath'); 24 | }, 25 | getBaseUrl() { 26 | return this.getRequiredProperty('example.baseUrl'); 27 | }, 28 | getPublicBasename() { 29 | return NodeUtils.isGhPages() ? this.getRequiredProperty('example.publicBasename') : '/'; 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /src/services/common/node-service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | getNodeEnv: function () { 5 | return process.env; 6 | }, 7 | getNodeEnvByKey: function (key) { 8 | if (!key) throw new Error('Key cannot be null/undefined'); 9 | return process.env[key]; 10 | }, 11 | getNodeEnvMode: function () { 12 | return this.getNodeEnvByKey('NODE_ENV') || 'test'; 13 | }, 14 | isProduction: function () { 15 | return this.getNodeEnvMode() === 'production'; 16 | }, 17 | isDevelopment: function () { 18 | return this.getNodeEnvMode() === 'development'; 19 | }, 20 | isGhPages: function () { 21 | return this.getNodeEnvMode() === 'gh-pages'; 22 | }, 23 | isTest: function () { 24 | return !this.getNodeEnvMode() || this.getNodeEnvMode() === 'test'; 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /src/services/data/ajax-service.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosRequestConfig } from 'axios'; 2 | 3 | import ConfigService from '~services/common/config-service'; 4 | 5 | /** 6 | * Service for making AJAX requests. 7 | * Uses Axios (https://github.com/mzabriskie/axios) 8 | */ 9 | const instance = axios.create({ 10 | baseURL: ConfigService.getBaseUrl(), 11 | timeout: 4000, 12 | }); 13 | 14 | export default { 15 | request: (options: AxiosRequestConfig) => instance.request(options), 16 | }; 17 | -------------------------------------------------------------------------------- /src/services/data/data-access-service.ts: -------------------------------------------------------------------------------- 1 | import AjaxService from './ajax-service'; 2 | 3 | import { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'; 4 | 5 | interface HttpError extends AxiosError, AxiosResponse { 6 | message: string; 7 | } 8 | 9 | enum HttpMethod { 10 | GET = 'GET', 11 | POST = 'POST', 12 | PUT = 'PUT', 13 | DELETE = 'DELETE', 14 | } 15 | 16 | function deriveError(error: HttpError) { 17 | if (!error) { 18 | return new Error('An unknown error occurred'); 19 | } else if (!error.message) { 20 | return `${error.status} ${error.statusText}`; 21 | } 22 | return error; 23 | } 24 | 25 | /** 26 | * HTTP service capable of performing GET and POST requests 27 | * This service will be injected into domain services (e.g. PatientService, MedicationService) 28 | * Agnostic of prototype/production 29 | */ 30 | const request = (method: HttpMethod, url: string, data?: any, options?: AxiosRequestConfig) => { 31 | const defaultOptions: AxiosRequestConfig = { 32 | url: url, 33 | method: method, 34 | responseType: 'json', 35 | }; 36 | 37 | if (data) { 38 | defaultOptions.data = JSON.stringify(data); 39 | defaultOptions.headers = { 40 | 'Content-Type': 'application/json', 41 | }; 42 | } 43 | 44 | let requestOptions = defaultOptions; 45 | if (options) { 46 | requestOptions = { ...defaultOptions, ...options }; 47 | } 48 | 49 | // Resolve the original request, and wrap the response in another promise. 50 | // This allows allows us to peer into the response before giving it back 51 | // to the caller, which is helpful when handling situations where a response 52 | // is technically successful from an AJAX perspective (200 OK), but failed 53 | // server-side due an arbitrary error (i.e. validation error). 54 | return new Promise((resolve, reject) => { 55 | AjaxService.request(requestOptions) 56 | .then(resolve) 57 | .catch((error) => reject(deriveError(error))); 58 | }); 59 | }; 60 | 61 | export const get = (url: string, options?: AxiosRequestConfig) => request(HttpMethod.GET, url, undefined, options); 62 | 63 | export const post = (url: string, data?: any, options?: AxiosRequestConfig) => 64 | request(HttpMethod.POST, url, data, options); 65 | -------------------------------------------------------------------------------- /src/services/domain/domain-service.ts: -------------------------------------------------------------------------------- 1 | import { get, post } from '~services/data/data-access-service'; 2 | import { randomNumber } from '~services/util'; 3 | 4 | const fakeError = new Error('Fake Error!'); 5 | 6 | /** 7 | * Example of utilizing DataAccessService 8 | */ 9 | export const fetchFoo = (id: string) => get(`/foo/${id}`); 10 | export const postFoo = (id: string, data: any) => post(`/foo/${id}`, data); 11 | 12 | /** 13 | * Mock an API response 14 | * @param doReject 15 | */ 16 | export const fetchMockData = (doReject = false) => { 17 | const delay: number = randomNumber(); 18 | const payload = { delay }; 19 | return new Promise((resolve, reject) => { 20 | setTimeout(() => (doReject ? reject(fakeError) : resolve(payload)), delay * 1000); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /src/services/util/index.ts: -------------------------------------------------------------------------------- 1 | const MIN_DELAY = 1; 2 | const MAX_DELAY = 3; 3 | 4 | /** 5 | * Generate a random number between a min and max 6 | */ 7 | export function randomNumber(): number { 8 | return Number(Math.random() * (MAX_DELAY - MIN_DELAY) + MIN_DELAY); 9 | } 10 | -------------------------------------------------------------------------------- /src/styles/global.scss: -------------------------------------------------------------------------------- 1 | @import 'mixins'; 2 | 3 | body, 4 | html { 5 | width: 100%; 6 | height: 100%; 7 | font: $font-stack; 8 | } 9 | 10 | #example-app { 11 | margin: 0; 12 | width: 100%; 13 | height: 100%; 14 | } 15 | 16 | code { 17 | font-size: 1.1rem; 18 | color: hsl(0, 0%, 29%); 19 | } 20 | 21 | .notification code { 22 | background: hsl(0, 0%, 90%); 23 | } 24 | 25 | $sizeUnit: rem; 26 | $marginKey: 'm'; 27 | $paddingKey: 'p'; 28 | $separator: '-'; 29 | $sizes: (('none', 0), ('xxs', 0.125), ('xs', 0.25), ('sm', 0.5), ('md', 1), ('lg', 2), ('xl', 4), ('xxl', 8)); 30 | $positions: (('t', 'top'), ('r', 'right'), ('b', 'bottom'), ('l', 'left')); 31 | 32 | @function sizeValue($key, $value) { 33 | @return if($key == 'none', 0, $value + $sizeUnit); 34 | } 35 | 36 | @each $size in $sizes { 37 | $sizeKey: nth($size, 1); 38 | $sizeValue: nth($size, 2); 39 | .#{$marginKey}#{$separator}#{$sizeKey} { 40 | margin: sizeValue($sizeKey, $sizeValue); 41 | } 42 | .#{$paddingKey}#{$separator}#{$sizeKey} { 43 | padding: sizeValue($sizeKey, $sizeValue); 44 | } 45 | @each $position in $positions { 46 | $posKey: nth($position, 1); 47 | $posValue: nth($position, 2); 48 | .#{$marginKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} { 49 | margin-#{$posValue}: sizeValue($sizeKey, $sizeValue); 50 | } 51 | .#{$paddingKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} { 52 | padding-#{$posValue}: sizeValue($sizeKey, $sizeValue); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/styles/mixins.scss: -------------------------------------------------------------------------------- 1 | @import '~bulma/sass/utilities/initial-variables'; 2 | @import '~bulma/sass/utilities/functions'; 3 | 4 | $family-serif: Inconsolata, Consolas, monospace; 5 | $link: hsl(204, 86%, 53%); 6 | 7 | @import '~bulma/bulma'; 8 | 9 | .navbar-item img { 10 | max-height: none; 11 | } 12 | 13 | .notification a:not(.button) { 14 | text-decoration: none; 15 | } 16 | 17 | .navbar.is-dark .navbar-brand > a.navbar-item:hover { 18 | background: unset; 19 | } 20 | 21 | $font-stack: 1rem Inconsolata; 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "exclude": ["./src/**/*.spec.ts"], 4 | "compilerOptions": { 5 | "target": "es6", 6 | "moduleResolution": "Node", 7 | "module": "commonjs", 8 | "lib": ["es6", "DOM"], 9 | "jsx": "react", 10 | "allowJs": true, 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "esModuleInterop": true, 14 | "resolveJsonModule": true, 15 | "baseUrl": "src", 16 | "paths": { 17 | "~app/*": ["*"], 18 | "~assets/*": ["assets/*"], 19 | "~components/*": ["components/*"], 20 | "~reducers/*": ["reducers/*"], 21 | "~services/*": ["services/*"] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 7 | const TerserPlugin = require('terser-webpack-plugin'); 8 | const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); 9 | 10 | /** 11 | * react-boilerplate scripts 12 | */ 13 | const NodeUtils = require('./src/services/common/node-service'); 14 | const buildInfo = require('./scripts/buildInfo'); 15 | const appConfig = require('./config/config'); 16 | 17 | buildInfo(); 18 | 19 | const APP_DIR = path.join(__dirname, 'src'); 20 | const NODE_MODULES = path.join(__dirname, 'node_modules'); 21 | 22 | const isDevelopment = NodeUtils.isDevelopment(); 23 | 24 | /** 25 | * Get webpack plugins 26 | * @returns {*[]} 27 | */ 28 | function getPlugins() { 29 | return [ 30 | new MiniCssExtractPlugin({ 31 | filename: isDevelopment ? '[name].css' : '[name].[contenthash].css', 32 | chunkFilename: isDevelopment ? '[id].css' : '[id].[contenthash].css', 33 | }), 34 | 35 | /** 36 | * Inject bundles and CSS directly into the HTML template 37 | */ 38 | new HtmlWebpackPlugin({ 39 | template: path.resolve(__dirname, 'src/index.html'), 40 | inject: 'body', 41 | }), 42 | 43 | /** 44 | * Pass NODE_ENV and APP_CONFIG to the application so that 45 | * "ConfigService" and "NodeService" can be used within TS/TSX files. 46 | */ 47 | new webpack.DefinePlugin({ 48 | 'process.env': { 49 | NODE_ENV: JSON.stringify(process.env.NODE_ENV), 50 | APP_CONFIG: JSON.stringify(appConfig), 51 | }, 52 | }), 53 | ]; 54 | } 55 | 56 | /** 57 | * Set up code splitting and chunking 58 | */ 59 | function getCodeSplittingConfig() { 60 | return { 61 | splitChunks: { 62 | cacheGroups: { 63 | commons: { 64 | test: /[\\/]node_modules[\\/]/, 65 | name: 'vendor', 66 | chunks: 'initial', 67 | }, 68 | }, 69 | }, 70 | runtimeChunk: { 71 | name: 'manifest', 72 | }, 73 | minimizer: [ 74 | new TerserPlugin({ 75 | terserOptions: { 76 | ecma: 8, 77 | mangle: false, 78 | keep_classnames: true, 79 | keep_fnames: true, 80 | }, 81 | }), 82 | ], 83 | }; 84 | } 85 | 86 | /** 87 | * Get Webpack file parsing rules 88 | * @returns {*[]} 89 | */ 90 | function getParserRules() { 91 | return [ 92 | { 93 | test: /\.(sa|sc|c)ss$/, 94 | use: [ 95 | { 96 | loader: MiniCssExtractPlugin.loader, 97 | options: {}, 98 | }, 99 | 'css-loader', 100 | 'postcss-loader', 101 | 'sass-loader', 102 | ], 103 | include: APP_DIR, 104 | exclude: NODE_MODULES, 105 | }, 106 | { 107 | test: /\.(js|jsx)$/, 108 | use: 'babel-loader', 109 | include: APP_DIR, 110 | exclude: NODE_MODULES, 111 | }, 112 | { 113 | test: /\.tsx?$/, 114 | use: 'ts-loader', 115 | include: APP_DIR, 116 | exclude: NODE_MODULES, 117 | }, 118 | { 119 | test: /\.(eot|woff|woff2|ttf|svg|png|jpg)$/, 120 | use: 'url-loader?limit=10000&name=[name]-[hash].[ext]', 121 | include: APP_DIR, 122 | exclude: NODE_MODULES, 123 | }, 124 | { 125 | test: /\.ico$/, 126 | use: 'file-loader?name=[name].[ext]', 127 | exclude: NODE_MODULES, 128 | }, 129 | { 130 | test: /\.json$/, 131 | use: 'json-loader', 132 | include: APP_DIR, 133 | exclude: NODE_MODULES, 134 | }, 135 | ]; 136 | } 137 | 138 | const webpackConfig = { 139 | /** 140 | * Configure the output directory and bundle name 141 | */ 142 | output: { 143 | path: path.join(__dirname, 'docs'), 144 | filename: '[name].[hash].js', 145 | }, 146 | resolve: { 147 | /** 148 | * Allow webpack to automatically resolve import extensions 149 | */ 150 | extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', 'scss'], 151 | /** 152 | * Define aliases to be used within import statements. 153 | * Be sure to update "tsconfig.json" if you add/update/delete aliases. 154 | */ 155 | alias: { 156 | '~app': path.resolve(APP_DIR), 157 | '~assets': path.resolve(APP_DIR, 'assets/'), 158 | '~components': path.resolve(APP_DIR, 'components/'), 159 | '~reducers': path.resolve(APP_DIR, 'reducers/'), 160 | '~services': path.resolve(APP_DIR, 'services/'), 161 | }, 162 | }, 163 | /** 164 | * Set up code splitting and chunking 165 | */ 166 | optimization: getCodeSplittingConfig(), 167 | /** 168 | * Set up webpack plugins 169 | */ 170 | plugins: getPlugins(), 171 | /** 172 | * Set up module parsing rules 173 | */ 174 | module: { 175 | rules: getParserRules(), 176 | }, 177 | }; 178 | 179 | /** 180 | * Add additional configurations based on NODE_ENV 181 | */ 182 | if (!NodeUtils.isDevelopment()) { 183 | webpackConfig.entry = './src/Bootstrap'; 184 | webpackConfig.mode = 'production'; 185 | } else { 186 | webpackConfig.mode = 'development'; 187 | webpackConfig.entry = [ 188 | `webpack-dev-server/client?http://localhost:${appConfig.example.port}`, 189 | 'webpack/hot/only-dev-server', 190 | './src/Bootstrap', 191 | ]; 192 | webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin()); 193 | webpackConfig.plugins.push(new ReactRefreshWebpackPlugin({ overlay: false })); 194 | 195 | webpackConfig.devServer = { 196 | open: true, 197 | port: appConfig.example.port, 198 | stats: 'errors-only', 199 | inline: true, 200 | injectClient: false, 201 | historyApiFallback: true, 202 | }; 203 | } 204 | 205 | module.exports = webpackConfig; 206 | --------------------------------------------------------------------------------