├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .travis.yml
├── LICENSE
├── Procfile
├── README.md
├── dist
├── index.html
├── main.098aa9ee0d410b880d633a4523eae478.css
├── main.098aa9ee0d410b880d633a4523eae478.css.map
├── main.0ce33a1ad2a5961809c0.js
└── main.0ce33a1ad2a5961809c0.js.map
├── dist_server
├── index.html
├── main.098aa9ee0d410b880d633a4523eae478.css
├── main.098aa9ee0d410b880d633a4523eae478.css.map
├── main.0ce33a1ad2a5961809c0.js
├── main.0ce33a1ad2a5961809c0.js.map
└── server.js
├── package.json
├── src
├── actions
│ ├── ajaxStatusActions.js
│ ├── authActions.js
│ ├── commentActions.js
│ └── notificationActions.js
├── api
│ ├── auth.js
│ ├── comments.js
│ └── index.js
├── components
│ ├── App.js
│ ├── Auth
│ │ ├── LoginForm.js
│ │ ├── LoginPage.js
│ │ └── style.scss
│ ├── Comments
│ │ ├── CommentForm.js
│ │ ├── CommentList.js
│ │ ├── CommentMain.js
│ │ ├── CommentPage.js
│ │ ├── ManageCommentPage.js
│ │ └── style.scss
│ ├── Home
│ │ ├── HomePage.js
│ │ ├── Welcome.js
│ │ └── style.scss
│ ├── Main.js
│ ├── MainContent
│ │ ├── index.js
│ │ └── style.scss
│ ├── Notifications
│ │ ├── index.js
│ │ └── style.scss
│ ├── PageNotFound.js
│ ├── SideNavigation
│ │ ├── index.js
│ │ └── style.scss
│ ├── TopAppBar
│ │ ├── index.js
│ │ └── style.scss
│ ├── _globals.scss
│ ├── common
│ │ ├── Preloader.js
│ │ └── style.scss
│ ├── style.scss
│ └── theme
│ │ └── _config.scss
├── constants
│ └── actionTypes.js
├── favicon.ico
├── index.ejs
├── index.js
├── models
│ ├── Comment.js
│ └── User.js
├── reducers
│ ├── ajaxStatusReducer.js
│ ├── authReducer.js
│ ├── commentReducer.js
│ ├── index.js
│ ├── initialState.js
│ └── notificationsReducer.js
├── routes.js
├── store
│ ├── configureStore.dev.js
│ ├── configureStore.js
│ └── configureStore.prod.js
├── style.scss
├── utils
│ ├── ajax.js
│ ├── dateHelper.js
│ └── dateHelper.spec.js
└── webpack-public-path.js
├── tools
├── build.js
├── chalkConfig.js
├── distServer.js
├── srcServer.js
├── startMessage.js
└── testSetup.js
├── webpack.config.dev.js
└── webpack.config.prod.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "latest",
4 | "react",
5 | "stage-1"
6 | ],
7 | "env": {
8 | "development": {
9 | "presets": [
10 | "react-hmre"
11 | ]
12 | },
13 | "production": {
14 | "plugins": [
15 | "transform-react-constant-elements",
16 | "transform-react-remove-prop-types"
17 | ]
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/node_modules/
2 | **/dist/
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "eslint:recommended",
4 | "plugin:import/errors",
5 | "plugin:import/warnings"
6 | ],
7 | "plugins": [
8 | "babel",
9 | "react"
10 | ],
11 | "parserOptions": {
12 | "ecmaVersion": 6,
13 | "sourceType": "module",
14 | "ecmaFeatures": {
15 | "jsx": true,
16 | "experimentalObjectRestSpread": true
17 | }
18 | },
19 | "env": {
20 | "es6": true,
21 | "browser": true,
22 | "node": true,
23 | "jquery": true,
24 | "mocha": true
25 | },
26 | "rules": {
27 | "quotes": 0,
28 | "indent": ["warn", 2, {"SwitchCase": 1}],
29 | "no-console": 1,
30 | "no-debugger": 1,
31 | "no-var": 1,
32 | "semi": [1, "always"],
33 | "no-trailing-spaces": 0,
34 | "eol-last": 0,
35 | "no-underscore-dangle": 0,
36 | "no-alert": 0,
37 | "no-lone-blocks": 0,
38 | "no-unused-vars": [1, {
39 | "vars": "all",
40 | "args": "after-used"
41 | }],
42 | "jsx-quotes": 1,
43 | "react/display-name": [ 1, {"ignoreTranspilerName": false }],
44 | "react/forbid-prop-types": [1, {"forbid": ["any"]}],
45 | "react/jsx-boolean-value": 0,
46 | "react/jsx-closing-bracket-location": 0,
47 | "react/jsx-curly-spacing": 1,
48 | "react/jsx-indent-props": 0,
49 | "react/jsx-key": 1,
50 | "react/jsx-max-props-per-line": 0,
51 | "react/jsx-no-bind": 0,
52 | "react/jsx-no-duplicate-props": 1,
53 | "react/jsx-no-literals": 0,
54 | "react/jsx-no-undef": 1,
55 | "react/jsx-pascal-case": 1,
56 | "react/jsx-sort-prop-types": 0,
57 | "react/jsx-sort-props": 0,
58 | "react/jsx-uses-react": 1,
59 | "react/jsx-uses-vars": 1,
60 | "react/no-danger": 1,
61 | "react/no-did-mount-set-state": 1,
62 | "react/no-did-update-set-state": 1,
63 | "react/no-direct-mutation-state": 1,
64 | "react/no-multi-comp": 1,
65 | "react/no-set-state": 0,
66 | "react/no-unknown-property": 1,
67 | "react/prefer-es6-class": 1,
68 | "react/prop-types": 1,
69 | "react/react-in-jsx-scope": 1,
70 | "react/require-extension": 1,
71 | "react/self-closing-comp": 1,
72 | "react/sort-comp": 1,
73 | "react/wrap-multilines": 1
74 | },
75 | "globals": {
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Coverage directory used by tools like istanbul
12 | coverage
13 |
14 | # Dependency directories
15 | node_modules
16 | jspm_packages
17 |
18 | # Editor files
19 | .vscode
20 | .idea
21 | *.iml
22 |
23 | # Mac files
24 | .DS_Store
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6"
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Ricardo Reis
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 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: npm run dist-server
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](http://travis-ci.org/rjmreis/react-redux-starter)
2 |
3 | # react-redux-starter
4 | A React/Redux starter project with login and basic CRUD functionality in a Material flavor
5 |
6 | ## The Goal
7 | The goal of this repo is to provide a general guidance in setting up a react/redux project with tools such as webpack, babel, eslint, trying as much as possible to follow best practises.
8 |
9 | ## Demo
10 |
11 | [reactredux-starter.herokuapp.com](https://reactredux-starter.herokuapp.com/)
12 |
13 | ```
14 | Login details
15 |
16 | user: admin
17 | password: password
18 | ```
19 |
20 | ## Quick Start
21 |
22 | Clone project and install dependencies:
23 | ```bash
24 | $ git clone https://github.com/rjmreis/react-redux-starter.git
25 | $ cd react-redux-starter
26 | $ npm install
27 | ```
28 |
29 | Start the app:
30 | ```bash
31 | $ npm start -s
32 | ```
33 |
34 | Build the app:
35 | ```bash
36 | $ npm run build
37 | ```
38 |
39 | ## NOTE
40 | This is a work in progress repo, tests are still missing...
41 |
42 | ## Credits
43 | The foundation of this project is highly based on the amazing **react-slingshot** repo by Cory House.
44 |
45 | [react-slingshot](https://github.com/coryhouse/react-slingshot)
46 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
react-redux-starter
--------------------------------------------------------------------------------
/dist/main.098aa9ee0d410b880d633a4523eae478.css:
--------------------------------------------------------------------------------
1 | .theme__ripple___3cRG3{position:absolute;top:50%;left:50%;z-index:100;pointer-events:none;background-color:currentColor;border-radius:50%;-webkit-transform-origin:50% 50%;transform-origin:50% 50%}.theme__rippleWrapper___2AWhQ{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:none}.theme__ripple___3cRG3{-webkit-transition-duration:.8s;transition-duration:.8s}.theme__ripple___3cRG3.theme__rippleRestarting___y45XA{opacity:.3;-webkit-transition-property:none;transition-property:none}.theme__ripple___3cRG3.theme__rippleActive___1QiQf{opacity:.3;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.theme__ripple___3cRG3:not(.theme__rippleActive___1QiQf):not(.theme__rippleRestarting___y45XA){opacity:0;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.theme__button___1iKuo{position:relative}.theme__button___1iKuo>input{position:absolute;top:0;left:0;z-index:0;width:.1px;height:.1px;padding:0;margin:0;overflow:hidden;opacity:0}.theme__flat___2ui7t,.theme__floating___1mZ5E,.theme__raised___ONZv6,.theme__toggle___1Zy-o{font-family:Roboto,Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:500;line-height:1;text-transform:uppercase;letter-spacing:0;position:relative;display:inline-block;height:3.6rem;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-line-pack:center;align-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:3.6rem;text-align:center;text-decoration:none;white-space:nowrap;cursor:pointer;border:0;outline:none;-webkit-transition:box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);transition:box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1)}.theme__flat___2ui7t::-moz-focus-inner,.theme__floating___1mZ5E::-moz-focus-inner,.theme__raised___ONZv6::-moz-focus-inner,.theme__toggle___1Zy-o::-moz-focus-inner{border:0}.theme__flat___2ui7t>span:not([data-react-toolbox=tooltip]),.theme__floating___1mZ5E>span:not([data-react-toolbox=tooltip]),.theme__raised___ONZv6>span:not([data-react-toolbox=tooltip]),.theme__toggle___1Zy-o>span:not([data-react-toolbox=tooltip]){display:inline-block;line-height:3.6rem;vertical-align:top}.theme__flat___2ui7t>svg,.theme__floating___1mZ5E>svg,.theme__raised___ONZv6>svg,.theme__toggle___1Zy-o>svg{display:inline-block;width:1em;height:3.6rem;font-size:120%;vertical-align:top;fill:currentColor}.theme__flat___2ui7t>*,.theme__floating___1mZ5E>*,.theme__raised___ONZv6>*,.theme__toggle___1Zy-o>*{pointer-events:none}.theme__flat___2ui7t>.theme__rippleWrapper___2zthi,.theme__floating___1mZ5E>.theme__rippleWrapper___2zthi,.theme__raised___ONZv6>.theme__rippleWrapper___2zthi,.theme__toggle___1Zy-o>.theme__rippleWrapper___2zthi{overflow:hidden}[disabled].theme__flat___2ui7t,[disabled].theme__floating___1mZ5E,[disabled].theme__raised___ONZv6,[disabled].theme__toggle___1Zy-o{color:rgba(0,0,0,.26);pointer-events:none;cursor:auto}.theme__flat___2ui7t,.theme__raised___ONZv6{min-width:9rem;padding:0 1.2rem;border-radius:.2rem}.theme__flat___2ui7t .theme__icon___1BTd6,.theme__raised___ONZv6 .theme__icon___1BTd6{margin-right:.6rem;font-size:120%;vertical-align:middle}.theme__flat___2ui7t>svg,.theme__raised___ONZv6>svg{margin-right:.5rem}[disabled].theme__floating___1mZ5E,[disabled].theme__raised___ONZv6{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);background-color:rgba(0,0,0,.12)}.theme__floating___1mZ5E:active,.theme__raised___ONZv6:active{box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.2)}.theme__floating___1mZ5E:focus:not(:active),.theme__raised___ONZv6:focus:not(:active){box-shadow:0 0 8px rgba(0,0,0,.18),0 8px 16px rgba(0,0,0,.36)}.theme__raised___ONZv6{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}.theme__flat___2ui7t{background:transparent}.theme__floating___1mZ5E{width:5.6rem;height:5.6rem;font-size:2.4rem;border-radius:50%;box-shadow:0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24)}.theme__floating___1mZ5E .theme__icon___1BTd6{line-height:5.6rem}.theme__floating___1mZ5E>.theme__rippleWrapper___2zthi{border-radius:50%}.theme__floating___1mZ5E.theme__mini___2oXdC{width:4rem;height:4rem;font-size:1.77778rem}.theme__floating___1mZ5E.theme__mini___2oXdC .theme__icon___1BTd6{line-height:4rem}.theme__toggle___1Zy-o{width:3.6rem;background:transparent;border-radius:50%}.theme__toggle___1Zy-o>.theme__icon___1BTd6,.theme__toggle___1Zy-o svg{font-size:2rem;line-height:3.6rem;vertical-align:top}.theme__toggle___1Zy-o>.theme__rippleWrapper___2zthi{border-radius:50%}.theme__neutral___uDC3j:not([disabled]).theme__floating___1mZ5E,.theme__neutral___uDC3j:not([disabled]).theme__raised___ONZv6{color:#212121;background-color:#fff}.theme__neutral___uDC3j:not([disabled]).theme__flat___2ui7t,.theme__neutral___uDC3j:not([disabled]).theme__toggle___1Zy-o{color:#212121}.theme__neutral___uDC3j:not([disabled]).theme__flat___2ui7t:focus:not(:active),.theme__neutral___uDC3j:not([disabled]).theme__flat___2ui7t:hover,.theme__neutral___uDC3j:not([disabled]).theme__toggle___1Zy-o:focus:not(:active){background:rgba(33,33,33,.2)}.theme__neutral___uDC3j:not([disabled]).theme__inverse___2Z8iZ.theme__floating___1mZ5E,.theme__neutral___uDC3j:not([disabled]).theme__inverse___2Z8iZ.theme__raised___ONZv6{color:#fff;background-color:#212121}.theme__neutral___uDC3j:not([disabled]).theme__inverse___2Z8iZ.theme__flat___2ui7t,.theme__neutral___uDC3j:not([disabled]).theme__inverse___2Z8iZ.theme__toggle___1Zy-o{color:#fff}.theme__neutral___uDC3j:not([disabled]).theme__inverse___2Z8iZ.theme__flat___2ui7t:focus:not(:active),.theme__neutral___uDC3j:not([disabled]).theme__inverse___2Z8iZ.theme__flat___2ui7t:hover,.theme__neutral___uDC3j:not([disabled]).theme__inverse___2Z8iZ.theme__toggle___1Zy-o:focus:not(:active){background:rgba(33,33,33,.2)}.theme__neutral___uDC3j.theme__inverse___2Z8iZ[disabled]{color:hsla(0,0%,100%,.54);background-color:hsla(0,0%,100%,.08)}.theme__primary___2NhN1:not([disabled]).theme__floating___1mZ5E,.theme__primary___2NhN1:not([disabled]).theme__raised___ONZv6{color:#fff;background:#ff5722}.theme__primary___2NhN1:not([disabled]).theme__flat___2ui7t,.theme__primary___2NhN1:not([disabled]).theme__toggle___1Zy-o{color:#ff5722}.theme__primary___2NhN1:not([disabled]).theme__flat___2ui7t:focus:not(:active),.theme__primary___2NhN1:not([disabled]).theme__flat___2ui7t:hover,.theme__primary___2NhN1:not([disabled]).theme__toggle___1Zy-o:focus:not(:active){background:rgba(255,87,34,.2)}.theme__accent___3MS_k:not([disabled]).theme__floating___1mZ5E,.theme__accent___3MS_k:not([disabled]).theme__raised___ONZv6{color:#fff;background:#546e7a}.theme__accent___3MS_k:not([disabled]).theme__flat___2ui7t,.theme__accent___3MS_k:not([disabled]).theme__toggle___1Zy-o{color:#546e7a}.theme__accent___3MS_k:not([disabled]).theme__flat___2ui7t:focus:not(:active),.theme__accent___3MS_k:not([disabled]).theme__flat___2ui7t:hover,.theme__accent___3MS_k:not([disabled]).theme__toggle___1Zy-o:focus:not(:active){background:rgba(84,110,122,.2)}.theme__avatar___3GCeP{position:relative;display:inline-block;width:4rem;height:4rem;overflow:hidden;font-size:2.4rem;color:#fff;text-align:center;vertical-align:middle;background-color:#9e9e9e;border-radius:50%}.theme__avatar___3GCeP>svg{width:1em;height:4rem;fill:currentColor}.theme__avatar___3GCeP>img{max-width:100%;height:auto}.theme__image___1H3TP{position:absolute;display:block;width:100%;height:100%;background-color:transparent;background-position:50%;background-size:cover;border-radius:50%}.theme__letter___34Q66{display:block;width:100%;line-height:4rem}.theme__card___2nWQb{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;overflow:hidden;font-size:1.4rem;background:#fff;border-radius:.2rem}.theme__card___2nWQb.theme__raised___2PPOH{box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.2)}.theme__card___2nWQb [data-react-toolbox=avatar]{display:block}.theme__cardMedia___3WTvG{position:relative;background-repeat:no-repeat;background-position:50%;background-size:cover}.theme__cardMedia___3WTvG.theme__square___1a9i8,.theme__cardMedia___3WTvG.theme__wide___3c58S{width:100%}.theme__cardMedia___3WTvG.theme__square___1a9i8 .theme__content___Fopuf,.theme__cardMedia___3WTvG.theme__wide___3c58S .theme__content___Fopuf{position:absolute;height:100%}.theme__cardMedia___3WTvG.theme__square___1a9i8 .theme__content___Fopuf>iframe,.theme__cardMedia___3WTvG.theme__square___1a9i8 .theme__content___Fopuf>img,.theme__cardMedia___3WTvG.theme__square___1a9i8 .theme__content___Fopuf>video,.theme__cardMedia___3WTvG.theme__wide___3c58S .theme__content___Fopuf>iframe,.theme__cardMedia___3WTvG.theme__wide___3c58S .theme__content___Fopuf>img,.theme__cardMedia___3WTvG.theme__wide___3c58S .theme__content___Fopuf>video{max-width:100%}.theme__cardMedia___3WTvG:after{display:block;height:0;content:""}.theme__cardMedia___3WTvG.theme__wide___3c58S:after{padding-top:56.25%}.theme__cardMedia___3WTvG.theme__square___1a9i8:after{padding-top:100%}.theme__cardMedia___3WTvG .theme__content___Fopuf{position:relative;top:0;left:0;display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;overflow:hidden}.theme__cardMedia___3WTvG .theme__contentOverlay___1KYpi .theme__cardActions___1aHjq,.theme__cardMedia___3WTvG .theme__contentOverlay___1KYpi .theme__cardText___3ElKZ,.theme__cardMedia___3WTvG .theme__contentOverlay___1KYpi .theme__cardTitle___3Tyrr{background-color:rgba(0,0,0,.35)}.theme__cardTitle___3Tyrr{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.theme__cardTitle___3Tyrr [data-react-toolbox=avatar]{margin-right:1.3rem}.theme__cardTitle___3Tyrr .theme__subtitle___grD6g{color:#757575}.theme__cardTitle___3Tyrr.theme__large___3eNqf{padding:2rem 1.6rem 1.4rem}.theme__cardTitle___3Tyrr.theme__large___3eNqf .theme__title___35Wsy{font-family:Roboto,Helvetica,Arial,sans-serif;font-size:2.4rem;font-weight:400;line-height:3.2rem;-moz-osx-font-smoothing:grayscale;line-height:1.25}.theme__cardTitle___3Tyrr.theme__small___3Q56x{padding:1.6rem}.theme__cardTitle___3Tyrr.theme__small___3Q56x .theme__title___35Wsy{font-family:Roboto,Helvetica,Arial,sans-serif;font-size:1.4rem;line-height:2.4rem;letter-spacing:0;font-weight:500;line-height:1.4}.theme__cardTitle___3Tyrr.theme__small___3Q56x .theme__subtitle___grD6g{font-weight:500;line-height:1.4}.theme__cardMedia___3WTvG .theme__cardTitle___3Tyrr .theme__subtitle___grD6g,.theme__cardMedia___3WTvG .theme__cardTitle___3Tyrr .theme__title___35Wsy{color:#fff}.theme__cardText___3ElKZ,.theme__cardTitle___3Tyrr{padding:1.4rem 1.6rem}.theme__cardText___3ElKZ:last-child,.theme__cardTitle___3Tyrr:last-child{padding-bottom:2rem}.theme__cardText___3ElKZ+.theme__cardText___3ElKZ,.theme__cardTitle___3Tyrr+.theme__cardText___3ElKZ{padding-top:0}.theme__cardActions___1aHjq{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:.8rem}.theme__cardActions___1aHjq [data-react-toolbox=button]{min-width:0;padding:0 .8rem;margin:0 .4rem}.theme__cardActions___1aHjq [data-react-toolbox=button]:first-child{margin-left:0}.theme__cardActions___1aHjq [data-react-toolbox=button]:last-child{margin-right:0}.theme__layout___2DIC_{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;height:100%;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;overflow-y:hidden}.theme__layout___2DIC_ .theme__navDrawer___1rdra{width:0;min-width:0;height:100%;overflow-x:hidden;overflow-y:hidden;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:width,min-width;transition-property:width,min-width}.theme__layout___2DIC_ .theme__navDrawer___1rdra .theme__scrim___2QDhH{position:absolute;top:0;bottom:0;left:0;z-index:200;width:0;height:100%;background-color:transparent;-webkit-transition:background-color .35s cubic-bezier(.4,0,.2,1),width 10ms linear .35s;transition:background-color .35s cubic-bezier(.4,0,.2,1),width 10ms linear .35s}.theme__layout___2DIC_ .theme__navDrawer___1rdra .theme__drawerContent___unz6w{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);position:absolute;z-index:300;display:-webkit-box;display:-ms-flexbox;display:flex;width:28rem;max-width:calc(100% - 5.6rem);height:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;overflow-x:hidden;overflow-y:hidden;color:#424242;pointer-events:none;background-color:#fafafa;border-right:1px solid #e0e0e0;-webkit-transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1);-webkit-transform:translateX(-100%);transform:translateX(-100%)}.theme__layout___2DIC_ .theme__navDrawer___1rdra .theme__drawerContent___unz6w.theme__scrollY___1AG90{overflow-y:auto}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__pinned___oVgJU{-webkit-transition-delay:.07s;transition-delay:.07s;width:28rem;max-width:calc(100% - 5.6rem)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__pinned___oVgJU .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__active___1P57z:not(.theme__pinned___oVgJU){-webkit-transition-delay:.07s;transition-delay:.07s}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__active___1P57z:not(.theme__pinned___oVgJU) .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__active___1P57z:not(.theme__pinned___oVgJU) .theme__scrim___2QDhH{width:100%;background-color:rgba(0,0,0,.6);-webkit-transition:background-color .35s cubic-bezier(.4,0,.2,1);transition:background-color .35s cubic-bezier(.4,0,.2,1)}@media screen and (min-width:600px){.theme__layout___2DIC_ .theme__navDrawer___1rdra .theme__drawerContent___unz6w,.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__pinned___oVgJU{width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__wide___3X5rC .theme__drawerContent___unz6w,.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__wide___3X5rC.theme__pinned___oVgJU{width:40rem;max-width:40rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smPermanent___1QkG3{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smPermanent___1QkG3 .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smPermanent___1QkG3.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smPermanent___1QkG3.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smTabletPermanent___1Ntvp{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smTabletPermanent___1Ntvp .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smTabletPermanent___1Ntvp.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__smTabletPermanent___1Ntvp.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}@media screen and (min-width:960px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__mdPermanent___3v_k7{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__mdPermanent___3v_k7 .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__mdPermanent___3v_k7.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__mdPermanent___3v_k7.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}@media screen and (min-width:1280px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgPermanent___3rQEf{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgPermanent___3rQEf .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgPermanent___3rQEf.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgPermanent___3rQEf.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}@media screen and (min-width:1024px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgTabletPermanent___NlW9h{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgTabletPermanent___NlW9h .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgTabletPermanent___NlW9h.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__lgTabletPermanent___NlW9h.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}@media screen and (min-width:1440px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xlPermanent___3O4lD{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xlPermanent___3O4lD .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xlPermanent___3O4lD.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xlPermanent___3O4lD.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}@media screen and (min-width:1600px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxlPermanent___yB-xN{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxlPermanent___yB-xN .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxlPermanent___yB-xN.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxlPermanent___yB-xN.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}@media screen and (min-width:1920px){.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxxlPermanent___2PMir{-webkit-transition-delay:.07s;transition-delay:.07s;width:32rem;max-width:32rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxxlPermanent___2PMir .theme__drawerContent___unz6w{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxxlPermanent___2PMir.theme__wide___3X5rC{width:40rem;max-width:40rem}.theme__layout___2DIC_ .theme__navDrawer___1rdra.theme__xxxlPermanent___2PMir.theme__active___1P57z>.theme__scrim___2QDhH{width:0;background-color:transparent}}.theme__layout___2DIC_ .theme__layout___2DIC_ .theme__scrim___2QDhH{z-index:299}.theme__layout___2DIC_ .theme__layout___2DIC_ .theme__layout___2DIC_ .theme__scrim___2QDhH{z-index:298}.theme__layout___2DIC_ .theme__panel___o2a2H{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;overflow-y:hidden}.theme__layout___2DIC_ .theme__panel___o2a2H.theme__scrollY___1AG90{overflow-y:auto}.theme__layout___2DIC_ .theme__sidebar___t1TKH{position:absolute;top:0;right:0;bottom:0;z-index:299;width:0;height:100%;overflow-x:hidden;overflow-y:hidden;color:#424242;background-color:#fafafa;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:width;transition-property:width}.theme__layout___2DIC_ .theme__sidebar___t1TKH .theme__sidebarContent___1MT-m{display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;overflow-y:hidden}.theme__layout___2DIC_ .theme__sidebar___t1TKH .theme__sidebarContent___1MT-m.theme__scrollY___1AG90{overflow-y:auto}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA .theme__sidebarContent___1MT-m{min-width:5.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA.theme__pinned___oVgJU{width:5.6rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA .theme__sidebarContent___1MT-m{min-width:6.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA.theme__pinned___oVgJU{width:6.4rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA .theme__sidebarContent___1MT-m{min-width:6.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA.theme__pinned___oVgJU{width:6.4rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA .theme__sidebarContent___1MT-m{min-width:6.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-1___3dCDA.theme__pinned___oVgJU{width:6.4rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL .theme__sidebarContent___1MT-m{min-width:11.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL.theme__pinned___oVgJU{width:11.2rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL .theme__sidebarContent___1MT-m{min-width:12.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL.theme__pinned___oVgJU{width:12.8rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL .theme__sidebarContent___1MT-m{min-width:12.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL.theme__pinned___oVgJU{width:12.8rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL .theme__sidebarContent___1MT-m{min-width:12.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-2___2OjoL.theme__pinned___oVgJU{width:12.8rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL .theme__sidebarContent___1MT-m{min-width:16.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL.theme__pinned___oVgJU{width:16.8rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL .theme__sidebarContent___1MT-m{min-width:19.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL.theme__pinned___oVgJU{width:19.2rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL .theme__sidebarContent___1MT-m{min-width:19.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL.theme__pinned___oVgJU{width:19.2rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL .theme__sidebarContent___1MT-m{min-width:19.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-3___26_RL.theme__pinned___oVgJU{width:19.2rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf .theme__sidebarContent___1MT-m{min-width:22.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf.theme__pinned___oVgJU{width:22.4rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf .theme__sidebarContent___1MT-m{min-width:25.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf.theme__pinned___oVgJU{width:25.6rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf .theme__sidebarContent___1MT-m{min-width:25.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf.theme__pinned___oVgJU{width:25.6rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf .theme__sidebarContent___1MT-m{min-width:25.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-4___kGxrf.theme__pinned___oVgJU{width:25.6rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ .theme__sidebarContent___1MT-m{min-width:28rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ.theme__pinned___oVgJU{width:28rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ .theme__sidebarContent___1MT-m{min-width:32rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ.theme__pinned___oVgJU{width:32rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ .theme__sidebarContent___1MT-m{min-width:32rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ.theme__pinned___oVgJU{width:32rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ .theme__sidebarContent___1MT-m{min-width:32rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-5___3HyHQ.theme__pinned___oVgJU{width:32rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh .theme__sidebarContent___1MT-m{min-width:33.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh.theme__pinned___oVgJU{width:33.6rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh .theme__sidebarContent___1MT-m{min-width:38.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh.theme__pinned___oVgJU{width:38.4rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh .theme__sidebarContent___1MT-m{min-width:38.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh.theme__pinned___oVgJU{width:38.4rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh .theme__sidebarContent___1MT-m{min-width:38.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-6___VWIJh.theme__pinned___oVgJU{width:38.4rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM .theme__sidebarContent___1MT-m{min-width:39.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM.theme__pinned___oVgJU{width:39.2rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM .theme__sidebarContent___1MT-m{min-width:44.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM.theme__pinned___oVgJU{width:44.8rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM .theme__sidebarContent___1MT-m{min-width:44.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM.theme__pinned___oVgJU{width:44.8rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM .theme__sidebarContent___1MT-m{min-width:44.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-7___RMBsM.theme__pinned___oVgJU{width:44.8rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4 .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4 .theme__sidebarContent___1MT-m{min-width:44.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4.theme__pinned___oVgJU{width:44.8rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4 .theme__sidebarContent___1MT-m{min-width:51.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4.theme__pinned___oVgJU{width:51.2rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4 .theme__sidebarContent___1MT-m{min-width:51.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4.theme__pinned___oVgJU{width:51.2rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4 .theme__sidebarContent___1MT-m{min-width:51.2rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-8___2p9V4.theme__pinned___oVgJU{width:51.2rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V.theme__pinned___oVgJU{width:100%}@media screen and (min-width:600px) and (orientation:landscape){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V .theme__sidebarContent___1MT-m{min-width:50.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V.theme__pinned___oVgJU{width:50.4rem}}@media screen and (min-width:600px) and (orientation:portrait){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V .theme__sidebarContent___1MT-m{min-width:57.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V.theme__pinned___oVgJU{width:57.6rem}}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V .theme__sidebarContent___1MT-m{min-width:57.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V.theme__pinned___oVgJU{width:57.6rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V .theme__sidebarContent___1MT-m{min-width:57.6rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-9___3JV_V.theme__pinned___oVgJU{width:57.6rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC.theme__pinned___oVgJU{width:100%}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC .theme__sidebarContent___1MT-m{min-width:64rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC.theme__pinned___oVgJU{width:64rem}}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC .theme__sidebarContent___1MT-m{min-width:64rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-10___IFhjC.theme__pinned___oVgJU{width:64rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-11___2gqr4 .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-11___2gqr4.theme__pinned___oVgJU{width:100%}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-11___2gqr4{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-11___2gqr4 .theme__sidebarContent___1MT-m{min-width:70.4rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-11___2gqr4.theme__pinned___oVgJU{width:70.4rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-12___3Fqrn .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-12___3Fqrn.theme__pinned___oVgJU{width:100%}@media screen and (min-width:840px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-12___3Fqrn{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-12___3Fqrn .theme__sidebarContent___1MT-m{min-width:76.8rem}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-12___3Fqrn.theme__pinned___oVgJU{width:76.8rem}}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-100___cH-H3{position:absolute}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-100___cH-H3 .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-100___cH-H3.theme__pinned___oVgJU{width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-25___2wWPw{position:absolute}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-25___2wWPw .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-25___2wWPw.theme__pinned___oVgJU{width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-33___1MMwi{position:absolute}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-33___1MMwi .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-33___1MMwi.theme__pinned___oVgJU{width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-50___gURY4{position:absolute}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-50___gURY4 .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-50___gURY4.theme__pinned___oVgJU{width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-66___1TeEX{position:absolute}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-66___1TeEX .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-66___1TeEX.theme__pinned___oVgJU{width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-75___1smcb{position:absolute}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-75___1smcb .theme__sidebarContent___1MT-m{min-width:100%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-75___1smcb.theme__pinned___oVgJU{width:100%}@media screen and (min-width:720px){.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-25___2wWPw{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-25___2wWPw .theme__sidebarContent___1MT-m{min-width:25%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-25___2wWPw.theme__pinned___oVgJU{width:25%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-33___1MMwi{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-33___1MMwi .theme__sidebarContent___1MT-m{min-width:33%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-33___1MMwi.theme__pinned___oVgJU{width:33%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-50___gURY4{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-50___gURY4 .theme__sidebarContent___1MT-m{min-width:50%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-50___gURY4.theme__pinned___oVgJU{width:50%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-66___1TeEX{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-66___1TeEX .theme__sidebarContent___1MT-m{min-width:66%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-66___1TeEX.theme__pinned___oVgJU{width:66%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-75___1smcb{position:relative}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-75___1smcb .theme__sidebarContent___1MT-m{min-width:75%}.theme__layout___2DIC_ .theme__sidebar___t1TKH.theme__width-75___1smcb.theme__pinned___oVgJU{width:75%}}.theme__field___14tiU{position:relative;display:block;height:1.8rem;margin-bottom:1.5rem;white-space:nowrap;vertical-align:middle}.theme__field___14tiU .theme__ripple___1-Txn{background-color:#ff5722;opacity:.3;-webkit-transition-duration:.65s;transition-duration:.65s}.theme__text___1nV6f{display:inline-block;padding-left:1rem;font-size:1.4rem;line-height:1.8rem;color:#000;white-space:nowrap;vertical-align:top}.theme__input___3zqc3{position:absolute;width:0;height:0;overflow:hidden;opacity:0}.theme__input___3zqc3:focus~.theme__check___2B20W:before{position:absolute;top:50%;left:50%;width:4.14rem;height:4.14rem;margin-top:-2.07rem;margin-left:-2.07rem;pointer-events:none;content:"";background-color:rgba(0,0,0,.1);border-radius:50%}.theme__input___3zqc3:focus~.theme__check___2B20W.theme__checked___2NQ9n:before{background-color:rgba(255,87,34,.26)}.theme__check___2B20W{position:relative;display:inline-block;width:1.8rem;height:1.8rem;vertical-align:top;cursor:pointer;border:2px solid #000;border-radius:2px;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color;transition-property:background-color}.theme__check___2B20W.theme__checked___2NQ9n{background-color:#ff5722;border-color:#ff5722}.theme__check___2B20W.theme__checked___2NQ9n:after{position:absolute;top:-.1rem;left:.4rem;width:.7rem;height:1.2rem;content:"";border-color:#fff;border-style:solid;border-top:0;border-right-width:2px;border-bottom-width:2px;border-left:0;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-animation:theme__checkmark-expand___1k7UD .14s ease-out forwards;animation:theme__checkmark-expand___1k7UD .14s ease-out forwards}.theme__disabled___3tar9>.theme__text___1nV6f{color:rgba(0,0,0,.26)}.theme__disabled___3tar9>.theme__check___2B20W{cursor:auto;border-color:rgba(0,0,0,.26)}.theme__disabled___3tar9>.theme__check___2B20W.theme__checked___2NQ9n{cursor:auto;background-color:rgba(0,0,0,.26);border-color:transparent}@-webkit-keyframes theme__checkmark-expand___1k7UD{0%{top:.9rem;left:.6rem;width:0;height:0}to{top:-.1rem;left:.4rem;width:.7rem;height:1.2rem}}@keyframes theme__checkmark-expand___1k7UD{0%{top:.9rem;left:.6rem;width:0;height:0}to{top:-.1rem;left:.4rem;width:.7rem;height:1.2rem}}.theme__list___3Ahlg{position:relative;display:inline-block;width:100%;padding:.8rem 0;text-align:left;white-space:nowrap;list-style:none}.theme__subheader___2hnyo{padding-left:1.6rem;margin:-.8rem 0 0;font-size:1.4rem;font-weight:500;line-height:4.8rem;color:#757575}.theme__divider___1WuUG{height:.1rem;margin:-.1rem 0 0;background-color:#eee;border:0}.theme__divider___1WuUG.theme__inset___2XT51{margin-right:1.6rem;margin-left:7.2rem}.theme__list___3Ahlg+.theme__divider___1WuUG{margin-top:-.8rem}.theme__listItem___25deI~.theme__divider___1WuUG{margin-top:.8rem;margin-bottom:.8rem}.theme__listItem___25deI{position:relative}.theme__listItem___25deI>[data-react-toolbox=ripple]{overflow:hidden}.theme__listItem___25deI .theme__ripple___3BKMI{color:#757575}.theme__item___QgVrb{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;min-height:4.8rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0 1.6rem;color:#212121}.theme__item___QgVrb.theme__selectable___pSlvM:not(.theme__disabled___281Pb):hover{cursor:pointer;background-color:#eee}.theme__item___QgVrb.theme__disabled___281Pb{pointer-events:none}.theme__item___QgVrb.theme__disabled___281Pb:not(.theme__checkboxItem___3FtoG),.theme__item___QgVrb.theme__disabled___281Pb>.theme__checkbox___2pdgS>[data-react-toolbox=label]{opacity:.5}.theme__left___1KL1E [data-react-toolbox=font-icon]{width:1.8rem}.theme__left___1KL1E :last-child>[data-react-toolbox=font-icon]{margin-right:2.2rem}.theme__right___3itF1>:last-child{margin-right:0}.theme__right___3itF1>:first-child{margin-left:1.6rem}.theme__left___1KL1E,.theme__right___3itF1{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-align:center;-ms-flex-align:center;align-items:center;vertical-align:middle}.theme__itemAction___1SOd4{display:-webkit-box;display:-ms-flexbox;display:flex;margin:.8rem 1.6rem .8rem 0}.theme__itemAction___1SOd4>*{padding:0}.theme__itemAction___1SOd4>[data-react-toolbox=font-icon]{font-size:2.4rem;color:#757575}.theme__itemContentRoot___3ofPf{display:block;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.theme__itemContentRoot___3ofPf.theme__large___2vIAA{display:-webkit-box;display:-ms-flexbox;display:flex;height:7.2rem;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.theme__checkbox___2pdgS{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;height:100%;min-height:4.8rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:0;cursor:pointer}.theme__checkbox___2pdgS>[data-react-toolbox=check]{margin-right:3.8rem}.theme__checkbox___2pdgS>[data-react-toolbox=label]{padding-left:0}.theme__itemText___D709k{display:block}.theme__itemText___D709k:not(.theme__primary___22ZvQ){padding-top:.3rem;font-size:1.4rem;color:#757575;white-space:normal}.theme__itemText___D709k.theme__primary___22ZvQ{font-size:1.6rem;color:#212121}.theme__iconMenu___1K6XK{position:relative;display:inline-block;text-align:center}.theme__iconMenu___1K6XK .theme__icon___Q98zC{cursor:pointer}.theme__menu___2bOZL{position:relative;display:inline-block}.theme__menu___2bOZL.theme__topLeft___49yru{position:absolute;top:0;left:0}.theme__menu___2bOZL.theme__topLeft___49yru>.theme__outline___3LItQ{-webkit-transform-origin:0 0;transform-origin:0 0}.theme__menu___2bOZL.theme__topRight___tGYgQ{position:absolute;top:0;right:0}.theme__menu___2bOZL.theme__topRight___tGYgQ>.theme__outline___3LItQ{-webkit-transform-origin:100% 0;transform-origin:100% 0}.theme__menu___2bOZL.theme__bottomLeft___1TaYY{position:absolute;bottom:0;left:0}.theme__menu___2bOZL.theme__bottomLeft___1TaYY>.theme__outline___3LItQ{-webkit-transform-origin:0 100%;transform-origin:0 100%}.theme__menu___2bOZL.theme__bottomRight___1_dUK{position:absolute;right:0;bottom:0}.theme__menu___2bOZL.theme__bottomRight___1_dUK>.theme__outline___3LItQ{-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.theme__menu___2bOZL:not(.theme__static___25uHO){z-index:200;pointer-events:none}.theme__menu___2bOZL:not(.theme__static___25uHO)>.theme__outline___3LItQ{opacity:0;-webkit-transition:opacity .2s cubic-bezier(.4,0,.2,1),-webkit-transform .3s cubic-bezier(.4,0,.2,1);transition:opacity .2s cubic-bezier(.4,0,.2,1),-webkit-transform .3s cubic-bezier(.4,0,.2,1);transition:transform .3s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1);transition:transform .3s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1),-webkit-transform .3s cubic-bezier(.4,0,.2,1);-webkit-transform:scale(0);transform:scale(0);will-change:transform}.theme__menu___2bOZL:not(.theme__static___25uHO)>.theme__menuInner___1k3_X{position:absolute;top:0;left:0;opacity:0}.theme__menu___2bOZL:not(.theme__static___25uHO).theme__rippled___2pZcI:not(.theme__active___3owm6)>.theme__menuInner___1k3_X,.theme__menu___2bOZL:not(.theme__static___25uHO).theme__rippled___2pZcI:not(.theme__active___3owm6)>.theme__outline___3LItQ{-webkit-transition-delay:.3s;transition-delay:.3s}.theme__menu___2bOZL:not(.theme__static___25uHO).theme__active___3owm6{pointer-events:all}.theme__menu___2bOZL:not(.theme__static___25uHO).theme__active___3owm6>.theme__outline___3LItQ{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.theme__menu___2bOZL:not(.theme__static___25uHO).theme__active___3owm6>.theme__menuInner___1k3_X{opacity:1;-webkit-transition:opacity .2s cubic-bezier(.4,0,.2,1),clip .3s cubic-bezier(.4,0,.2,1);transition:opacity .2s cubic-bezier(.4,0,.2,1),clip .3s cubic-bezier(.4,0,.2,1)}.theme__outline___3LItQ{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);position:absolute;top:0;left:0;display:block;background-color:#fff;border-radius:.2rem}.theme__menuInner___1k3_X{position:relative;display:block;padding:.8rem 0;text-align:left;white-space:nowrap;list-style:none}.theme__menuItem___3SQPN{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;height:4.8rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0 1.6rem;overflow:hidden;font-size:1.6rem;color:#212121}.theme__menuItem___3SQPN:not(.theme__disabled___tYdgT):hover{cursor:pointer;background-color:#eee}.theme__menuItem___3SQPN.theme__disabled___tYdgT{pointer-events:none;opacity:.5}.theme__menuItem___3SQPN.theme__selected___3zlED{font-weight:500;background-color:transparent}.theme__menuItem___3SQPN .theme__ripple___2PP2K{color:#757575}.theme__menuItem___3SQPN .theme__icon___Q98zC{width:3.84rem;font-size:2.4rem!important}.theme__caption___1TBtj{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:1.6rem}.theme__shortcut___1VR3f{margin-left:1.6rem}.theme__menuDivider___2aLZ3{display:block;width:100%;height:1px;margin:1.2rem 0;background-color:#eee}.theme__radio___-qz0o,.theme__radioChecked___37vlk{position:relative;display:inline-block;width:2rem;height:2rem;vertical-align:top;cursor:pointer;border:.2rem solid #000;border-radius:50%}.theme__radio___-qz0o:before,.theme__radioChecked___37vlk:before{position:absolute;top:0;left:0;width:100%;height:100%;content:"";background-color:#ff5722;border-radius:50%;-webkit-transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1);-webkit-transform:scale(0);transform:scale(0)}.theme__radio___-qz0o .theme__ripple___3p5ha,.theme__radioChecked___37vlk .theme__ripple___3p5ha{background-color:#ff5722;opacity:.3;-webkit-transition-duration:.65s;transition-duration:.65s}.theme__radioChecked___37vlk{border:.2rem solid #ff5722}.theme__radioChecked___37vlk:before{-webkit-transform:scale(.65);transform:scale(.65)}.theme__disabled___15z04,.theme__field___30YjY{position:relative;display:block;height:2rem;margin-bottom:1.5rem;white-space:nowrap;vertical-align:middle}.theme__text___1gqkQ{display:inline-block;padding-left:1rem;font-size:1.4rem;line-height:2rem;color:#000;white-space:nowrap;vertical-align:top}.theme__input___Z_QPq{position:absolute;width:0;height:0;padding:0;margin:0;border:0;opacity:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.theme__input___Z_QPq:focus~.theme__radio___-qz0o,.theme__input___Z_QPq:focus~.theme__radioChecked___37vlk{box-shadow:0 0 0 1rem rgba(0,0,0,.1)}.theme__input___Z_QPq:focus~.theme__radioChecked___37vlk{box-shadow:0 0 0 1rem rgba(255,87,34,.26)}.theme__disabled___15z04 .theme__text___1gqkQ{color:rgba(0,0,0,.26)}.theme__disabled___15z04 .theme__radio___-qz0o,.theme__disabled___15z04 .theme__radioChecked___37vlk{cursor:auto;border-color:rgba(0,0,0,.26)}.theme__disabled___15z04 .theme__radioChecked___37vlk:before{background-color:rgba(0,0,0,.26)}.theme__tabs___2lGJI{-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column}.theme__navigation___2N9WO,.theme__tabs___2lGJI{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-direction:normal}.theme__navigation___2N9WO{position:relative;-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;box-shadow:inset 0 -1px #eee}.theme__navigationContainer___rLpe4{display:-webkit-box;display:-ms-flexbox;display:flex}.theme__navigationContainer___rLpe4 .theme__navigation___2N9WO{-webkit-box-flex:1;-ms-flex:1;flex:1}.theme__arrow___1Bm49{padding:0 1.2rem;color:#000}.theme__arrowContainer___1HYX7{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;box-shadow:inset 0 -1px #eee}.theme__label___3A-Tl{padding:1.7rem 1.2rem;font-size:1.4rem;font-weight:500;line-height:1;color:rgba(0,0,0,.7);text-align:center;text-transform:uppercase;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:box-shadow,color;transition-property:box-shadow,color}.theme__label___3A-Tl.theme__active___2SLiK{color:#000}.theme__label___3A-Tl.theme__disabled___1mq-I{opacity:.2}.theme__label___3A-Tl:not(.theme__disabled___1mq-I){cursor:pointer}.theme__label___3A-Tl.theme__hidden___1XZZy{display:none}.theme__label___3A-Tl.theme__withIcon___pi4k-{padding-top:1.3rem;padding-bottom:1.3rem}.theme__label___3A-Tl.theme__withText___2-Su2 .theme__icon___wI5gE{margin-bottom:.8rem}.theme__icon___wI5gE{display:block;height:2.4rem;margin:0 auto;line-height:2.4rem}.theme__pointer___pWCM7{position:absolute;width:0;height:.2rem;margin-top:-.2rem;background-color:#ff5722;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:left,width;transition-property:left,width}.theme__pointer___pWCM7.theme__disableAnimation___mBuDO{-webkit-transition:none;transition:none}.theme__tab___2YMGw{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:1.7rem 1.2rem}.theme__tab___2YMGw:not(.theme__active___2SLiK){display:none}.theme__tab___2YMGw.theme__active___2SLiK{display:-webkit-box;display:-ms-flexbox;display:flex}.theme__fixed___3dgXb .theme__label___3A-Tl{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.theme__inverse___x1bCH .theme__arrowContainer___1HYX7,.theme__inverse___x1bCH .theme__navigation___2N9WO{background-color:#ff5722}.theme__inverse___x1bCH .theme__label___3A-Tl{color:hsla(0,0%,100%,.7)}.theme__inverse___x1bCH .theme__arrow___1Bm49,.theme__inverse___x1bCH .theme__label___3A-Tl.theme__active___2SLiK{color:#fff}.theme__inverse___x1bCH .theme__pointer___pWCM7{background-color:#546e7a}.theme__appBar___wbg0y{display:-webkit-box;display:-ms-flexbox;display:flex;height:6.4rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0 2.4rem;color:#fff;background:#f4511e;-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}@media screen and (max-width:480px) and (orientation:portrait){.theme__appBar___wbg0y{height:5.6rem}}@media screen and (max-width:600px) and (orientation:landscape){.theme__appBar___wbg0y{height:4.8rem}}.theme__appBar___wbg0y:not(.theme__flat___1lt-1){z-index:100;box-shadow:0 2px 5px rgba(0,0,0,.26)}.theme__appBar___wbg0y.theme__fixed___3rLFE{position:fixed;top:0;right:0;left:0;z-index:300}.theme__appBar___wbg0y a{color:#fff}.theme__appBar___wbg0y .theme__title___mFCzt{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:1.8rem;font-weight:700}.theme__appBar___wbg0y .theme__title___mFCzt>small{font-size:1.8rem;font-weight:400}.theme__appBar___wbg0y .theme__leftIcon___3lBT0{margin-left:-1.2rem}.theme__appBar___wbg0y .theme__rightIcon___3I1u6{margin-right:-1.2rem;margin-left:auto}.theme__appBar___wbg0y.theme__scrollHide___375zR{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.theme__chip___3Gjj_{position:relative;display:inline-block;max-width:100%;padding:0 1.2rem;margin-right:.25rem;overflow:hidden;font-size:1.4rem;line-height:3.2rem;color:#757575;text-overflow:ellipsis;white-space:nowrap;background-color:#eee;border-radius:3.2rem}.theme__avatar___1IEZZ{padding-left:0}.theme__avatar___1IEZZ>[data-react-toolbox=avatar]{width:3.2rem;height:3.2rem;margin-right:.8rem;vertical-align:middle}.theme__avatar___1IEZZ>[data-react-toolbox=avatar]>span{font-size:2rem;line-height:3.2rem}.theme__deletable___3k2SH{padding-right:3.2rem}.theme__delete___2LAZw{position:absolute;right:0;display:inline-block;width:2.4rem;height:2.4rem;padding:.4rem;margin:.4rem;vertical-align:middle;cursor:pointer}.theme__delete___2LAZw:hover .theme__deleteIcon___3XWBI{background:#9e9e9e}.theme__deleteIcon___3XWBI{vertical-align:top;background:#bdbdbd;border-radius:2.4rem}.theme__deleteIcon___3XWBI .theme__deleteX___2hNz-{fill:transparent;stroke-width:.4rem;stroke:#fff}.theme__input___qUQeP{position:relative;padding:2rem 0}.theme__input___qUQeP.theme__withIcon___f6YT1{margin-left:4.8rem}.theme__icon___1_C6Z{position:absolute;top:1.6rem;left:-4.8rem;display:block;width:4.8rem;height:4.8rem;font-size:2.4rem!important;line-height:4.8rem!important;color:rgba(0,0,0,.26);text-align:center;-webkit-transition:color .35s cubic-bezier(.4,0,.2,1);transition:color .35s cubic-bezier(.4,0,.2,1)}.theme__inputElement___27dyY{display:block;width:100%;padding:.8rem 0;font-size:1.6rem;color:#212121;background-color:transparent;border:0;border-bottom:1px solid rgba(0,0,0,.12);outline:none}.theme__inputElement___27dyY:focus:not([disabled]):not([readonly])~.theme__bar___2GHeb:after,.theme__inputElement___27dyY:focus:not([disabled]):not([readonly])~.theme__bar___2GHeb:before{width:50%}.theme__inputElement___27dyY:focus:not([disabled]):not([readonly])~.theme__label___tqKDt:not(.theme__fixed___2pXa4){color:#ff5722}.theme__inputElement___27dyY:focus:not([disabled]):not([readonly])~.theme__label___tqKDt>.theme__required___2OgFq{color:#de3226}.theme__inputElement___27dyY:focus:not([disabled]):not([readonly])~.theme__hint___2D9g-{display:block;opacity:1}.theme__inputElement___27dyY:focus:not([disabled]):not([readonly])~.theme__icon___1_C6Z{color:#ff5722}.theme__inputElement___27dyY.theme__filled___1UI7Z~.theme__label___tqKDt:not(.theme__fixed___2pXa4),.theme__inputElement___27dyY:focus:not([disabled]):not([readonly])~.theme__label___tqKDt:not(.theme__fixed___2pXa4),.theme__inputElement___27dyY[type=date]~.theme__label___tqKDt:not(.theme__fixed___2pXa4),.theme__inputElement___27dyY[type=time]~.theme__label___tqKDt:not(.theme__fixed___2pXa4){top:.6rem;font-size:1.2rem}.theme__inputElement___27dyY.theme__filled___1UI7Z.theme__filled___1UI7Z~.theme__hint___2D9g-,.theme__inputElement___27dyY:focus:not([disabled]):not([readonly]).theme__filled___1UI7Z~.theme__hint___2D9g-,.theme__inputElement___27dyY[type=date].theme__filled___1UI7Z~.theme__hint___2D9g-,.theme__inputElement___27dyY[type=time].theme__filled___1UI7Z~.theme__hint___2D9g-{opacity:0}.theme__inputElement___27dyY.theme__filled___1UI7Z~.theme__hint___2D9g-,.theme__inputElement___27dyY.theme__filled___1UI7Z~.theme__label___tqKDt.theme__fixed___2pXa4{display:none}.theme__label___tqKDt{position:absolute;top:3.2rem;left:0;font-size:1.6rem;line-height:1.6rem;color:rgba(0,0,0,.26);pointer-events:none;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:top,font-size,color;transition-property:top,font-size,color}.theme__label___tqKDt.theme__fixed___2pXa4~.theme__hint___2D9g-{display:none}.theme__hint___2D9g-{position:absolute;top:3.2rem;left:0;font-size:1.6rem;line-height:1.6rem;color:rgba(0,0,0,.26);pointer-events:none;opacity:1;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:opacity;transition-property:opacity}.theme__bar___2GHeb{position:relative;display:block;width:100%}.theme__bar___2GHeb:after,.theme__bar___2GHeb:before{-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.2s;transition-duration:.2s;position:absolute;bottom:0;width:0;height:2px;content:"";background-color:#ff5722;-webkit-transition-property:width,background-color;transition-property:width,background-color}.theme__bar___2GHeb:before{left:50%}.theme__bar___2GHeb:after{right:50%}.theme__counter___398RE,.theme__error___3ilni{margin-bottom:-2rem;font-size:1.2rem;line-height:2rem;color:#de3226}.theme__counter___398RE{position:absolute;right:0;color:rgba(0,0,0,.26)}.theme__disabled___6VTPW>.theme__inputElement___27dyY{color:rgba(0,0,0,.26);border-bottom-style:dotted}.theme__errored___3peD4{padding-bottom:0}.theme__errored___3peD4>.theme__inputElement___27dyY{margin-top:1px;border-bottom-color:#de3226}.theme__errored___3peD4>.theme__counter___398RE,.theme__errored___3peD4>.theme__label___tqKDt,.theme__errored___3peD4>.theme__label___tqKDt>.theme__required___2OgFq{color:#de3226}.theme__hidden___3lRxh{display:none}.theme__autocomplete___13r65{position:relative;padding:1rem 0}.theme__autocomplete___13r65.theme__focus___35ZTa .theme__suggestions___3bxnc{max-height:45vh;visibility:visible;box-shadow:0 1px 6px rgba(0,0,0,.12),0 1px 4px rgba(0,0,0,.24)}.theme__values___ky6NA{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-bottom:.5rem}.theme__value___26Cd8{margin:.25rem .5rem .25rem 0}.theme__suggestions___3bxnc{position:absolute;z-index:100;width:100%;max-height:0;overflow-x:hidden;overflow-y:auto;visibility:hidden;background-color:#fff;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:max-height,box-shadow;transition-property:max-height,box-shadow}.theme__suggestions___3bxnc::-webkit-scrollbar{width:0;height:0}.theme__suggestions___3bxnc:not(.theme__up___FUauw){margin-top:-2rem}.theme__suggestions___3bxnc.theme__up___FUauw{bottom:0}.theme__suggestion___shQpe{padding:1rem;font-size:1.6rem;cursor:pointer}.theme__suggestion___shQpe.theme__active___nQ-Lu{background-color:#eee}.theme__input___77Yss{position:relative}.theme__input___77Yss:after{position:absolute;top:50%;right:.8rem;width:0;height:0;pointer-events:none;content:"";border-top:.54857rem solid rgba(0,0,0,.12);border-right:.54857rem solid transparent;border-left:.54857rem solid transparent;-webkit-transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1)}.slide-left__enter___UDCzm,.slide-left__leave___1yls4{position:absolute;-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.slide-left__enter___UDCzm{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.slide-left__enter___UDCzm.slide-left__enterActive___2llDv,.slide-left__leave___1yls4{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}.slide-left__leave___1yls4.slide-left__leaveActive___1ImVa{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.slide-right__enter___8bk-m,.slide-right__leave___3NliL{position:absolute}.slide-right__enterActive___3pxpZ,.slide-right__leaveActive___3spKq{-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.slide-right__enter___8bk-m{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.slide-right__enter___8bk-m.slide-right__enterActive___3pxpZ,.slide-right__leave___3NliL{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}.slide-right__leave___3NliL.slide-right__leaveActive___3spKq{opacity:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.zoom-in__enter___3Ti1d,.zoom-in__leave___3EnQZ{position:absolute}.zoom-in__enterActive___1eFhL,.zoom-in__leaveActive___3dBpi{-webkit-transition:opacity,-webkit-transform;transition:opacity,-webkit-transform;transition:transform,opacity;transition:transform,opacity,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.5s;transition-duration:.5s}.zoom-in__enter___3Ti1d{opacity:0;-webkit-transform:scale(.85);transform:scale(.85)}.zoom-in__enter___3Ti1d.zoom-in__enterActive___1eFhL,.zoom-in__leave___3EnQZ{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.zoom-in__leave___3EnQZ.zoom-in__leaveActive___3dBpi{opacity:0;-webkit-transform:scale(1.25);transform:scale(1.25)}.zoom-out__enter___xiACW,.zoom-out__leave___3wDWL{position:absolute}.zoom-out__enterActive___3QrhD,.zoom-out__leaveActive___3C11f{-webkit-transition:opacity,-webkit-transform;transition:opacity,-webkit-transform;transition:transform,opacity;transition:transform,opacity,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.5s;transition-duration:.5s}.zoom-out__enter___xiACW{opacity:0;-webkit-transform:scale(1.25);transform:scale(1.25)}.zoom-out__enter___xiACW.zoom-out__enterActive___3QrhD,.zoom-out__leave___3wDWL{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.zoom-out__leave___3wDWL.zoom-out__leaveActive___3C11f{opacity:0;-webkit-transform:scale(.85);transform:scale(.85)}.theme__overlay___PiEHX{position:fixed;top:0;left:0;z-index:300;display:-webkit-box;display:-ms-flexbox;display:flex;width:100vw;height:100vh;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-ms-flex-line-pack:center;align-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;pointer-events:none}.theme__overlay___PiEHX.theme__invisible___3SslD>:not(.theme__backdrop___WbaQn){pointer-events:all}.theme__backdrop___WbaQn{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:0;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:opacity;transition-property:opacity}.theme__active___2oZU5{pointer-events:all}.theme__active___2oZU5>.theme__backdrop___WbaQn{opacity:.6}.theme__dialog___1f3Zg{display:-webkit-box;display:-ms-flexbox;display:flex;max-width:96vw;max-height:96vh;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background-color:#fff;border-radius:.2rem;box-shadow:0 19px 60px rgba(0,0,0,.3),0 15px 20px rgba(0,0,0,.22);opacity:0;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transform:translateY(-4rem);transform:translateY(-4rem)}.theme__dialog___1f3Zg.theme__active___3rz6t{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}.theme__small___WKoav{width:30vw}@media screen and (max-width:720px){.theme__small___WKoav{width:50vw}}@media screen and (max-width:600px){.theme__small___WKoav{width:75vw}}.theme__normal___1WehK{width:50vw}@media screen and (max-width:600px){.theme__normal___1WehK{width:96vw}}.theme__fullscreen___2Akul,.theme__large___10bxm{width:96vw}@media screen and (max-width:600px){.theme__fullscreen___2Akul{width:100vw;max-width:100vw;min-height:100vh;max-height:100vh;border-radius:0}}.theme__title____sEzV{font-family:Roboto,Helvetica,Arial,sans-serif;font-size:2rem;font-weight:500;line-height:1;letter-spacing:.02em;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;margin-bottom:1.6rem;color:#000}.theme__body___1_nNM{-webkit-box-flex:2;-ms-flex-positive:2;flex-grow:2;padding:2.4rem;color:#757575}.theme__navigation___3eiS-{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;padding:.8rem;text-align:right}.theme__button___3HGWm{min-width:0;padding-right:.8rem;padding-left:.8rem;margin-left:.8rem}.theme__input___1TiDt:not(.theme__disabled___2N4Gy)>.theme__inputElement___1oBGc{cursor:pointer}.theme__header___1DCA-{padding:1.6rem 2rem;color:#fff;cursor:pointer;background-color:#ff5722}.theme__year___38-P5{display:inline-block;font-size:1.4rem;-webkit-transition:opacity,font-size .35s cubic-bezier(.4,0,.2,1);transition:opacity,font-size .35s cubic-bezier(.4,0,.2,1)}.theme__date___2R1Ad{display:block;font-weight:500;text-transform:capitalize;-webkit-transition:opacity .35s cubic-bezier(.4,0,.2,1);transition:opacity .35s cubic-bezier(.4,0,.2,1)}.theme__calendarWrapper___15gNf{padding:1rem .5rem 0}.theme__yearsDisplay___24Iwn .theme__date___2R1Ad{opacity:.6}.theme__yearsDisplay___24Iwn .theme__year___38-P5{font-size:1.6rem}.theme__monthsDisplay___5fYTt .theme__year___38-P5{opacity:.6}.theme__dialog___1RQhu{width:33rem}.theme__dialog___1RQhu>[role=body]{padding:0}.theme__dialog___1RQhu>[role=navigation]>.theme__button___14VKJ{color:#ff5722}.theme__dialog___1RQhu>[role=navigation]>.theme__button___14VKJ:focus:not(:active),.theme__dialog___1RQhu>[role=navigation]>.theme__button___14VKJ:hover{background:rgba(255,87,34,.2)}.theme__calendar___1I5OE{position:relative;height:27rem;overflow:hidden;font-size:1.4rem;line-height:3rem;text-align:center;background:#fff}.theme__calendar___1I5OE .theme__next___11dJn,.theme__calendar___1I5OE .theme__prev___xfk7M{position:absolute;top:0;z-index:100;height:3.6rem;cursor:pointer;opacity:.7}.theme__calendar___1I5OE .theme__prev___xfk7M{left:0}.theme__calendar___1I5OE .theme__next___11dJn{right:0}.theme__title___2Ue3-{display:inline-block;font-weight:500;line-height:3rem}.theme__years___3xKtS{height:100%;overflow-y:auto;font-size:1.8rem}.theme__years___3xKtS>li{line-height:2.4;cursor:pointer}.theme__years___3xKtS>li.theme__active___2k63V{font-size:2.4rem;font-weight:500;color:#ff5722}.theme__week___17JkF{display:-webkit-box;display:-ms-flexbox;display:flex;height:3rem;-ms-flex-wrap:wrap;flex-wrap:wrap;font-size:1.3rem;line-height:3rem;opacity:.5}.theme__week___17JkF>span{-webkit-box-flex:0;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%}.theme__days___3kAIy{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;font-size:1.3rem}.theme__day___3cb3g{-webkit-box-flex:0;-ms-flex:0 0 14.28571%;flex:0 0 14.28571%;padding:.2rem 0}.theme__day___3cb3g>span{display:inline-block;width:3rem;height:3rem;line-height:3rem;border-radius:50%}.theme__day___3cb3g:hover:not(.theme__active___2k63V):not(.theme__disabled___2N4Gy)>span{color:#fff;background:rgba(255,87,34,.21)}.theme__day___3cb3g.theme__active___2k63V>span{color:#fff;background:#ff5722}.theme__day___3cb3g:hover:not(.theme__disabled___2N4Gy)>span{cursor:pointer}.theme__day___3cb3g.theme__disabled___2N4Gy{opacity:.25}.theme__month___27O28{background-color:#fff}.theme__drawer___3cqqC{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);position:absolute;top:0;display:block;width:24rem;height:100%;overflow-x:hidden;overflow-y:auto;color:#424242;pointer-events:none;background-color:#fafafa;-webkit-transition-delay:0s;transition-delay:0s;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;will-change:transform}.theme__drawer___3cqqC.theme__active___2tbs1{pointer-events:all;-webkit-transition-delay:.07s;transition-delay:.07s;-webkit-transform:translateX(0);transform:translateX(0)}.theme__drawer___3cqqC.theme__right___ZJiGp{right:0;border-left:1px solid #e0e0e0}.theme__drawer___3cqqC.theme__right___ZJiGp:not(.theme__active___2tbs1){-webkit-transform:translateX(100%);transform:translateX(100%)}.theme__drawer___3cqqC.theme__left___wQVqA{left:0;border-right:1px solid #e0e0e0}.theme__drawer___3cqqC.theme__left___wQVqA:not(.theme__active___2tbs1){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.theme__dropdown___co-4M{position:relative}.theme__dropdown___co-4M:not(.theme__active___31xyK)>.theme__values___1jS4g{max-height:0;visibility:hidden}.theme__dropdown___co-4M.theme__active___31xyK>.theme__label___1lqXI,.theme__dropdown___co-4M.theme__active___31xyK>.theme__value___mflIw{opacity:.5}.theme__dropdown___co-4M.theme__active___31xyK>.theme__values___1jS4g{max-height:45vh;visibility:visible;box-shadow:0 1px 6px rgba(0,0,0,.12),0 1px 4px rgba(0,0,0,.24)}.theme__dropdown___co-4M:not(.theme__up___3kWOP)>.theme__values___1jS4g{top:0;bottom:auto}.theme__dropdown___co-4M.theme__up___3kWOP>.theme__values___1jS4g{top:auto;bottom:0}.theme__dropdown___co-4M.theme__disabled___3yAxB{pointer-events:none;cursor:normal}.theme__value___mflIw>input{cursor:pointer}.theme__value___mflIw:after{position:absolute;top:50%;right:.8rem;width:0;height:0;pointer-events:none;content:"";border-top:.54857rem solid rgba(0,0,0,.12);border-right:.54857rem solid transparent;border-left:.54857rem solid transparent;-webkit-transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1)}.theme__field___1elDx{position:relative;padding:2rem 0;cursor:pointer}.theme__field___1elDx.theme__errored___w5ZKs{padding-bottom:0}.theme__field___1elDx.theme__errored___w5ZKs>.theme__label___1lqXI{color:#de3226}.theme__field___1elDx.theme__errored___w5ZKs>.theme__templateValue___3if5o{border-bottom:1px solid #de3226}.theme__field___1elDx.theme__errored___w5ZKs>.theme__label___1lqXI>.theme__required___28L-E{color:#de3226}.theme__field___1elDx.theme__disabled___3yAxB{pointer-events:none;cursor:normal}.theme__field___1elDx.theme__disabled___3yAxB>.theme__templateValue___3if5o{border-bottom-style:dotted;opacity:.7}.theme__templateValue___3if5o{position:relative;min-height:3.84rem;padding:.8rem 0;color:#212121;background-color:transparent;border-bottom:1px solid rgba(0,0,0,.12)}.theme__label___1lqXI{position:absolute;top:.6rem;left:0;font-size:1.2rem;line-height:1.6rem;color:rgba(0,0,0,.26)}.theme__label___1lqXI .theme__required___28L-E{color:#de3226}.theme__error___2QR6b{margin-bottom:-2rem;font-size:1.2rem;line-height:2rem;color:#de3226}.theme__values___1jS4g{position:absolute;z-index:100;width:100%;overflow-y:auto;list-style:none;background-color:#fff;border-radius:.2rem;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:max-height,box-shadow;transition-property:max-height,box-shadow}.theme__values___1jS4g::-webkit-scrollbar{width:0;height:0}.theme__values___1jS4g>*{position:relative;padding:1rem;overflow:hidden;cursor:pointer}.theme__values___1jS4g>:hover{background-color:#eee}.theme__values___1jS4g>.theme__selected___2Uc3r{color:#ff5722}.theme__linear___Ljn5d{position:relative;display:inline-block;width:100%;height:.4rem;overflow:hidden;background:#eee}.theme__linear___Ljn5d.theme__indeterminate___3-YPh .theme__value___xShnS{-webkit-transform-origin:center center;transform-origin:center center;-webkit-animation:theme__linear-indeterminate-bar___rBsh8 1s linear infinite;animation:theme__linear-indeterminate-bar___rBsh8 1s linear infinite}.theme__buffer___2D7u0,.theme__value___xShnS{position:absolute;top:0;right:0;bottom:0;left:0;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transform:scaleX(0);transform:scaleX(0);-webkit-transform-origin:left center;transform-origin:left center}.theme__value___xShnS{background-color:#ff5722}[disabled] .theme__value___xShnS{background-color:rgba(0,0,0,.26)}.theme__buffer___2D7u0{background-image:-webkit-linear-gradient(left,hsla(0,0%,100%,.7),hsla(0,0%,100%,.7)),-webkit-linear-gradient(left,#ff5722,#ff5722);background-image:linear-gradient(90deg,hsla(0,0%,100%,.7),hsla(0,0%,100%,.7)),linear-gradient(90deg,#ff5722,#ff5722)}[disabled] .theme__buffer___2D7u0{background-image:-webkit-linear-gradient(left,hsla(0,0%,100%,.7),hsla(0,0%,100%,.7)),-webkit-linear-gradient(left,rgba(0,0,0,.26),rgba(0,0,0,.26));background-image:linear-gradient(90deg,hsla(0,0%,100%,.7),hsla(0,0%,100%,.7)),linear-gradient(90deg,rgba(0,0,0,.26),rgba(0,0,0,.26))}.theme__circular___1e2Sg{position:relative;display:inline-block;width:60px;height:60px;-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.theme__circular___1e2Sg.theme__indeterminate___3-YPh .theme__circle___3GNXM{-webkit-animation:theme__circular-indeterminate-bar-rotate___3OG7F 2s linear infinite;animation:theme__circular-indeterminate-bar-rotate___3OG7F 2s linear infinite}.theme__circular___1e2Sg.theme__indeterminate___3-YPh .theme__path___15ZCl{-webkit-animation:theme__circular-indeterminate-bar-dash___3AlSL 1.5s ease-in-out infinite;animation:theme__circular-indeterminate-bar-dash___3AlSL 1.5s ease-in-out infinite;stroke-dasharray:1.25,250;stroke-dashoffset:0}.theme__circular___1e2Sg.theme__indeterminate___3-YPh.theme__multicolor___1RiLp .theme__path___15ZCl{-webkit-animation:theme__circular-indeterminate-bar-dash___3AlSL 1.5s ease-in-out infinite,theme__colors___2VEin 6s ease-in-out infinite;animation:theme__circular-indeterminate-bar-dash___3AlSL 1.5s ease-in-out infinite,theme__colors___2VEin 6s ease-in-out infinite}.theme__circle___3GNXM{width:100%;height:100%}.theme__path___15ZCl{-webkit-transition:stroke-dasharray .35s cubic-bezier(.4,0,.2,1);transition:stroke-dasharray .35s cubic-bezier(.4,0,.2,1);fill:none;stroke-dasharray:0,250;stroke-dashoffset:0;stroke-linecap:round;stroke-miterlimit:20;stroke-width:4;stroke:#ff5722}@-webkit-keyframes theme__linear-indeterminate-bar___rBsh8{0%{-webkit-transform:translate(-50%) scaleX(0);transform:translate(-50%) scaleX(0)}50%{-webkit-transform:translate(0) scaleX(.3);transform:translate(0) scaleX(.3)}to{-webkit-transform:translate(50%) scaleX(0);transform:translate(50%) scaleX(0)}}@keyframes theme__linear-indeterminate-bar___rBsh8{0%{-webkit-transform:translate(-50%) scaleX(0);transform:translate(-50%) scaleX(0)}50%{-webkit-transform:translate(0) scaleX(.3);transform:translate(0) scaleX(.3)}to{-webkit-transform:translate(50%) scaleX(0);transform:translate(50%) scaleX(0)}}@-webkit-keyframes theme__circular-indeterminate-bar-rotate___3OG7F{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes theme__circular-indeterminate-bar-rotate___3OG7F{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes theme__circular-indeterminate-bar-dash___3AlSL{0%{stroke-dasharray:1.25,250;stroke-dashoffset:0}50%{stroke-dasharray:111.25,250;stroke-dashoffset:-43.75}to{stroke-dasharray:111.25,250;stroke-dashoffset:-155}}@keyframes theme__circular-indeterminate-bar-dash___3AlSL{0%{stroke-dasharray:1.25,250;stroke-dashoffset:0}50%{stroke-dasharray:111.25,250;stroke-dashoffset:-43.75}to{stroke-dasharray:111.25,250;stroke-dashoffset:-155}}@-webkit-keyframes theme__colors___2VEin{0%{stroke:#4285f4}25%{stroke:#de3e35}50%{stroke:#f7c223}75%{stroke:#1b9a59}to{stroke:#4285f4}}@keyframes theme__colors___2VEin{0%{stroke:#4285f4}25%{stroke:#de3e35}50%{stroke:#f7c223}75%{stroke:#1b9a59}to{stroke:#4285f4}}.theme__container___3AsSH{position:relative;width:calc(100% - 3.2rem);height:3.2rem;margin-right:3.2rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.theme__container___3AsSH:not(:last-child){margin-right:4.2rem}.theme__container___3AsSH:not(:first-child){margin-left:1rem}.theme__knob____QAHG{position:relative;top:0;left:0;z-index:200;display:-webkit-box;display:-ms-flexbox;display:flex;width:3.2rem;height:3.2rem;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;background-color:transparent}.theme__innerknob___20XNj{z-index:100;width:1.2rem;height:1.2rem;background-color:#ff5722;border-radius:50%;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:height,width,background-color,border;transition-property:height,width,background-color,border}.theme__snaps___3KjIu{position:absolute;top:1.5rem;left:0;display:-webkit-box;display:-ms-flexbox;display:flex;width:calc(100% + .2rem);height:.2rem;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;pointer-events:none}.theme__snaps___3KjIu:after{display:block;width:.2rem;height:.2rem;content:"";background-color:#000;border-radius:50%}.theme__snap___3PGtj{-webkit-box-flex:1;-ms-flex:1;flex:1}.theme__snap___3PGtj:after{display:block;width:.2rem;height:.2rem;content:"";background-color:#000;border-radius:50%}.theme__input___3BSW2{width:5rem;padding:0;margin-bottom:0}.theme__input___3BSW2>input{text-align:center}.theme__progress___xkm0P{position:absolute;top:0;left:1.6rem;width:100%;height:100%}.theme__progress___xkm0P .theme__innerprogress____LUK-{position:absolute;top:1.5rem;height:.2rem}.theme__progress___xkm0P .theme__innerprogress____LUK- [data-ref=value]{-webkit-transition-duration:0s;transition-duration:0s}.theme__slider___2H6aE:focus .theme__knob____QAHG:before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:"";background-color:#ff5722;border-radius:50%;opacity:.26}.theme__slider___2H6aE[disabled]{pointer-events:none;cursor:auto}.theme__slider___2H6aE[disabled] .theme__innerknob___20XNj{background-color:#b1b1b1}.theme__slider___2H6aE.theme__editable___3fZo3{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.theme__slider___2H6aE.theme__pinned___3tZ7h .theme__innerknob___20XNj:before{width:2.6rem;margin-left:.3rem;content:"";background-color:#ff5722;border-radius:50% 50% 50% 0;-webkit-transform:rotate(-45deg) scale(0) translate(0);transform:rotate(-45deg) scale(0) translate(0)}.theme__slider___2H6aE.theme__pinned___3tZ7h .theme__innerknob___20XNj:after,.theme__slider___2H6aE.theme__pinned___3tZ7h .theme__innerknob___20XNj:before{position:absolute;top:0;left:0;height:2.6rem;-webkit-transition:background-color .18s ease,-webkit-transform .2s ease;transition:background-color .18s ease,-webkit-transform .2s ease;transition:transform .2s ease,background-color .18s ease;transition:transform .2s ease,background-color .18s ease,-webkit-transform .2s ease}.theme__slider___2H6aE.theme__pinned___3tZ7h .theme__innerknob___20XNj:after{width:3.2rem;font-size:10px;color:#fff;text-align:center;content:attr(data-value);-webkit-transform:scale(0) translate(0);transform:scale(0) translate(0)}.theme__slider___2H6aE.theme__pressed___1GzJj.theme__pinned___3tZ7h .theme__innerknob___20XNj:before{-webkit-transition-delay:.1s;transition-delay:.1s;-webkit-transform:rotate(-45deg) scale(1) translate(1.7rem,-1.7rem);transform:rotate(-45deg) scale(1) translate(1.7rem,-1.7rem)}.theme__slider___2H6aE.theme__pressed___1GzJj.theme__pinned___3tZ7h .theme__innerknob___20XNj:after{-webkit-transition-delay:.1s;transition-delay:.1s;-webkit-transform:scale(1) translateY(-1.7rem);transform:scale(1) translateY(-1.7rem)}.theme__slider___2H6aE.theme__pressed___1GzJj:not(.theme__pinned___3tZ7h).theme__ring___N87_t .theme__progress___xkm0P{left:3rem;width:calc(100% - 1.4rem)}.theme__slider___2H6aE.theme__pressed___1GzJj:not(.theme__pinned___3tZ7h) .theme__innerknob___20XNj{width:100%;height:100%;-webkit-transform:translateZ(0);transform:translateZ(0)}.theme__slider___2H6aE.theme__ring___N87_t .theme__innerknob___20XNj{background-color:transparent;border:.2rem solid #eee}.theme__slider___2H6aE.theme__ring___N87_t .theme__innerknob___20XNj:before{background-color:#ff5722}.theme__slider___2H6aE.theme__ring___N87_t .theme__progress___xkm0P{left:2rem;width:calc(100% - .4rem);-webkit-transition:left .18s ease,width .18s ease;transition:left .18s ease,width .18s ease}.theme__slider___2H6aE.theme__ring___N87_t.theme__pinned___3tZ7h .theme__innerknob___20XNj{background-color:#fff}.theme__slider___2H6aE.theme__ring___N87_t.theme__pinned___3tZ7h .theme__progress___xkm0P{left:1.6rem;width:100%}.theme__disabled___3HqAo,.theme__field___2rog8{position:relative;display:block;height:auto;margin-bottom:1.5rem;white-space:nowrap;vertical-align:middle}.theme__text___3b1B6{display:inline-block;padding-left:1rem;font-size:1.4rem;line-height:2.4rem;color:#000;white-space:normal;vertical-align:top}.theme__off___Ih3qa,.theme__on___3ocqI{position:relative;display:inline-block;width:3.6rem;height:1.4rem;margin-top:.5rem;vertical-align:top;cursor:pointer;border-radius:1.4rem}.theme__thumb___3ryrT{-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.28s;transition-duration:.28s;position:absolute;top:-.3rem;width:2rem;height:2rem;cursor:pointer;border-radius:50%;-webkit-transition-property:left;transition-property:left}.theme__thumb___3ryrT .theme__ripple___1A_Pi{background-color:#ff5722;opacity:.3;-webkit-transition-duration:.65s;transition-duration:.65s}.theme__on___3ocqI{background:rgba(255,87,34,.5)}.theme__on___3ocqI .theme__thumb___3ryrT{box-shadow:0 3px 4px 0 rgba(0,0,0,.14),0 3px 3px -2px rgba(0,0,0,.2),0 1px 8px 0 rgba(0,0,0,.12);left:1.6rem;background:#ff5722}.theme__off___Ih3qa{background:rgba(0,0,0,.26)}.theme__off___Ih3qa .theme__thumb___3ryrT{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);left:0;background:#fafafa}.theme__off___Ih3qa .theme__ripple___1A_Pi{background:rgba(0,0,0,.4)}.theme__input___10E4S:focus:not(:active)+.theme__switch-off___105FO>.theme__thumb___3ryrT:before,.theme__input___10E4S:focus:not(:active)+.theme__switch-on___2n4g1>.theme__thumb___3ryrT:before{position:absolute;top:50%;left:50%;box-sizing:border-box;display:inline-block;width:.8rem;height:.8rem;content:"";background-color:transparent;border-radius:50%;-webkit-transform:translate(-.4rem,-.4rem);transform:translate(-.4rem,-.4rem)}.theme__input___10E4S{width:0;height:0;overflow:hidden;opacity:0}.theme__input___10E4S:focus:not(:active)+.theme__switch-on___2n4g1>.theme__thumb___3ryrT:before{background-color:rgba(255,87,34,.26);box-shadow:0 0 0 2rem rgba(255,87,34,.26)}.theme__input___10E4S:focus:not(:active)+.theme__switch-off___105FO>.theme__thumb___3ryrT:before{background-color:rgba(0,0,0,.1);box-shadow:0 0 0 2rem rgba(0,0,0,.1)}.theme__disabled___3HqAo .theme__text___3b1B6{color:rgba(0,0,0,.26)}.theme__disabled___3HqAo .theme__off___Ih3qa,.theme__disabled___3HqAo .theme__on___3ocqI{cursor:auto;background:rgba(0,0,0,.12)}.theme__disabled___3HqAo .theme__thumb___3ryrT{cursor:auto;background-color:#bdbdbd;border-color:transparent}.theme__input___33OFH:not(.theme__disabled___3zAd9)>.theme__inputElement___3V_R1{cursor:pointer}.theme__header___B8avX{position:relative;width:100%;padding:1rem;font-size:5.2rem;color:#fff;text-align:center;background:#ff5722}.theme__hours___2bCtV,.theme__minutes___fKY3r{display:inline-block;cursor:pointer;opacity:.6}.theme__separator___1wf1f{margin:0 .5rem;opacity:.6}.theme__ampm___2zwK2{position:absolute;top:50%;right:2rem;width:4rem;height:4.4rem;margin-top:-2.2rem;font-size:1.6rem;line-height:2.2rem;text-align:center}.theme__am___ZDt_I,.theme__pm___15BOL{display:block;cursor:pointer;opacity:.6}.theme__dialog___2xstp{width:30rem}.theme__dialog___2xstp>[role=body]{padding:0;overflow-y:visible}.theme__dialog___2xstp>[role=navigation]>.theme__button___2Naxh{color:#ff5722}.theme__dialog___2xstp>[role=navigation]>.theme__button___2Naxh:focus:not(:active),.theme__dialog___2xstp>[role=navigation]>.theme__button___2Naxh:hover{background:rgba(255,87,34,.2)}.theme__dialog___2xstp.theme__amFormat___3V_aj .theme__am___ZDt_I,.theme__dialog___2xstp.theme__hoursDisplay___2XYVr .theme__hours___2bCtV,.theme__dialog___2xstp.theme__minutesDisplay___2lM_9 .theme__minutes___fKY3r,.theme__dialog___2xstp.theme__pmFormat___EeG6D .theme__pm___15BOL{opacity:1}.theme__clock___2Wdtj{padding:1.5rem 2rem}.theme__placeholder___49iU5{position:relative;z-index:100}.theme__clockWrapper___nVLna{position:absolute;width:100%;background-color:#eee;border-radius:50%}.theme__face___3ZQPp{position:absolute;top:50%;left:50%;z-index:100;cursor:pointer;border-radius:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%)}.theme__number___19LR-{position:relative;width:2rem;height:2rem;margin-top:-1rem;margin-left:-1rem;text-align:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.theme__number___19LR-.theme__active___2hiVT{color:#fff}.theme__hand___Ff-XL{bottom:50%;display:block;width:.4rem;margin-left:-.2rem;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}.theme__hand___Ff-XL,.theme__hand___Ff-XL:before{position:absolute;left:50%;background-color:#ff5722}.theme__hand___Ff-XL:before{bottom:0;width:1rem;height:1rem;margin-bottom:-.5rem;margin-left:-.5rem;content:"";border-radius:50%}.theme__hand___Ff-XL.theme__small___Cthf4>.theme__knob___3yr7J{background-color:rgba(255,87,34,.2)}.theme__hand___Ff-XL.theme__small___Cthf4>.theme__knob___3yr7J:after{position:absolute;top:50%;left:50%;width:1.2rem;height:1.2rem;margin-top:-.6rem;margin-left:-.6rem;content:"";background:#ff5722;border-radius:50%}.theme__hand___Ff-XL.theme__small___Cthf4>.theme__knob___3yr7J:before{position:absolute;bottom:0;left:50%;width:.4rem;height:2.2rem;margin-left:-.2rem;content:"";background:#ff5722}.theme__knob___3yr7J{position:absolute;top:-3.4rem;left:50%;width:3.4rem;height:3.4rem;margin-left:-1.7rem;cursor:pointer;background-color:#ff5722;border-radius:50%}.theme__icon___oJcgi{margin-right:1rem;font-size:1.8rem}.theme__link___AKdRk{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-line-pack:center;align-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:1.5;cursor:pointer;-webkit-transition:opacity .35s cubic-bezier(.4,0,.2,1);transition:opacity .35s cubic-bezier(.4,0,.2,1)}.theme__link___AKdRk:not(.theme__active___1r_T0){opacity:.5}.theme__link___AKdRk:active,.theme__link___AKdRk:hover{opacity:1}.theme__link___AKdRk>*{vertical-align:middle}.theme__link___AKdRk>abbr{text-transform:capitalize}.theme__link___AKdRk>small{margin-left:.8rem;font-size:1.2rem;text-align:center}.theme__horizontal___1Gx6_>[data-react-toolbox=button],.theme__horizontal___1Gx6_>[data-react-toolbox=link]{display:inline-block;margin:0 .5rem}.theme__vertical___29Teo>[data-react-toolbox=button],.theme__vertical___29Teo>[data-react-toolbox=link]{display:block;margin:.5rem}.theme__horizontal___1Gx6_,.theme__vertical___29Teo{padding:.5rem}.theme__horizontal___1Gx6_>[data-react-toolbox=link],.theme__vertical___29Teo>[data-react-toolbox=link]{color:#000}.theme__snackbar___33MRN{position:fixed;right:2.4rem;bottom:0;left:2.4rem;z-index:200;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:1.4rem 2.4rem;margin:0 auto;margin-top:1.4rem;color:#fff;background-color:#212121;border-radius:.2rem;-webkit-transition:all .35s cubic-bezier(.4,0,.2,1) .35s;transition:all .35s cubic-bezier(.4,0,.2,1) .35s}.theme__snackbar___33MRN.theme__accept___I_Pq1 .theme__button___psiy3{color:#4caf50}.theme__snackbar___33MRN.theme__warning___29XlW .theme__button___psiy3{color:#eeff41}.theme__snackbar___33MRN.theme__cancel___1C-_T .theme__button___psiy3{color:#f44336}.theme__snackbar___33MRN:not(.theme__active___1U6m8){-webkit-transform:translateY(100%);transform:translateY(100%)}.theme__snackbar___33MRN.theme__active___1U6m8{-webkit-transform:translateY(0);transform:translateY(0)}.theme__label___2EWLb{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:1.4rem}.theme__button___psiy3{min-width:inherit;margin:-.7rem -1.2rem -.7rem 4.8rem}.theme__table___3Gpgy{width:100%;font-size:1.2rem;color:#757575;text-align:left;border-spacing:0}.theme__table___3Gpgy tr{height:48px;line-height:48px}.theme__table___3Gpgy th{font-weight:700}.theme__table___3Gpgy th:first-letter{text-transform:capitalize}.theme__table___3Gpgy td,.theme__table___3Gpgy th{position:relative;padding:0 1.8rem;border-bottom:1px solid rgba(0,0,0,.12)}.theme__table___3Gpgy td.theme__selectable___3T6wF,.theme__table___3Gpgy th.theme__selectable___3T6wF{width:1.8rem;padding-right:0}.theme__table___3Gpgy td.theme__selectable___3T6wF>*,.theme__table___3Gpgy th.theme__selectable___3T6wF>*{margin:0}.theme__row___2iik7{-webkit-transition:background-color .35s cubic-bezier(.4,0,.2,1);transition:background-color .35s cubic-bezier(.4,0,.2,1)}.theme__row___2iik7:last-child td{border-color:transparent}.theme__row___2iik7>td>input{display:block;width:100%;background-color:transparent;border:0}.theme__row___2iik7:hover,.theme__selected___3xb9B{background-color:#eee}.theme__editable___1aYHG>*{cursor:pointer}.theme__tooltip___3uHDc{position:absolute;z-index:200;display:block;max-width:17rem;padding:.5rem;font-family:Roboto,sans-serif;font-size:1rem;font-weight:700;line-height:1.4rem;text-align:center;text-transform:none;pointer-events:none;-webkit-transition:transform .2s cubic-bezier(.4,0,.2,1);transition:transform .2s cubic-bezier(.4,0,.2,1);-webkit-transform:scale(0) translateX(-50%);transform:scale(0) translateX(-50%);-webkit-transform-origin:top left;transform-origin:top left}.theme__tooltip___3uHDc.theme__tooltipActive___3FruK{-webkit-transform:scale(1) translateX(-50%);transform:scale(1) translateX(-50%)}.theme__tooltip___3uHDc.theme__tooltipTop___2JE6v{-webkit-transform:scale(0) translateX(-50%) translateY(-100%);transform:scale(0) translateX(-50%) translateY(-100%)}.theme__tooltip___3uHDc.theme__tooltipTop___2JE6v.theme__tooltipActive___3FruK{-webkit-transform:scale(1) translateX(-50%) translateY(-100%);transform:scale(1) translateX(-50%) translateY(-100%)}.theme__tooltip___3uHDc.theme__tooltipLeft___3S-DF{-webkit-transform:scale(0) translateX(-100%) translateY(-50%);transform:scale(0) translateX(-100%) translateY(-50%)}.theme__tooltip___3uHDc.theme__tooltipLeft___3S-DF.theme__tooltipActive___3FruK{-webkit-transform:scale(1) translateX(-100%) translateY(-50%);transform:scale(1) translateX(-100%) translateY(-50%)}.theme__tooltip___3uHDc.theme__tooltipRight___DIPzx{-webkit-transform:scale(0) translateX(0) translateY(-50%);transform:scale(0) translateX(0) translateY(-50%)}.theme__tooltip___3uHDc.theme__tooltipRight___DIPzx.theme__tooltipActive___3FruK{-webkit-transform:scale(1) translateX(0) translateY(-50%);transform:scale(1) translateX(0) translateY(-50%)}.theme__tooltipInner___3yZfk{display:block;padding:.8rem;color:#fff;background:rgba(97,97,97,.9);border-radius:.2rem}.style__appbar___2QTMv{z-index:200;display:-webkit-box;display:-ms-flexbox;display:flex;min-height:6.4rem;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;box-shadow:0 1px hsla(0,0%,100%,.65);background-color:#37474f}.style__appTitle___14TWh{text-transform:uppercase}.style__companySettings___xBM6u,.style__topBarOptions___mSQNO{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:right}.style__companySettings___xBM6u>span{text-transform:uppercase;font-size:1.4rem;font-weight:500}.style__menu___19mUU>div{margin-top:4rem;margin-right:1rem}.style__menu___19mUU button>span{color:#fff}.style__root___1OFQ4{display:-webkit-box;display:-ms-flexbox;display:flex;width:22rem;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background-color:#fff}.style__navigation___VosYm{position:fixed;top:6.4rem;bottom:0;left:0;z-index:300;box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.2);-webkit-transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:-webkit-transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1);transition:transform .35s cubic-bezier(.4,0,.2,1),-webkit-transform .35s cubic-bezier(.4,0,.2,1)}.style__list___iyZve{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;overflow-y:auto}.style__list___iyZve::-webkit-scrollbar{width:0;height:0}.style__item___3fG-k>span{padding:1.2rem 2.4rem}.style__item___3fG-k [data-react-toolbox=list-item-text]{font-size:1.4rem;font-weight:500}.style__active___2e1_p{background:#eee}.style__active___2e1_p span:before{position:absolute;bottom:0;left:0;display:block;width:.3rem;height:100%;content:"";background-color:#ff5722}.style__footer___UuQo4{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;padding:2.4rem;overflow:hidden;text-align:center;font-size:1.4rem;color:#757575;border-top:1px solid #e0e0e0}.style__footer___UuQo4>*{display:block}.style__footerTitle___UML2d{color:#fd7348;font-weight:500;padding-bottom:.5rem}/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}html{font-size:62.5%}body{position:absolute;width:100%;height:100%;padding:0;margin:0;font-family:Roboto,sans-serif;font-size:1.6rem;-webkit-touch-callout:none}body *{-webkit-tap-highlight-color:rgba(255,255,255,0)}a,abbr,address,article,aside,audio,b,blockquote,body,caption,cite,code,dd,del,dfn,dialog,div,dl,dt,em,fieldset,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video{padding:0;margin:0;border:0;outline:0}*,:after,:before{box-sizing:border-box;padding:0;margin:0}a,abbr,button,h1,h2,h3,h4,h5,h6,label,p,small,span{font-smoothing:antialiased;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}a{text-decoration:none;-webkit-tap-highlight-color:transparent}button,input:not([type=checkbox]):not([type=radio]){outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(255,255,255,0)}input[required]:-moz-ui-invalid{box-shadow:none}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{opacity:.54}h1,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-size:5.6rem;line-height:1.35;letter-spacing:-.02em}h1,h1 small,h2,h2 small,h3 small,h4 small,h5 small,h6 small{font-family:Roboto,Helvetica,Arial,sans-serif;font-weight:400}h2{font-size:4.5rem;line-height:4.8rem}h3{font-size:3.4rem;line-height:4rem}h3,h4{font-family:Roboto,Helvetica,Arial,sans-serif;font-weight:400}h4{font-size:2.4rem;line-height:3.2rem;-moz-osx-font-smoothing:grayscale}h5{font-family:Roboto,Helvetica,Arial,sans-serif;font-size:2rem;font-weight:500;line-height:1;letter-spacing:.02em}h6{font-family:Roboto,Helvetica,Arial,sans-serif;font-size:1.6rem;letter-spacing:.04em}h6,p{font-weight:400;line-height:2.4rem}p{font-size:1.4rem;letter-spacing:0}.style__mainPage___3-2ms{margin-top:6.4rem;margin-left:22rem}.style__mainContent___cQjt4{padding:2rem}.style__mainBreadcrumbs___3oSTT{padding-bottom:2rem;color:#abacac}.style__mainBreadcrumbs___3oSTT a{-webkit-transition:color .4s;transition:color .4s;color:#37474f}.style__mainBreadcrumbs___3oSTT a:link,.style__mainBreadcrumbs___3oSTT a:visited{color:#37474f}.style__mainBreadcrumbs___3oSTT a:active,.style__mainBreadcrumbs___3oSTT a:hover{color:#2e3339}.style__showbox___2_rzn{position:absolute;top:0;bottom:0;left:0;right:0;z-index:1000001;height:100%;width:100%;background:none repeat scroll 0 0 #000;position:fixed;display:block;opacity:.5}.style__loader___2nW0b{position:relative;top:5.4rem}.style__notificationSnackbar___1QypG{width:60%;text-align:center}hgroup{text-align:center;margin-top:8rem}hgroup h3{color:#37474f}hgroup .style__subtitle___iA-iX{margin-top:1rem;color:#fd7348;font-weight:200}.style__group___eZldG{position:relative;margin-bottom:2rem}.style__dashboardCard___3-5mX{width:40rem;margin:4em auto;padding:3em 2em 2em}.style__cardActions___29Swh{padding-top:2rem;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.style__welcome___3aHN5 .style__title___3ayCw{margin-top:3rem;color:#fd7348}.style__welcome___3aHN5 .style__subtitle___2Mmn8{margin-top:2rem;letter-spacing:.3em;color:#abacac}.style__commentForm___txxPA{padding:1rem}.style__toolbar___ySVYb{padding-bottom:1rem}.style__bottomOptions___1DDQN{margin-top:2rem}.style__pageNotFound___3-Ggj>p{font-size:2.4rem;font-weight:400;padding-bottom:2rem}body{background:#f6f6f6}
2 | /*# sourceMappingURL=main.098aa9ee0d410b880d633a4523eae478.css.map*/
--------------------------------------------------------------------------------
/dist_server/index.html:
--------------------------------------------------------------------------------
1 | react-redux-starter
--------------------------------------------------------------------------------
/dist_server/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const path = require('path');
3 | // const compression = require('compression');
4 |
5 | const port = process.env.PORT || 3000;
6 | const app = express();
7 |
8 | // app.use(compression());
9 | app.use(express.static(__dirname));
10 |
11 | app.get('/', (_req, res) => {
12 | res.sendFile(path.join(__dirname, 'index.html'));
13 | });
14 |
15 | /* eslint-disable no-console */
16 |
17 | app.listen(port, (err) => {
18 | if (err) {
19 | console.log(err);
20 | } else {
21 | console.log(`server started port: ${port}`);
22 | }
23 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-redux-starter",
3 | "version": "0.1.0",
4 | "author": "Ricardo Reis",
5 | "homepage": "https://github.com/rjmreis/react-redux-starter#readme",
6 | "description": "React/Redux starter with login and basic CRUD functionality",
7 | "bugs": {
8 | "url": "https://github.com/rjmreis/react-redux-starter/issues"
9 | },
10 | "engines": {
11 | "npm": ">=6.0.0"
12 | },
13 | "scripts": {
14 | "start-message": "babel-node tools/startMessage.js",
15 | "prestart": "npm-run-all --parallel start-message remove-dist",
16 | "start": "npm-run-all --parallel test:watch open:src lint:watch",
17 | "open:src": "babel-node tools/srcServer.js",
18 | "open:dist": "babel-node tools/distServer.js",
19 | "dist-server": "node dist_server/server.js",
20 | "lint": "esw webpack.config.* src tools --color",
21 | "lint:watch": "npm run lint -- --watch",
22 | "clean-dist": "npm run remove-dist && mkdir dist",
23 | "remove-dist": "rimraf ./dist",
24 | "prebuild": "npm run clean-dist && npm run lint && npm run test",
25 | "build": "babel-node tools/build.js && npm run open:dist",
26 | "test": "mocha tools/testSetup.js \"src/**/*.spec.js\" --reporter progress",
27 | "test:cover": "babel-node node_modules/isparta/bin/isparta cover --root src --report html node_modules/mocha/bin/_mocha -- --require ./tools/testSetup.js \"src/**/*.spec.js\" --reporter progress",
28 | "test:cover:travis": "babel-node node_modules/isparta/bin/isparta cover --root src --report lcovonly _mocha -- --require ./tools/testSetup.js \"src/**/*.spec.js\" && cat ./coverage/lcov.info | node_modules/coveralls/bin/coveralls.js",
29 | "test:watch": "npm run test -- --watch",
30 | "open:cover": "npm run test:cover && open coverage/index.html"
31 | },
32 | "license": "MIT",
33 | "dependencies": {
34 | "babel-cli": "6.18.0",
35 | "babel-core": "6.21.0",
36 | "express": "^4.14.0",
37 | "immutability-helper": "^2.0.0",
38 | "normalize.css": "^5.0.0",
39 | "object-assign": "4.1.0",
40 | "react": "15.4.1",
41 | "react-addons-css-transition-group": "^15.4.1",
42 | "react-breadcrumbs": "^1.5.1",
43 | "react-dom": "15.4.1",
44 | "react-redux": "5.0.1",
45 | "react-router": "3.0.0",
46 | "react-router-redux": "4.0.7",
47 | "react-toolbox": "^1.3.3",
48 | "redux": "3.6.0",
49 | "redux-thunk": "2.1.0",
50 | "validate.js": "^0.11.1"
51 | },
52 | "devDependencies": {
53 | "autoprefixer": "6.5.4",
54 | "babel-eslint": "^7.1.1",
55 | "babel-loader": "6.2.10",
56 | "babel-plugin-react-display-name": "2.0.0",
57 | "babel-plugin-transform-react-constant-elements": "6.9.1",
58 | "babel-plugin-transform-react-remove-prop-types": "0.2.11",
59 | "babel-preset-latest": "6.16.0",
60 | "babel-preset-react": "6.16.0",
61 | "babel-preset-react-hmre": "1.1.1",
62 | "babel-preset-stage-1": "6.16.0",
63 | "babel-register": "6.18.0",
64 | "browser-sync": "2.18.5",
65 | "chai": "3.5.0",
66 | "chalk": "1.1.3",
67 | "connect-history-api-fallback": "1.3.0",
68 | "coveralls": "2.11.15",
69 | "cross-env": "3.1.3",
70 | "css-loader": "0.26.1",
71 | "enzyme": "2.6.0",
72 | "eslint": "3.12.2",
73 | "eslint-plugin-babel": "^4.0.0",
74 | "eslint-plugin-import": "2.2.0",
75 | "eslint-plugin-jsx-a11y": "3.0.2",
76 | "eslint-plugin-react": "6.8.0",
77 | "eslint-watch": "2.1.14",
78 | "extract-text-webpack-plugin": "1.0.1",
79 | "file-loader": "0.9.0",
80 | "html-webpack-plugin": "2.24.1",
81 | "isparta": "4.0.0",
82 | "json-loader": "^0.5.4",
83 | "mocha": "3.2.0",
84 | "mockdate": "2.0.1",
85 | "node-sass": "4.1.0",
86 | "npm-run-all": "3.1.2",
87 | "open": "0.0.5",
88 | "postcss-loader": "1.2.1",
89 | "prompt": "1.0.0",
90 | "react-addons-test-utils": "15.4.1",
91 | "redux-immutable-state-invariant": "1.2.4",
92 | "replace": "0.3.0",
93 | "rimraf": "2.5.4",
94 | "sass-loader": "4.1.0",
95 | "sinon": "1.17.6",
96 | "sinon-chai": "2.8.0",
97 | "style-loader": "0.13.1",
98 | "url-loader": "0.5.7",
99 | "webpack": "1.14.0",
100 | "webpack-dev-middleware": "1.9.0",
101 | "webpack-hot-middleware": "2.13.2",
102 | "webpack-md5-hash": "0.0.5"
103 | },
104 | "keywords": [
105 | "react",
106 | "redux",
107 | "material"
108 | ],
109 | "repository": {
110 | "type": "git",
111 | "url": ""
112 | }
113 | }
--------------------------------------------------------------------------------
/src/actions/ajaxStatusActions.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/actionTypes';
2 |
3 | export function beginAjaxCall() {
4 | return { type: types.BEGIN_AJAX_CALL };
5 | }
6 |
7 | export function ajaxCallError() {
8 | return { type: types.AJAX_CALL_ERROR };
9 | }
10 |
--------------------------------------------------------------------------------
/src/actions/authActions.js:
--------------------------------------------------------------------------------
1 | import { browserHistory } from 'react-router';
2 | import * as types from '../constants/actionTypes';
3 | import api from '../api';
4 | import { beginAjaxCall, ajaxCallError } from './ajaxStatusActions';
5 |
6 | const requestLogin = creds => {
7 | return {
8 | type: types.LOGIN_REQUEST,
9 | isAuthenticated: false,
10 | creds
11 | };
12 | };
13 |
14 | const receiveLogin = auth => {
15 | return {
16 | type: types.LOGIN_SUCCESS,
17 | isAuthenticated: true,
18 | user: auth.user
19 | };
20 | };
21 |
22 | const loginError = message => {
23 | return {
24 | type: types.LOGIN_FAILURE,
25 | isAuthenticated: false,
26 | message
27 | };
28 | };
29 |
30 | const requestLogout = () => {
31 | return {
32 | type: types.LOGOUT_REQUEST,
33 | isAuthenticated: true
34 | };
35 | };
36 |
37 | const receiveLogout = () => {
38 | return {
39 | type: types.LOGOUT_SUCCESS,
40 | isAuthenticated: false
41 | };
42 | };
43 |
44 | // Calls the API to get a token and
45 | // dispatches actions along the way
46 | export const loginUser = creds => (
47 |
48 | dispatch => {
49 | dispatch(beginAjaxCall());
50 |
51 | // We dispatch requestLogin to kickoff the call to the API
52 | dispatch(requestLogin(creds));
53 |
54 | return api.auth.authenticate(creds)
55 | .then(auth => {
56 | // If login was successful, set the token in local storage
57 | localStorage.setItem('id_token', auth.id_token);
58 | localStorage.setItem('user', JSON.stringify(auth.user));
59 |
60 | // Dispatch the success action
61 | dispatch(receiveLogin(auth));
62 | }).catch(error => {
63 | dispatch(ajaxCallError(error));
64 | dispatch(loginError(error.message));
65 | throw error;
66 | });
67 | }
68 | );
69 |
70 | // Logs the user out
71 | export const logoutUser = () => {
72 | return dispatch => {
73 | dispatch(requestLogout());
74 | localStorage.removeItem('id_token');
75 | localStorage.removeItem('user');
76 | dispatch(receiveLogout());
77 | browserHistory.push('/');
78 | };
79 | };
80 |
--------------------------------------------------------------------------------
/src/actions/commentActions.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/actionTypes';
2 | import api from '../api';
3 | import { beginAjaxCall } from './ajaxStatusActions';
4 | import { handleAjaxError } from '../utils/ajax';
5 |
6 | export const listComments = () => (
7 | (dispatch) => {
8 | dispatch(beginAjaxCall());
9 |
10 | return api.comments.listComments()
11 | .then(comments => {
12 | dispatch({ type: types.LIST_COMMENTS_SUCCESS, comments: comments });
13 | }).catch(error => {
14 | handleAjaxError(dispatch, error);
15 | throw error;
16 | });
17 | }
18 | );
19 |
20 | export const saveComment = (comment) => (
21 | (dispatch) => {
22 | dispatch(beginAjaxCall());
23 |
24 | return api.comments.saveComment(comment)
25 | .then(savedComment => {
26 | comment.id ? dispatch({ type: types.UPDATE_COMMENT_SUCCESS, comment: savedComment }) :
27 | dispatch({ type: types.CREATE_COMMENT_SUCCESS, comment: savedComment });
28 | }).catch(error => {
29 | handleAjaxError(dispatch, error);
30 | throw (error);
31 | });
32 | }
33 | );
34 |
35 | export const deleteComment = comment => (
36 | (dispatch) => {
37 | dispatch(beginAjaxCall());
38 |
39 | let commentId = comment.id;
40 | return api.comments.deleteComment(comment)
41 | .then(() => {
42 | dispatch({ type: types.DELETE_COMMENT_SUCCESS, commentId: commentId });
43 | }).catch(error => {
44 | handleAjaxError(dispatch, error);
45 | throw (error);
46 | });
47 | }
48 | );
49 |
--------------------------------------------------------------------------------
/src/actions/notificationActions.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/actionTypes';
2 |
3 | export const showNotification = message => (
4 | (dispatch) => {
5 | return dispatch({ type: types.SHOW_NOTIFICATION, message });
6 | }
7 | );
8 |
9 | export const hideNotification = () => (
10 | (dispatch) => {
11 | return dispatch({ type: types.HIDE_NOTIFICATION });
12 | }
13 | );
--------------------------------------------------------------------------------
/src/api/auth.js:
--------------------------------------------------------------------------------
1 | const auth = {
2 | authenticate: creds => new Promise(function (resolve, reject) {
3 | if (creds.username === 'admin' && creds.password === 'password') {
4 | resolve({
5 | id_token: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.xuEv8qrfXu424LZk8bVgr9MQJUIrp1rHcPyZw_KSsds',
6 | user: {
7 | name: 'Admin'
8 | }
9 | });
10 | } else {
11 | reject();
12 | }
13 | })
14 | };
15 |
16 | export default auth;
17 |
--------------------------------------------------------------------------------
/src/api/comments.js:
--------------------------------------------------------------------------------
1 | /**
2 | * PROXY API - AJAX calls should be implemented at this layer.
3 | * For demo purposes localStorage is used instead
4 | */
5 | const comments = {
6 | listComments: () => new Promise(function (resolve) {
7 | let comments = JSON.parse(localStorage.getItem('comments')) || [];
8 |
9 | resolve(comments);
10 | }),
11 |
12 | saveComment: (comment) => {
13 | let comments = JSON.parse(localStorage.getItem('comments')) || [];
14 |
15 | if (comment.id) {
16 | // Update array with new object
17 | let newComments = [...comments.filter(_comment => _comment.id !== comment.id), Object.assign({}, comment)];
18 | localStorage.setItem('comments', JSON.stringify(newComments));
19 |
20 | return new Promise(function (resolve) {
21 | resolve(comment);
22 | });
23 | } else {
24 | // Create comment
25 | let newComment = Object.assign({}, comment);
26 | newComment.id = Math.floor((Date.now() + Math.random()) * 0x10000); // Generate random id
27 |
28 | // Update array with new object
29 | let newComments = [...comments, Object.assign({}, newComment)];
30 | localStorage.setItem('comments', JSON.stringify(newComments));
31 |
32 | return new Promise(function (resolve) {
33 | resolve(newComment);
34 | });
35 | }
36 | },
37 |
38 | deleteComment: (comment) => {
39 | let comments = JSON.parse(localStorage.getItem('comments')) || [];
40 | let newComments = comments.filter(_comment => _comment.id !== comment.id);
41 | localStorage.setItem('comments', JSON.stringify(newComments));
42 |
43 | return new Promise(function (resolve) {
44 | resolve(true);
45 | });
46 | }
47 | };
48 |
49 | export default comments;
50 |
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | import auth from './auth';
2 | import comments from './comments';
3 |
4 | // Reference to all API definitions
5 | const api = {
6 | auth,
7 | comments
8 | };
9 |
10 | export default api;
11 |
--------------------------------------------------------------------------------
/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { connect } from 'react-redux';
3 | import { Layout } from 'react-toolbox';
4 | import Main from './Main';
5 | import LoginPage from './Auth/LoginPage';
6 |
7 | const App = (props) => (
8 |
9 | {props.isAuthenticated ? {props.children} : }
10 |
11 | );
12 |
13 | App.propTypes = {
14 | children: PropTypes.element.isRequired,
15 | routes: PropTypes.array.isRequired,
16 | isAuthenticated: PropTypes.bool.isRequired
17 | };
18 |
19 | const mapStateToProps = state => ({
20 | isAuthenticated: state.auth.isAuthenticated
21 | });
22 |
23 | export default connect(mapStateToProps)(App);
24 |
--------------------------------------------------------------------------------
/src/components/Auth/LoginForm.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Card, CardActions } from 'react-toolbox/lib/card';
3 | import { Button } from 'react-toolbox/lib/button';
4 | import { Input } from 'react-toolbox/lib/input';
5 | import style from './style.scss'; // eslint-disable-line
6 |
7 | const LoginForm = ({creds, login, onChange}) => {
8 |
9 | return (
10 |
22 | );
23 | };
24 |
25 | LoginForm.propTypes = {
26 | creds: React.PropTypes.object.isRequired,
27 | login: React.PropTypes.func.isRequired,
28 | onChange: React.PropTypes.func.isRequired
29 | };
30 |
31 | export default LoginForm;
32 |
--------------------------------------------------------------------------------
/src/components/Auth/LoginPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { bindActionCreators } from 'redux';
3 | import { connect } from 'react-redux';
4 | import { Panel } from 'react-toolbox';
5 | import Notifications from '../Notifications';
6 | import LoginForm from './LoginForm';
7 | import User from '../../models/User';
8 | import * as actions from '../../actions/authActions';
9 | import { showNotification } from '../../actions/notificationActions';
10 | import style from './style.scss'; // eslint-disable-line
11 |
12 | class Login extends Component {
13 | constructor(props) {
14 | super(props);
15 |
16 | this.state = {
17 | creds: new User(),
18 | showValidationErrors: false
19 | };
20 |
21 | this.handleChange = this.handleChange.bind(this);
22 | this.login = this.login.bind(this);
23 | }
24 |
25 | handleChange(value, event) {
26 | let field = event.target.name;
27 | let creds = this.state.creds;
28 | creds[field] = value.trim();
29 | return this.setState({ creds: creds });
30 | }
31 |
32 | login(event) {
33 | event.preventDefault();
34 |
35 | let creds = { username: this.state.creds.username, password: this.state.creds.password };
36 | this.props.actions.loginUser(creds)
37 | .catch(() => {
38 | this.props.showNotification('Authentication failed');
39 | });
40 | }
41 |
42 | render() {
43 | return (
44 |
45 |
46 | react-redux-starter
47 | by Ricardo Reis
48 |
49 |
50 |
51 |
52 |
53 |
54 | );
55 | }
56 | }
57 |
58 | Login.propTypes = {
59 | actions: PropTypes.object.isRequired,
60 | showNotification: PropTypes.func.isRequired
61 | };
62 |
63 | const mapStateToProps = state => ({
64 | isAuthenticated: state.auth.isAuthenticated
65 | });
66 |
67 | const mapDispatchToProps = (dispatch) => ({
68 | actions: bindActionCreators(actions, dispatch),
69 | showNotification: bindActionCreators(showNotification, dispatch)
70 | });
71 |
72 | export default connect(mapStateToProps, mapDispatchToProps)(Login);
73 |
--------------------------------------------------------------------------------
/src/components/Auth/style.scss:
--------------------------------------------------------------------------------
1 | @import '../globals';
2 |
3 | hgroup {
4 | text-align:center;
5 | margin-top: 8rem;
6 |
7 | h3 {
8 | color: $appbar-color;
9 | }
10 |
11 | .subtitle {
12 | margin-top: 1rem;
13 | color: $coral;
14 | font-weight: 200;
15 | }
16 | }
17 |
18 | .group {
19 | position: relative;
20 | margin-bottom: 2rem;
21 | }
22 |
23 | .dashboardCard {
24 | width: 40rem;
25 | margin: 4em auto;
26 | padding: 3em 2em 2em 2em;
27 | }
28 |
29 | .cardActions {
30 | padding-top: 2rem;
31 | justify-content: flex-end;
32 | }
--------------------------------------------------------------------------------
/src/components/Comments/CommentForm.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { browserHistory } from 'react-router';
3 | import Input from 'react-toolbox/lib/input';
4 | import { Card, CardTitle } from 'react-toolbox/lib/card';
5 | import { Button } from 'react-toolbox/lib/button';
6 | import classnames from 'classnames';
7 | import style from './style.scss'; // eslint-disable-line
8 |
9 | const CommentForm = ({ comment, onSave, onChange, onDelete, saving, errors }) => {
10 |
11 | return (
12 |
13 |
14 |
15 |
19 |
20 |
47 |
48 | );
49 | };
50 |
51 | CommentForm.propTypes = {
52 | comment: React.PropTypes.object,
53 | onSave: React.PropTypes.func.isRequired,
54 | onChange: React.PropTypes.func.isRequired,
55 | onDelete: React.PropTypes.func.isRequired,
56 | saving: React.PropTypes.bool,
57 | errors: React.PropTypes.object
58 | };
59 |
60 | export default CommentForm;
61 |
--------------------------------------------------------------------------------
/src/components/Comments/CommentList.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { browserHistory } from 'react-router';
3 | import { Card, CardText } from 'react-toolbox/lib/card';
4 | import { List, ListItem, ListSubHeader } from 'react-toolbox/lib/list';
5 |
6 | const CommentList = ({ comments }) => {
7 |
8 | return (
9 |
10 | {(comments.length > 0 ?
11 | (
12 |
13 |
14 | {comments.map(comment =>
15 | browserHistory.push('/comments/' + comment.id)}
20 | rightIcon="assignment" />
21 | )}
22 |
23 |
24 | ) :
25 | No Comments yet!
26 | )}
27 |
28 | );
29 | };
30 |
31 | CommentList.propTypes = {
32 | comments: PropTypes.array.isRequired
33 | };
34 |
35 | export default CommentList;
36 |
--------------------------------------------------------------------------------
/src/components/Comments/CommentMain.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { browserHistory } from 'react-router';
3 | import { Button } from 'react-toolbox/lib/button';
4 | import classnames from 'classnames';
5 | import CommentList from './CommentList';
6 | import style from './style.scss'; // eslint-disable-line
7 |
8 | const Comments = ({ comments }) => {
9 |
10 | return (
11 |
12 |
13 |
14 |
Comments
15 |
16 |
17 |
19 |
20 |
25 |
26 | );
27 | };
28 |
29 | Comments.propTypes = {
30 | comments: PropTypes.array.isRequired
31 | };
32 |
33 | export default Comments;
34 |
--------------------------------------------------------------------------------
/src/components/Comments/CommentPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { connect } from 'react-redux';
3 | import { bindActionCreators } from 'redux';
4 | import * as actions from '../../actions/commentActions';
5 | import CommentMain from './CommentMain';
6 |
7 | class CommentsPage extends Component {
8 | constructor(props) {
9 | super(props);
10 | }
11 |
12 | componentWillMount() {
13 | const { listComments } = this.props.actions;
14 | listComments();
15 | }
16 |
17 | render() {
18 | const { comments } = this.props;
19 |
20 | return (
21 |
22 | );
23 | }
24 | }
25 |
26 | CommentsPage.propTypes = {
27 | actions: PropTypes.object.isRequired,
28 | comments: PropTypes.array.isRequired
29 | };
30 |
31 | const mapStateToProps = (state) => ({
32 | comments: state.comments
33 | });
34 |
35 | const mapDispatchToProps = (dispatch) => ({
36 | actions: bindActionCreators(actions, dispatch)
37 | });
38 |
39 | export default connect(mapStateToProps, mapDispatchToProps)(CommentsPage);
40 |
--------------------------------------------------------------------------------
/src/components/Comments/ManageCommentPage.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { connect } from 'react-redux';
3 | import { bindActionCreators } from 'redux';
4 | import { browserHistory } from 'react-router';
5 | import * as actions from '../../actions/commentActions';
6 | import { showNotification } from '../../actions/notificationActions';
7 | import CommentForm from './CommentForm';
8 | import Comment from '../../models/Comment';
9 |
10 | class ManageCommentPage extends React.Component {
11 | constructor(props) {
12 | super(props);
13 |
14 | this.state = {
15 | comment: Object.assign({}, props.comment),
16 | errors: {},
17 | saving: false
18 | };
19 |
20 | this.handleChange = this.handleChange.bind(this);
21 | this.saveComment = this.saveComment.bind(this);
22 | this.deleteComment = this.deleteComment.bind(this);
23 | }
24 |
25 | componentWillMount() {
26 | const { listComments } = this.props.actions;
27 |
28 | if (!this.state.comments) {
29 | listComments();
30 | }
31 | }
32 |
33 | componentWillReceiveProps(nextProps) {
34 | if (nextProps.comment !== null && this.props.comment.id !== nextProps.comment.id) {
35 | // Necessary to populate form when an existing comment is loaded
36 | this.setState({ comment: Object.assign({}, nextProps.comment) });
37 | }
38 | }
39 |
40 | handleChange(value, event) {
41 | const field = event.target.name;
42 | let comment = this.state.comment;
43 | comment[field] = value;
44 | return this.setState({ comment: comment });
45 | }
46 |
47 | saveComment(event) {
48 | event.preventDefault();
49 |
50 | this.setState({ saving: true });
51 |
52 | this.props.actions.saveComment(this.state.comment)
53 | .then(() => {
54 | this.props.showNotification('Comment saved successfully');
55 | browserHistory.push('/comments');
56 | })
57 | .catch(error => {
58 | this.setState({ saving: false });
59 | this.props.showNotification(error.message);
60 | });
61 | }
62 |
63 | deleteComment(event) {
64 | event.preventDefault();
65 |
66 | this.setState({ saving: true });
67 |
68 | this.props.actions.deleteComment(this.state.comment)
69 | .then(() => {
70 | this.setState({ saving: false });
71 | this.props.showNotification('Comment deleted successfully');
72 | browserHistory.push('/comments');
73 | })
74 | .catch(error => {
75 | this.setState({ saving: false });
76 | this.props.showNotification(error.message);
77 | });
78 | }
79 |
80 | render() {
81 | return (
82 |
92 | );
93 | }
94 | }
95 |
96 | ManageCommentPage.propTypes = {
97 | comment: PropTypes.object,
98 | actions: PropTypes.object.isRequired,
99 | showNotification: PropTypes.func.isRequired
100 | };
101 |
102 | const getCommentById = (comments, id) => {
103 | const comment = comments.filter(comment => comment.id == id);
104 | if (comment.length) return comment[0]; //since filter returns an array, have to grab the first.
105 | return null;
106 | };
107 |
108 | const mapStateToProps = (state, ownProps) => {
109 | const commentId = ownProps.params.id;
110 |
111 | let comment = new Comment();
112 |
113 | if (commentId && state.comments.length > 0) {
114 | comment = getCommentById(state.comments, commentId);
115 | }
116 |
117 | return {
118 | comment: comment
119 | };
120 | };
121 |
122 | const mapDispatchToProps = (dispatch) => ({
123 | actions: bindActionCreators(actions, dispatch),
124 | showNotification: bindActionCreators(showNotification, dispatch)
125 | });
126 |
127 | export default connect(mapStateToProps, mapDispatchToProps)(ManageCommentPage);
128 |
--------------------------------------------------------------------------------
/src/components/Comments/style.scss:
--------------------------------------------------------------------------------
1 | @import "./globals";
2 |
3 | .commentForm {
4 | padding: 1rem 1rem 1rem 1rem;
5 | }
6 |
7 | .toolbar {
8 | padding-bottom: 1rem;
9 | }
10 |
11 | .bottomOptions {
12 | margin-top: 2rem;
13 | }
--------------------------------------------------------------------------------
/src/components/Home/HomePage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import Welcome from './Welcome';
4 |
5 | export const HomePage = () => {
6 | return (
7 |
8 | );
9 | };
10 |
11 | export default connect()(HomePage);
12 |
--------------------------------------------------------------------------------
/src/components/Home/Welcome.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import style from './style.scss'; // eslint-disable-line
3 |
4 | const Welcome = () => (
5 |
6 |
7 |
8 |
Welcome to react-redux-starter
9 |
A React/Redux starter project with login and basic CRUD functionality in a Material flavor
10 |
11 |
12 |
13 | );
14 |
15 | export default Welcome;
16 |
--------------------------------------------------------------------------------
/src/components/Home/style.scss:
--------------------------------------------------------------------------------
1 | @import '../globals';
2 |
3 | .welcome {
4 | .title {
5 | margin-top: 3rem;
6 | color: $coral;
7 | }
8 |
9 | .subtitle {
10 | margin-top: 2rem;
11 | letter-spacing: 0.3em;
12 | color: $hit-grey;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/components/Main.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { connect } from 'react-redux';
3 | import { bindActionCreators } from 'redux';
4 | import { Panel } from 'react-toolbox';
5 | import TopAppBar from './TopAppBar';
6 | import SideNavigation from './SideNavigation';
7 | import MainContent from './MainContent';
8 | import Preloader from './common/Preloader';
9 | import Notifications from './Notifications';
10 | import { logoutUser } from '../actions/authActions';
11 |
12 | const Main = (props) => (
13 |
14 |
15 |
16 | {props.children}
17 |
18 |
19 |
20 | );
21 |
22 | Main.propTypes = {
23 | children: PropTypes.element,
24 | routes: PropTypes.array,
25 | isLoading: PropTypes.bool.isRequired,
26 | actions: PropTypes.object.isRequired,
27 | auth: PropTypes.object.isRequired
28 | };
29 |
30 | const mapStateToProps = (state) => ({
31 | isLoading: state.ajaxCallsInProgress > 0,
32 | auth: state.auth
33 | });
34 |
35 | const mapDispatchToProps = (dispatch) => ({
36 | actions: {
37 | logoutUser: bindActionCreators(logoutUser, dispatch)
38 | }
39 | });
40 |
41 | export default connect(mapStateToProps, mapDispatchToProps)(Main);
--------------------------------------------------------------------------------
/src/components/MainContent/index.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import 'react-toolbox/lib/commons.scss';
3 | import Breadcrumbs from 'react-breadcrumbs';
4 | import style from './style.scss'; // eslint-disable-line
5 |
6 | const MainContent = (props) => (
7 |
8 |
9 |
10 |
11 |
12 | {props.children}
13 |
14 |
15 | );
16 |
17 | MainContent.propTypes = {
18 | children: PropTypes.element,
19 | routes: PropTypes.array
20 | };
21 |
22 | export default MainContent;
23 |
--------------------------------------------------------------------------------
/src/components/MainContent/style.scss:
--------------------------------------------------------------------------------
1 | @import "./globals";
2 |
3 | .mainPage {
4 | margin-top: $appbar-height;
5 | margin-left: $navigation-width;
6 | }
7 |
8 | .mainContent {
9 | padding: 2rem 2rem 2rem 2rem;
10 | }
11 |
12 | .mainBreadcrumbs {
13 | padding-bottom: 2rem;
14 | color: $hit-grey;
15 |
16 | a {
17 | transition: color .4s;
18 | color: $appbar-color;
19 | }
20 | a:link, a:visited { color: $appbar-color; }
21 | a:active, a:hover { color: $ebony; }
22 | }
--------------------------------------------------------------------------------
/src/components/Notifications/index.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { bindActionCreators } from 'redux';
3 | import { connect } from 'react-redux';
4 | import { Snackbar } from 'react-toolbox';
5 | import * as actions from '../../actions/notificationActions';
6 | import style from './style.scss'; // eslint-disable-line
7 |
8 | class Notifications extends React.Component {
9 | constructor(props) {
10 | super(props);
11 |
12 | this.hideNotification = this.hideNotification.bind(this);
13 | }
14 |
15 | hideNotification() {
16 | this.props.actions.hideNotification();
17 | }
18 |
19 | render() {
20 | const { notifications } = this.props;
21 |
22 | return (
23 | this.hideNotification()}
29 | />
30 | );
31 | }
32 | }
33 |
34 | Notifications.propTypes = {
35 | notifications: PropTypes.object.isRequired,
36 | actions: PropTypes.object.isRequired
37 | };
38 |
39 | const mapStateToProps = (state) => ({
40 | notifications: state.notifications
41 | });
42 |
43 | const mapDispatchToProps = (dispatch) => ({
44 | actions: bindActionCreators(actions, dispatch)
45 | });
46 |
47 | export default connect(mapStateToProps, mapDispatchToProps)(Notifications);
--------------------------------------------------------------------------------
/src/components/Notifications/style.scss:
--------------------------------------------------------------------------------
1 | .notificationSnackbar {
2 | width: 60%;
3 | text-align: center;
4 | }
--------------------------------------------------------------------------------
/src/components/PageNotFound.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router';
3 | import { Button } from 'react-toolbox/lib/button';
4 | import style from './style.scss'; // eslint-disable-line
5 |
6 | const PageNotFound = () => {
7 | return (
8 |
9 |
10 |
Page Not Found
11 |
12 |
13 |
14 |
15 |
16 | );
17 | };
18 |
19 | export default PageNotFound;
20 |
--------------------------------------------------------------------------------
/src/components/SideNavigation/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { List, ListItem } from 'react-toolbox';
3 | import { Link, IndexLink } from 'react-router';
4 | import classnames from 'classnames';
5 | import style from './style.scss'; // eslint-disable-line
6 |
7 | const SideNavigation = () => {
8 |
9 | const components = {
10 | comments: {
11 | name: 'Comments',
12 | path: '/comments',
13 | icon: 'assignment'
14 | }
15 | };
16 |
17 | const drawerItems = Object.keys(components).map((key) => {
18 | return (
19 |
20 |
26 |
27 | );
28 | });
29 |
30 | return (
31 |
43 | );
44 | };
45 |
46 | export default SideNavigation;
47 |
--------------------------------------------------------------------------------
/src/components/SideNavigation/style.scss:
--------------------------------------------------------------------------------
1 | @import '../globals';
2 |
3 | .root {
4 | display: flex;
5 | width: $navigation-width;
6 | flex-direction: column;
7 | background-color: $color-background;
8 | }
9 |
10 | .navigation {
11 | position: fixed;
12 | top: $appbar-height;
13 | bottom: 0;
14 | left: 0;
15 | z-index: $z-index-highest;
16 | box-shadow: $documentation-left-shadow;
17 | transition: transform $animation-duration $animation-curve-default;
18 | }
19 |
20 | .list {
21 | @include no-webkit-scrollbar;
22 | flex-grow: 1;
23 | overflow-y: auto;
24 | }
25 |
26 | .item {
27 | > span{
28 | padding: $navigation-v-padding $navigation-h-padding;
29 | }
30 | [data-react-toolbox="list-item-text"] {
31 | font-size: $font-size-small;
32 | font-weight: $font-weight-semi-bold;
33 | }
34 | }
35 |
36 | .active {
37 | background: $color-divider;
38 |
39 | span:before {
40 | position: absolute;
41 | bottom: 0;
42 | left: 0;
43 | display: block;
44 | width: .3rem;
45 | height: 100%;
46 | content: '';
47 | background-color: $color-primary;
48 | }
49 | }
50 |
51 | .footer {
52 | flex-grow: 0;
53 | padding: $navigation-h-padding;
54 | overflow: hidden;
55 | text-align: center;
56 | font-size: $font-size-small;
57 | color: $color-text-secondary;
58 | border-top: $navigation-footer-border;
59 | > * {
60 | display: block;
61 | }
62 | }
63 |
64 | .footerTitle {
65 | color: $coral;
66 | font-weight: 500;
67 | padding-bottom: 0.5rem;
68 | }
--------------------------------------------------------------------------------
/src/components/TopAppBar/index.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { Link } from 'react-router';
3 | import { AppBar } from 'react-toolbox/lib/app_bar';
4 | import { IconMenu, MenuItem } from 'react-toolbox/lib/menu';
5 | import style from './style.scss'; // eslint-disable-line
6 |
7 | const TopAppBar = ({actions, auth}) => {
8 |
9 | const userName = auth.user.name;
10 |
11 | return (
12 |
13 |
14 | react-redux-starter
15 |
16 |
17 | {userName}
18 |
19 |
20 |
21 |
22 |
23 | );
24 | };
25 |
26 | TopAppBar.propTypes = {
27 | children: PropTypes.node,
28 | actions: PropTypes.object.isRequired,
29 | auth: PropTypes.object.isRequired
30 | };
31 |
32 | export default TopAppBar;
33 |
--------------------------------------------------------------------------------
/src/components/TopAppBar/style.scss:
--------------------------------------------------------------------------------
1 | @import "../globals";
2 |
3 | .appbar {
4 | z-index: $z-index-higher;
5 | display: flex;
6 | min-height: $appbar-height;
7 | flex-direction: row;
8 | align-items: center;
9 | justify-content: flex-start;
10 | box-shadow: $appbar-shadow;
11 | background-color: $appbar-color;
12 | }
13 |
14 | .appTitle {
15 | text-transform: uppercase;
16 | }
17 |
18 | .topBarOptions {
19 | flex-grow: 1;
20 | text-align: right;
21 | }
22 |
23 | .companySettings {
24 | flex-grow: 1;
25 | text-align: right;
26 |
27 | > span {
28 | text-transform: uppercase;
29 | font-size: 1.4rem;
30 | font-weight: 500;
31 | }
32 | }
33 |
34 | .menu {
35 | > div {
36 | margin-top: 4rem;
37 | margin-right: 1rem;
38 | }
39 |
40 | button > span {
41 | color: #ffffff;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/_globals.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/colors";
2 | @import "~react-toolbox/lib/globals";
3 | @import "~react-toolbox/lib/mixins";
4 |
5 | $unit: 1rem;
6 | $color-content: #fafafa;
7 | $navigation-width: 22 * $unit;
8 | $navigation-h-padding: 2.4 * $unit;
9 | $navigation-v-padding: 1.2 * $unit;
10 | $navigation-footer-border: solid 1px rgb(224, 224, 224);
11 | $documentation-left-shadow: 0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.2);
12 | $documentation-right-shadow: -2px 0 4px rgba(0,0,0,.14);
13 |
14 | $appbar-height: 6.4 * $unit;
15 | $appbar-logo-size: 15 * $unit;
16 | $appbar-shadow: 0 1px rgba(255,255,255,.65);
17 | $appbar-navigation-offset: 6.5 * $unit;
18 |
19 | $appbar-color: #37474F;
20 | $white-smoke: #F6F6F6;
21 | $ebony: #2E3339;
22 | $very-light-grey: #CCCCCC;
23 | $coral: #FD7348;
24 | $hit-grey: #ABACAC;
25 | $pattens-blue: #D7E8F7;
26 |
--------------------------------------------------------------------------------
/src/components/common/Preloader.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import ProgressBar from 'react-toolbox/lib/progress_bar';
3 | import style from './style.scss';
4 |
5 | class Preloader extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | }
9 |
10 | render() {
11 | const { isLoading } = this.props;
12 |
13 | if (!isLoading) {
14 | return false;
15 | }
16 |
17 | return (
18 |
23 | );
24 | }
25 | }
26 |
27 | Preloader.propTypes = {
28 | isLoading: PropTypes.bool.isRequired
29 | };
30 |
31 | export default Preloader;
32 |
--------------------------------------------------------------------------------
/src/components/common/style.scss:
--------------------------------------------------------------------------------
1 | @import '../globals';
2 |
3 | .showbox {
4 | position: absolute;
5 | top: 0;
6 | bottom: 0;
7 | left: 0;
8 | right: 0;
9 | z-index: 1000001;
10 | height: 100%;
11 | width: 100%;
12 | background: none repeat scroll 0 0 black;
13 | position: fixed;
14 | display: block;
15 | opacity: 0.5;
16 | }
17 |
18 | .loader {
19 | position: relative;
20 | top: $appbar-height - 1rem;
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/style.scss:
--------------------------------------------------------------------------------
1 | @import "./globals";
2 |
3 | .pageNotFound {
4 | > p {
5 | font-size: 2.4rem;
6 | font-weight: 400;
7 | padding-bottom: 2rem;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/components/theme/_config.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/colors";
2 |
3 | $color-primary: $palette-deep-orange-500;
4 | $color-primary-dark: $palette-deep-orange-600;
5 | $color-accent: $palette-blue-grey-600;
6 | $color-accent-dark: $palette-blue-grey-700;
7 | $color-primary-contrast: $color-dark-contrast;
8 | $color-accent-contrast: $color-dark-contrast;
--------------------------------------------------------------------------------
/src/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | // AUTH
2 | export const LOGIN_REQUEST = 'LOGIN_REQUEST';
3 | export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
4 | export const LOGIN_FAILURE = 'LOGIN_FAILURE';
5 | export const LOGOUT_REQUEST = 'LOGOUT_REQUEST';
6 | export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
7 | export const LOGOUT_FAILURE = 'LOGOUT_FAILURE';
8 |
9 | // AJAX
10 | export const BEGIN_AJAX_CALL = 'BEGIN_AJAX_CALL';
11 | export const AJAX_CALL_ERROR = 'AJAX_CALL_ERROR';
12 |
13 | // COMMENTS
14 | export const LIST_COMMENTS_SUCCESS = 'LIST_COMMENTS_SUCCESS';
15 | export const CREATE_COMMENT_SUCCESS = 'CREATE_COMMENT_SUCCESS';
16 | export const UPDATE_COMMENT_SUCCESS = 'UPDATE_COMMENT_SUCCESS';
17 | export const DELETE_COMMENT_SUCCESS = 'DELETE_COMMENT_SUCCESS';
18 |
19 | // NOTIFICATIONS
20 | export const SHOW_NOTIFICATION = 'SHOW_NOTIFICATION';
21 | export const HIDE_NOTIFICATION = 'HIDE_NOTIFICATION';
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rjmreis/react-redux-starter/d87e7ab57c6404f9140b518c6576708b9bcca7af/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 | react-redux-starter
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/default */
2 | import React from 'react';
3 | import { render } from 'react-dom';
4 | import { Provider } from 'react-redux';
5 | import { Router, browserHistory } from 'react-router';
6 | import { syncHistoryWithStore } from 'react-router-redux';
7 | import routes from './routes';
8 | import configureStore from './store/configureStore';
9 | import './style.scss';
10 |
11 | const store = configureStore();
12 | const history = syncHistoryWithStore(browserHistory, store);
13 |
14 | render(
15 |
16 |
17 | ,
18 | document.getElementById('app')
19 | );
20 |
--------------------------------------------------------------------------------
/src/models/Comment.js:
--------------------------------------------------------------------------------
1 | export default class Comment {
2 | constructor() {
3 | this.title = '';
4 | this.description = '';
5 | }
6 | }
--------------------------------------------------------------------------------
/src/models/User.js:
--------------------------------------------------------------------------------
1 | import validate from 'validate.js';
2 |
3 | export default class User {
4 | constructor() {
5 | this.username = '';
6 | this.password = '';
7 |
8 | this.constraints = {
9 | username: {
10 | presence: true
11 | },
12 | password: {
13 | presence: true
14 | }
15 | };
16 | }
17 |
18 | isValid() {
19 | return validate(this, this.constraints) === undefined;
20 | }
21 |
22 | getError(key) {
23 | let message = validate({ [key]: this[key] }, this.constraints);
24 |
25 | return message[key] ? message[key][0] : '';
26 | }
27 | }
--------------------------------------------------------------------------------
/src/reducers/ajaxStatusReducer.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/actionTypes';
2 | import initialState from './initialState';
3 |
4 | function actionTypeEndsInSuccess(type) {
5 | return type.substring(type.length - 8) === '_SUCCESS';
6 | }
7 |
8 | export default function ajaxStatusReducer(state = initialState.ajaxCallsInProgress, action) {
9 | if (action.type === types.BEGIN_AJAX_CALL) {
10 | return state + 1;
11 | } else if (action.type === types.AJAX_CALL_ERROR || actionTypeEndsInSuccess(action.type)) {
12 | return state - 1;
13 | }
14 |
15 | return state;
16 | }
17 |
--------------------------------------------------------------------------------
/src/reducers/authReducer.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/actionTypes';
2 | import initialState from './initialState';
3 |
4 | export default function auth(state = initialState.auth, action) {
5 | switch (action.type) {
6 | case types.LOGIN_REQUEST:
7 | return Object.assign({}, state, {
8 | isAuthenticated: false
9 | });
10 | case types.LOGIN_SUCCESS:
11 | return Object.assign({}, state, {
12 | isAuthenticated: true,
13 | user: action.user,
14 | errorMessage: ''
15 | });
16 | case types.LOGIN_FAILURE:
17 | return Object.assign({}, state, {
18 | isAuthenticated: false,
19 | errorMessage: action.message
20 | });
21 | case types.LOGOUT_SUCCESS:
22 | return Object.assign({}, state, {
23 | isAuthenticated: false,
24 | user: {}
25 | });
26 | default:
27 | return state;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/reducers/commentReducer.js:
--------------------------------------------------------------------------------
1 | // import objectAssign from 'object-assign';
2 | import * as types from '../constants/actionTypes';
3 | import initialState from './initialState';
4 |
5 | // IMPORTANT: Note that with Redux, state should NEVER be changed.
6 | // State is considered immutable. Instead,
7 | // create a copy of the state passed and set new values on the copy.
8 | // Note the use of the spread operator and Object.assign to create a copy of current state.
9 | export default function commentsReducer(state = initialState.comments, action) {
10 | switch (action.type) {
11 | case types.LIST_COMMENTS_SUCCESS:
12 | return action.comments;
13 |
14 | case types.CREATE_COMMENT_SUCCESS:
15 | return [...state, Object.assign({}, action.comment)];
16 |
17 | case types.UPDATE_COMMENT_SUCCESS:
18 | return [...state.filter(comment => comment.id !== action.comment.id), Object.assign({}, action.comment)];
19 |
20 | case types.DELETE_COMMENT_SUCCESS: {
21 | return state.filter(comment => comment.id !== action.commentId);
22 | }
23 |
24 | default:
25 | return state;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import { routerReducer } from 'react-router-redux';
3 | import authReducer from './authReducer';
4 | import commentReducer from './commentReducer';
5 | import ajaxStatusReducer from './ajaxStatusReducer';
6 | import notificationsReducer from './notificationsReducer';
7 |
8 | const rootReducer = combineReducers({
9 | routing: routerReducer,
10 | auth: authReducer,
11 | comments: commentReducer,
12 | ajaxCallsInProgress: ajaxStatusReducer,
13 | notifications: notificationsReducer
14 | });
15 |
16 | export default rootReducer;
--------------------------------------------------------------------------------
/src/reducers/initialState.js:
--------------------------------------------------------------------------------
1 | export default {
2 | auth: {
3 | isAuthenticated: localStorage.getItem('id_token') ? true : false,
4 | user: localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : {}
5 | },
6 | comments: [],
7 | ajaxCallsInProgress: 0,
8 | notifications: {
9 | active: false,
10 | message: ''
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/src/reducers/notificationsReducer.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/actionTypes';
2 | import initialState from './initialState';
3 |
4 | export default function notificationsReducer(state = initialState.notifications, action) {
5 | if (action.type === types.SHOW_NOTIFICATION) {
6 | return { active: true, message: action.message };
7 | } else if (action.type === types.HIDE_NOTIFICATION) {
8 | return { active: false, message: state.message };
9 | }
10 |
11 | return state;
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-named-as-default */
2 |
3 | import React from 'react';
4 | import { Route, IndexRoute } from 'react-router';
5 |
6 | import App from './components/App.js';
7 | import HomePage from './components/Home/HomePage.js';
8 | import CommentPage from './components/Comments/CommentPage.js';
9 | import ManageCommentPage from './components/Comments/ManageCommentPage.js';
10 | import PageNotFound from './components/PageNotFound.js';
11 |
12 | export default (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 |
--------------------------------------------------------------------------------
/src/store/configureStore.dev.js:
--------------------------------------------------------------------------------
1 | // This file merely configures the store for hot reloading.
2 | // This boilerplate file is likely to be the same for each project that uses Redux.
3 | // With Redux, the actual stores are in /reducers.
4 |
5 | import { createStore, compose, applyMiddleware } from 'redux';
6 | import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
7 | import thunkMiddleware from 'redux-thunk';
8 | import rootReducer from '../reducers';
9 |
10 | export default function configureStore(initialState) {
11 | const middewares = [
12 | // Add other middleware on this line...
13 |
14 | // Redux middleware that spits an error on you when you try to mutate your state either inside a dispatch or between dispatches.
15 | reduxImmutableStateInvariant(),
16 |
17 | // thunk middleware can also accept an extra argument to be passed to each thunk action
18 | // https://github.com/gaearon/redux-thunk#injecting-a-custom-argument
19 | thunkMiddleware
20 | ];
21 |
22 | const store = createStore(rootReducer, initialState, compose(
23 | applyMiddleware(...middewares),
24 | window.devToolsExtension ? window.devToolsExtension() : f => f // add support for Redux dev tools
25 | )
26 | );
27 |
28 | if (module.hot) {
29 | // Enable Webpack hot module replacement for reducers
30 | module.hot.accept('../reducers', () => {
31 | const nextReducer = require('../reducers').default; // eslint-disable-line global-require
32 | store.replaceReducer(nextReducer);
33 | });
34 | }
35 |
36 | return store;
37 | }
--------------------------------------------------------------------------------
/src/store/configureStore.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production') {
2 | module.exports = require('./configureStore.prod');
3 | } else {
4 | module.exports = require('./configureStore.dev');
5 | }
6 |
--------------------------------------------------------------------------------
/src/store/configureStore.prod.js:
--------------------------------------------------------------------------------
1 | import { createStore, compose, applyMiddleware } from 'redux';
2 | import thunkMiddleware from 'redux-thunk';
3 | import rootReducer from '../reducers';
4 |
5 | export default function configureStore(initialState) {
6 | const middewares = [
7 | // Add other middleware on this line...
8 |
9 | // thunk middleware can also accept an extra argument to be passed to each thunk action
10 | // https://github.com/gaearon/redux-thunk#injecting-a-custom-argument
11 | thunkMiddleware,
12 | ];
13 |
14 | return createStore(rootReducer, initialState, compose(
15 | applyMiddleware(...middewares)
16 | )
17 | );
18 | }
--------------------------------------------------------------------------------
/src/style.scss:
--------------------------------------------------------------------------------
1 | @import './components/globals';
2 |
3 | body {
4 | background: $white-smoke;
5 | }
6 |
--------------------------------------------------------------------------------
/src/utils/ajax.js:
--------------------------------------------------------------------------------
1 | import { ajaxCallError } from '../actions/ajaxStatusActions';
2 |
3 | export const handleAjaxError = (dispatch, error) => {
4 | dispatch(ajaxCallError(error));
5 | };
6 |
--------------------------------------------------------------------------------
/src/utils/dateHelper.js:
--------------------------------------------------------------------------------
1 | export default class DateHelper {
2 | // See tests for desired format.
3 | static getFormattedDateTime(date = new Date()) {
4 | return `${date.getMonth() + 1}/${date.getDate()} ${date.getHours()}:${this.padLeadingZero(date.getMinutes())}:${this.padLeadingZero(date.getSeconds())}`;
5 | }
6 |
7 | static padLeadingZero(value) {
8 | return value > 9 ? value : `0${value}`;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/utils/dateHelper.spec.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import DateHelper from './dateHelper';
3 |
4 | describe('Date Helper', () => {
5 | describe('getFormattedDateTime', () => {
6 | it('returns mm/dd hh:mm:ss formatted time when passed a date', () => {
7 | // arrange
8 | // The 7 numbers specify the year, month, day, hour, minute, second, and millisecond, in that order
9 | const date = new Date(99, 0, 24, 11, 33, 30, 0);
10 |
11 | // assert
12 | expect(DateHelper.getFormattedDateTime(date)).to.equal('1/24 11:33:30');
13 | });
14 |
15 | it('pads single digit minute and second values with leading zeros', () => {
16 | // arrange
17 | // The 7 numbers specify the year, month, day, hour, minute, second, and millisecond, in that order
18 | const date = new Date(99, 0, 4, 11, 3, 2, 0);
19 |
20 | // assert
21 | expect(DateHelper.getFormattedDateTime(date)).to.equal('1/4 11:03:02');
22 | });
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/webpack-public-path.js:
--------------------------------------------------------------------------------
1 | // Dynamically set the webpack public path at runtime below
2 | // This magic global is used by webpack to set the public path at runtime.
3 | // The public path is set dynamically to avoid the following issues:
4 | // 1. https://github.com/coryhouse/react-slingshot/issues/205
5 | // 2. https://github.com/coryhouse/react-slingshot/issues/181
6 | // 3. https://github.com/coryhouse/react-slingshot/pull/125
7 | // Documentation: http://webpack.github.io/docs/configuration.html#output-publicpath
8 | // eslint-disable-next-line no-undef
9 | __webpack_public_path__ = window.location.protocol + "//" + window.location.host + "/";
10 |
--------------------------------------------------------------------------------
/tools/build.js:
--------------------------------------------------------------------------------
1 | // More info on Webpack's Node API here: https://webpack.github.io/docs/node.js-api.html
2 | // Allowing console calls below since this is a build file.
3 | /* eslint-disable no-console */
4 | import webpack from 'webpack';
5 | import config from '../webpack.config.prod';
6 | import { chalkError, chalkSuccess, chalkWarning, chalkProcessing } from './chalkConfig';
7 |
8 | process.env.NODE_ENV = 'production'; // this assures React is built in prod mode and that the Babel dev config doesn't apply.
9 |
10 | console.log(chalkProcessing('Generating minified bundle for production via Webpack. This will take a moment...'));
11 |
12 | webpack(config).run((error, stats) => {
13 | if (error) { // so a fatal error occurred. Stop here.
14 | console.log(chalkError(error));
15 | return 1;
16 | }
17 |
18 | const jsonStats = stats.toJson();
19 |
20 | if (jsonStats.hasErrors) {
21 | return jsonStats.errors.map(error => console.log(chalkError(error)));
22 | }
23 |
24 | if (jsonStats.hasWarnings) {
25 | console.log(chalkWarning('Webpack generated the following warnings: '));
26 | jsonStats.warnings.map(warning => console.log(chalkWarning(warning)));
27 | }
28 |
29 | console.log(`Webpack stats: ${stats}`);
30 |
31 | console.log(chalkSuccess('Your app is compiled in production mode in /dist. It\'s ready to roll!'));
32 |
33 | return 0;
34 | });
35 |
--------------------------------------------------------------------------------
/tools/chalkConfig.js:
--------------------------------------------------------------------------------
1 | // Centralized configuration for chalk, which is used to add color to console.log statements.
2 | import chalk from 'chalk';
3 | export const chalkError = chalk.red;
4 | export const chalkSuccess = chalk.green;
5 | export const chalkWarning = chalk.yellow;
6 | export const chalkProcessing = chalk.blue;
7 |
--------------------------------------------------------------------------------
/tools/distServer.js:
--------------------------------------------------------------------------------
1 | // This file configures a web server for testing the production build
2 | // on your local machine.
3 |
4 | import browserSync from 'browser-sync'; // eslint-disable-line
5 | import historyApiFallback from 'connect-history-api-fallback';
6 | import {chalkProcessing} from './chalkConfig';
7 |
8 | /* eslint-disable no-console */
9 |
10 | console.log(chalkProcessing('Opening production build...'));
11 |
12 | // Run Browsersync
13 | browserSync({
14 | port: process.env.PORT || 3000,
15 | ui: {
16 | port: process.env.UI || 3001
17 | },
18 | server: {
19 | baseDir: 'dist'
20 | },
21 |
22 | files: [
23 | 'src/*.html'
24 | ],
25 |
26 | middleware: [historyApiFallback()]
27 | });
28 |
--------------------------------------------------------------------------------
/tools/srcServer.js:
--------------------------------------------------------------------------------
1 | // This file configures the development web server
2 | // which supports hot reloading and synchronized testing.
3 |
4 | // Require Browsersync along with webpack and middleware for it
5 | import browserSync from 'browser-sync'; // eslint-disable-line
6 | // Required for react-router browserHistory
7 | // see https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-102623643
8 | import historyApiFallback from 'connect-history-api-fallback';
9 | import webpack from 'webpack';
10 | import webpackDevMiddleware from 'webpack-dev-middleware';
11 | import webpackHotMiddleware from 'webpack-hot-middleware';
12 | import config from '../webpack.config.dev';
13 |
14 | const bundler = webpack(config);
15 |
16 | // Run Browsersync and use middleware for Hot Module Replacement
17 | browserSync({
18 | port: 3000,
19 | ui: {
20 | port: 3001
21 | },
22 | server: {
23 | baseDir: 'src',
24 |
25 | middleware: [
26 | historyApiFallback(),
27 |
28 | webpackDevMiddleware(bundler, {
29 | // Dev middleware can't access config, so we provide publicPath
30 | publicPath: config.output.publicPath,
31 |
32 | // These settings suppress noisy webpack output so only errors are displayed to the console.
33 | noInfo: false,
34 | quiet: false,
35 | stats: {
36 | assets: false,
37 | colors: true,
38 | version: false,
39 | hash: false,
40 | timings: false,
41 | chunks: false,
42 | chunkModules: false
43 | },
44 |
45 | // for other settings see
46 | // http://webpack.github.io/docs/webpack-dev-middleware.html
47 | }),
48 |
49 | // bundler should be the same as above
50 | webpackHotMiddleware(bundler)
51 | ]
52 | },
53 |
54 | // no need to watch '*.js' here, webpack will take care of it for us,
55 | // including full page reloads if HMR won't work
56 | files: [
57 | 'src/*.html'
58 | ]
59 | });
60 |
--------------------------------------------------------------------------------
/tools/startMessage.js:
--------------------------------------------------------------------------------
1 | import { chalkSuccess } from './chalkConfig';
2 |
3 | /* eslint-disable no-console */
4 |
5 | console.log(chalkSuccess('Starting app in dev mode...'));
6 |
--------------------------------------------------------------------------------
/tools/testSetup.js:
--------------------------------------------------------------------------------
1 | // Tests are placed alongside files under test.
2 | // This file does the following:
3 | // 1. Sets the environment to 'test' so that
4 | // dev-specific babel config in .babelrc doesn't run.
5 | // 2. Disables Webpack-specific features that Mocha doesn't understand.
6 | // 3. Registers babel for transpiling our code for testing.
7 |
8 | // This assures the .babelrc dev config (which includes
9 | // hot module reloading code) doesn't apply for tests.
10 | // Setting NODE_ENV to test instead of production because setting it to production will suppress error messaging
11 | // and propType validation warnings.
12 | process.env.NODE_ENV = 'test';
13 |
14 | // Disable webpack-specific features for tests since
15 | // Mocha doesn't know what to do with them.
16 | ['.css', '.scss', '.png', '.jpg'].forEach(ext => {
17 | require.extensions[ext] = () => null;
18 | });
19 |
20 | // Register babel so that it will transpile ES6 to ES5
21 | // before our tests run.
22 | require('babel-register')();
23 |
--------------------------------------------------------------------------------
/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | import webpack from 'webpack';
3 | import HtmlWebpackPlugin from 'html-webpack-plugin';
4 | import autoprefixer from 'autoprefixer';
5 |
6 | export default {
7 | resolve: {
8 | extensions: ['', '.js', '.jsx'],
9 | modulesDirectories: [
10 | 'node_modules',
11 | path.resolve(__dirname, './node_modules')
12 | ]
13 | },
14 | debug: true,
15 | devtool: 'eval-source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
16 | noInfo: true, // set to false to see a list of every file being bundled.
17 | entry: [
18 | // must be first entry to properly set public path
19 | './src/webpack-public-path',
20 | 'webpack-hot-middleware/client?reload=true',
21 | './src/index'
22 | ],
23 | target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
24 | output: {
25 | path: `${__dirname}/src`, // Note: Physical files are only output by the production build task `npm run build`.
26 | publicPath: '/',
27 | filename: 'bundle.js'
28 | },
29 | plugins: [
30 | new webpack.DefinePlugin({
31 | 'process.env': {
32 | 'NODE_ENV': JSON.stringify('development'), // Tells React to build in either dev or prod modes. https://facebook.github.io/react/downloads.html (See bottom)
33 | 'API': JSON.stringify(process.env.API)
34 | },
35 | __DEV__: true
36 | }),
37 | new webpack.HotModuleReplacementPlugin(),
38 | new webpack.NoErrorsPlugin(),
39 | new HtmlWebpackPlugin({ // Create HTML file that includes references to bundled CSS and JS.
40 | template: 'src/index.ejs',
41 | minify: {
42 | removeComments: true,
43 | collapseWhitespace: true
44 | },
45 | inject: true
46 | })
47 | ],
48 | module: {
49 | loaders: [
50 | { test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel'] },
51 | { test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file' },
52 | { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?limit=10000&mimetype=application/font-woff" },
53 | { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' },
54 | { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' },
55 | { test: /\.(jpe?g|png|gif)$/i, loader: 'file?name=[name].[ext]' },
56 | { test: /\.ico$/, loader: 'file?name=[name].[ext]' },
57 | { test: /(\.css|\.scss)$/, loaders: ['style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', 'postcss', 'sass?sourceMap'] },
58 | { test: /\.json$/, exclude: /node_modules/, loader: 'json' },
59 | ]
60 | },
61 | postcss: () => [autoprefixer],
62 | sassLoader: {
63 | data: '@import "theme/_config.scss";',
64 | includePaths: [path.resolve(__dirname, './src/components')]
65 | }
66 | };
67 |
--------------------------------------------------------------------------------
/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | // For info about this file refer to webpack and webpack-hot-middleware documentation
2 | // For info on how we're generating bundles with hashed filenames for cache busting: https://medium.com/@okonetchnikov/long-term-caching-of-static-assets-with-webpack-1ecb139adb95#.w99i89nsz
3 | const path = require('path');
4 | import webpack from 'webpack';
5 | import ExtractTextPlugin from 'extract-text-webpack-plugin';
6 | import WebpackMd5Hash from 'webpack-md5-hash';
7 | import HtmlWebpackPlugin from 'html-webpack-plugin';
8 | import autoprefixer from 'autoprefixer';
9 |
10 | export default {
11 | resolve: {
12 | extensions: ['', '.js', '.jsx'],
13 | modulesDirectories: [
14 | 'node_modules',
15 | path.resolve(__dirname, './node_modules')
16 | ]
17 | },
18 | debug: true,
19 | devtool: 'source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
20 | noInfo: true, // set to false to see a list of every file being bundled.
21 | entry: './src/index',
22 | target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
23 | output: {
24 | path: `${__dirname}/dist`,
25 | publicPath: '/',
26 | filename: '[name].[chunkhash].js'
27 | },
28 | plugins: [
29 | // Hash the files using MD5 so that their names change when the content changes.
30 | new WebpackMd5Hash(),
31 |
32 | // Optimize the order that items are bundled. This assures the hash is deterministic.
33 | new webpack.optimize.OccurenceOrderPlugin(),
34 |
35 | // Tells React to build in prod mode. https://facebook.github.io/react/downloads.html
36 | new webpack.DefinePlugin({
37 | 'process.env': {
38 | 'NODE_ENV': JSON.stringify('production'), // Tells React to build in either dev or prod modes. https://facebook.github.io/react/downloads.html (See bottom)
39 | 'API': JSON.stringify(process.env.API)
40 | },
41 | __DEV__: false
42 | }),
43 |
44 | // Generate an external css file with a hash in the filename
45 | new ExtractTextPlugin('[name].[contenthash].css'),
46 |
47 | // Generate HTML file that contains references to generated bundles. See here for how this works: https://github.com/ampedandwired/html-webpack-plugin#basic-usage
48 | new HtmlWebpackPlugin({
49 | template: 'src/index.ejs',
50 | minify: {
51 | removeComments: true,
52 | collapseWhitespace: true,
53 | removeRedundantAttributes: true,
54 | useShortDoctype: true,
55 | removeEmptyAttributes: true,
56 | removeStyleLinkTypeAttributes: true,
57 | keepClosingSlash: true,
58 | minifyJS: true,
59 | minifyCSS: true,
60 | minifyURLs: true
61 | },
62 | inject: true
63 | }),
64 |
65 | // Eliminate duplicate packages when generating bundle
66 | new webpack.optimize.DedupePlugin(),
67 |
68 | // Minify JS
69 | new webpack.optimize.UglifyJsPlugin()
70 | ],
71 | module: {
72 | loaders: [
73 | { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel' },
74 | { test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'url?name=[name].[ext]' },
75 | { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?limit=10000&mimetype=application/font-woff&name=[name].[ext]" },
76 | { test: /\.ttf(\?v=\d+.\d+.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream&name=[name].[ext]' },
77 | { test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml&name=[name].[ext]' },
78 | { test: /\.(jpe?g|png|gif)$/i, loader: 'file?name=[name].[ext]' },
79 | { test: /\.ico$/, loader: 'file?name=[name].[ext]' },
80 | { test: /(\.css|\.scss)$/, loader: ExtractTextPlugin.extract('css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?sourceMap') }
81 | ]
82 | },
83 | postcss: () => [autoprefixer],
84 | sassLoader: {
85 | data: '@import "theme/_config.scss";',
86 | includePaths: [path.resolve(__dirname, './src/components')]
87 | }
88 | };
89 |
--------------------------------------------------------------------------------