├── .editorconfig
├── .env.development
├── .env.production
├── .eslintignore
├── .eslintrc.js
├── .github
├── CODE_OF_CONDUCT.md
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.VN.md
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
└── manifest.json
├── server.js
├── server
└── routes
│ └── index.js
├── src
├── actions
│ ├── action-types.js
│ └── index.js
├── components
│ ├── common
│ │ └── loading
│ │ │ ├── Loading.jsx
│ │ │ └── Loading.scss
│ ├── layout
│ │ ├── App.jsx
│ │ ├── App.scss
│ │ ├── App.test.js
│ │ ├── body
│ │ │ ├── Body.jsx
│ │ │ └── Body.scss
│ │ ├── footer
│ │ │ ├── Footer.jsx
│ │ │ └── Footer.scss
│ │ └── header
│ │ │ ├── Header.jsx
│ │ │ └── Header.scss
│ └── pages
│ │ ├── demo-animate-css
│ │ ├── DemoAnimateCss.jsx
│ │ └── DemoAnimateCss.scss
│ │ ├── demo-bootstrap
│ │ └── DemoBootstrap.jsx
│ │ ├── demo-jquery
│ │ ├── DemoJquery.jsx
│ │ └── DemoJquery.scss
│ │ ├── demo-loadable-component
│ │ ├── DemoLoadableComponent.jsx
│ │ └── LoadableDemoComponent.jsx
│ │ ├── demo-react-reveal
│ │ └── DemoReactReveal.jsx
│ │ ├── demo-react-router
│ │ ├── DemoReactRouter.jsx
│ │ ├── Images.jsx
│ │ ├── LoadableImage.jsx
│ │ ├── Text.jsx
│ │ ├── UserList.jsx
│ │ └── UserProfile.jsx
│ │ ├── demo-react-scrollchor
│ │ ├── DemoReactScrollchor.jsx
│ │ └── DemoReactScrollchor.scss
│ │ ├── demo-react-table
│ │ ├── DemoReactTable.jsx
│ │ ├── ModalEditTodo.jsx
│ │ └── style.scss
│ │ ├── demo-reactstrap
│ │ └── DemoReactstrap.jsx
│ │ ├── demo-redux
│ │ ├── DemoRedux.jsx
│ │ ├── FormAddItem.jsx
│ │ └── ItemTable.jsx
│ │ └── lifecycle-component.jsx
├── environments
│ ├── env.development.js
│ ├── env.production.js
│ └── index.js
├── index.js
├── lib
│ ├── animate.css.js
│ ├── bootstrap.js
│ ├── font-awesome.js
│ ├── index.js
│ └── jquery.js
├── reducers
│ ├── index.js
│ ├── items.js
│ ├── todos.js
│ └── users.js
├── registerServiceWorker.js
├── services
│ ├── auth-service.js
│ ├── db-service.js
│ └── util-service.js
└── styles
│ ├── _animate.scss
│ ├── _classes.scss
│ ├── _mixins.scss
│ ├── _variables.scss
│ └── index.scss
├── test.js
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # Howto with your editor: http://editorconfig.org/#download
4 | # Sublime: https://github.com/sindresorhus/editorconfig-sublime
5 |
6 | # top-most EditorConfig file
7 | root = true
8 |
9 | # Unix-style newlines with a newline ending every file
10 | [**]
11 | end_of_line = lf
12 | insert_final_newline = true
13 |
14 | # Standard at: https://github.com/felixge/node-style-guide
15 | [**.{js,json,jsx}]
16 | trim_trailing_whitespace = true
17 | indent_style = space
18 | indent_size = 2
19 | quote_type = single
20 | curly_bracket_next_line = false
21 | spaces_around_operators = true
22 | space_after_control_statements = true
23 | space_after_anonymous_functions = true
24 | spaces_in_brackets = false
25 |
26 | # No Standard. Please document a standard if different from .js
27 | [**.{yml,css,scss}]
28 | trim_trailing_whitespace = true
29 | indent_style = tab
30 | indent_size = 2
31 |
32 | [**.html]
33 | trim_trailing_whitespace = true
34 | indent_style = space
35 | indent_size = 2
36 |
37 | # No standard. Please document a standard if different from .js
38 | [**.md]
39 | indent_style = tab
40 |
41 | # Standard at:
42 | [Makefile]
43 | indent_style = tab
44 |
45 | # The indentation in package.json will always need to be 2 spaces
46 | # https://github.com/npm/npm/issues/4718
47 | [{package, bower}.json]
48 | indent_style = space
49 | indent_size = 2
50 |
--------------------------------------------------------------------------------
/.env.development:
--------------------------------------------------------------------------------
1 | REACT_APP_ENV=development
--------------------------------------------------------------------------------
/.env.production:
--------------------------------------------------------------------------------
1 | REACT_APP_ENV=production
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | coverage/*
3 | dist/*
4 | dll/*
5 | build/*
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": [
3 | "airbnb",
4 | "plugin:jsx-a11y/recommended"
5 | ],
6 | "parser": "babel-eslint",
7 | "parserOptions": {
8 | "ecmaVersion": 9,
9 | "sourceType": "module",
10 | "ecmaFeatures": {
11 | "experimentalObjectRestSpread": true,
12 | "allowImportExportEverywhere": true,
13 | "jsx": true
14 | }
15 | },
16 | "plugins": [
17 | "react",
18 | "jsx-a11y",
19 | "import"
20 | ],
21 | "env": {
22 | browser: true,
23 | node: true,
24 | node: true,
25 | es6: true,
26 | browser: true,
27 | jasmine: true,
28 | mocha: true,
29 | jquery: true
30 | },
31 | "rules": {
32 | 'camelcase': 0,
33 | 'comma-dangle': [2, 'never'],
34 | 'comma-spacing': [2, { before: false, after: true }],
35 | 'consistent-return': 0,
36 | 'curly': 0,
37 | 'default-case': 0,
38 | 'eqeqeq': [2, 'smart'],
39 | 'func-names': 0,
40 | 'guard-for-in': 2,
41 | 'indent': [2, 2, { SwitchCase: 1 }],
42 | 'key-spacing': [2, { beforeColon: false, afterColon: true }],
43 | 'keyword-spacing': [2, { before: true, after: true }],
44 | 'max-len': 0,
45 | 'new-cap': 0,
46 | 'no-bitwise': 0,
47 | 'no-caller': 2,
48 | 'no-console': 0,
49 | 'no-else-return': 0,
50 | 'no-empty-class': 0,
51 | 'no-multi-spaces': 2,
52 | 'no-param-reassign': 0,
53 | 'no-shadow': 0,
54 | 'no-spaced-func': 2,
55 | 'no-throw-literal': 2,
56 | 'no-trailing-spaces': 2,
57 | 'no-undef': 2,
58 | 'no-unneeded-ternary': 2,
59 | 'no-unreachable': 2,
60 | 'no-underscore-dangle': 0,
61 | 'no-unused-expressions': 0,
62 | 'no-unused-vars': 0,
63 | 'no-use-before-define': [1, 'nofunc'],
64 | 'no-var': 0,
65 | 'object-curly-spacing': [2, 'always'],
66 | 'one-var': [0, 'never'],
67 | 'one-var-declaration-per-line': [2, 'always'],
68 | 'padded-blocks': 0,
69 | 'space-before-function-paren': [2, {
70 | 'anonymous': 'always',
71 | 'named': 'never',
72 | 'asyncArrow': 'always'
73 | }],
74 | 'space-in-parens': [2, 'never'],
75 | 'spaced-comment': [2, 'always'],
76 | 'strict': 0,
77 | 'quote-props': 0,
78 | 'quotes': [1, 'single'],
79 | 'wrap-iife': [2, 'outside'],
80 | 'vars-on-top': 0,
81 | 'global-require': 0,
82 | 'no-plusplus': 0,
83 | 'eqeqeq': 0,
84 | 'no-case-declarations': 0,
85 | 'class-methods-use-this': 0,
86 | 'prefer-destructuring': 0,
87 | 'no-alert': 0,
88 | 'no-mixed-operators': 0,
89 | 'object-property-newline': 0,
90 | 'no-nested-ternary': 0,
91 | // import plugin
92 | 'import/no-mutable-exports': 0,
93 | 'import/extensions': 0,
94 | 'import/first': 0,
95 | 'import/no-named-as-default': 0,
96 | // react plugin
97 | 'react/jsx-filename-extension': [1, { "extensions": [".js", ".jsx"] }],
98 | 'react/prefer-stateless-function': 0,
99 | 'react/forbid-prop-types': 0,
100 | 'react/jsx-max-props-per-line': 0,
101 | // jsx-a11y plugin
102 | 'jsx-a11y/href-no-hash': 0,
103 | 'jsx-a11y/anchor-is-valid': 0,
104 | 'jsx-a11y/img-redundant-alt': 0,
105 | 'jsx-a11y/label-has-for': 0
106 | },
107 | 'globals': {
108 | by: true,
109 | browser: true,
110 | element: true,
111 | inject: true,
112 | io: true,
113 | moment: true,
114 | Modernizr: true,
115 | Promise: true,
116 | __TESTING__: true,
117 | _: false,
118 | ApplicationConfiguration: true
119 | }
120 | };
121 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ### Code of conduct
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Expected behavior
2 |
3 |
4 | ### Actual behavior
5 |
6 |
7 | ### Steps to reproduce the behavior
8 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Your checklist for this pull request
2 |
3 | ### Description
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # production
61 | /build
62 | /dist
63 |
64 | # misc
65 | .DS_Store
66 | .env.local
67 | .env.development.local
68 | .env.test.local
69 | .env.production.local
70 |
71 | npm-debug.log*
72 | yarn-debug.log*
73 | yarn-error.log*
74 |
75 | # auto generated files (sass, less, ...)
76 | src/**/*.css
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 node-oracle-sql
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.VN.md:
--------------------------------------------------------------------------------
1 | # react-configure
2 |
3 | Chào mọi người, đây là bài viết chia sẻ kinh nghiệm của bản thân mình khi tìm hiểu về công cụ create-react-app cho việc lập trình ReactJS trở nên dễ dàng hơn.
4 | Trong bài viết này, mình sẽ nói về những điều có thể cần thiết cần phải tinh chỉnh trước khi bắt đầu 1 dự án React của các bạn, cụ thể là sử dụng [create-react-app](https://github.com/facebook/create-react-app) với các thư viện [redux](https://redux.js.org/docs/basics/UsageWithReact.html),
5 | react-redux,
6 | redux-thunk,
7 | react-router,
8 | react-router-dom,
9 | sass,
10 | code spliting,
11 | jQuery,
12 | bootstrap,
13 | react-loadable,
14 | react-scrollchor,
15 | react-intl,
16 | react-select,
17 | react-datepicker,
18 | react-table,
19 | moment,
20 | ...
21 |
22 |
23 | Đây là demo về 1 số phần mình làm: [https://huynhsamha.github.io/react-configure/](https://huynhsamha.github.io/react-configure/)
24 |
25 |
26 |
27 |
28 | - [Bắt đầu với `create-react-app`](#bắt-đầu-với-create-react-app)
29 | - [Thiết lập biến môi trường (environment variables)](#thiết-lập-biến-môi-trường-environment-variables)
30 | - [Post-Processing CSS](#post-processing-css)
31 | - [CSS Preprocessor (Sass, Less etc.)](#css-preprocessor-sass-less-etc)
32 | - [Tạo server Node.JS](#tạo-server-nodejs)
33 | - [Use `express` to initialization](#use-express-to-initialization)
34 | - [Configuration](#configuration)
35 | - [Install dependencies package](#install-dependencies-package)
36 | - [Install package `cors`](#install-package-cors)
37 | - [Start server-client](#start-server-client)
38 | - [Environment cho react app](#environment-cho-react-app)
39 | - [Cấu trúc thư mục `src` trong react app](#cấu-trúc-thư-mục-src-trong-react-app)
40 | - [Styles](#styles)
41 | - [Library and packages](#library-and-packages)
42 | - [Utility service](#utility-service)
43 | - [Reducers - Actions](#reducers---actions)
44 | - [Components](#components)
45 | - [Layout Components](#layout-components)
46 | - [Common Components](#common-components)
47 | - [Pages Components](#pages-components)
48 | - [jQuery](#jquery)
49 | - [Installation](#installation)
50 | - [How to use?](#how-to-use)
51 | - [Recommend](#recommend)
52 | - [Bootstrap 3, 4](#bootstrap-3-4)
53 | - [Sử dụng cùng với jquery](#sử-dụng-cùng-với-jquery)
54 | - [Installation](#installation-1)
55 | - [How to use?](#how-to-use-1)
56 | - [Sử dụng thông qua React Component - `reactstrap`](#sử-dụng-thông-qua-react-component---reactstrap)
57 | - [Installation and Usage](#installation-and-usage)
58 | - [Font Awesome](#font-awesome)
59 | - [Thông qua `index.html`](#thông-qua-indexhtml)
60 | - [Sử dụng npm package](#sử-dụng-npm-package)
61 | - [Animate.css](#animatecss)
62 | - [Install and configure](#install-and-configure)
63 | - [Custom duration time](#custom-duration-time)
64 | - [How to use](#how-to-use)
65 | - [Demo](#demo)
66 | - [`react-router-dom` (router)](#react-router-dom-router)
67 | - [`react-loadable` (code-splitting)](#react-loadable-code-splitting)
68 | - [Installation, Usage](#installation-usage)
69 | - [Test Loadable Components - code-splitting](#test-loadable-components---code-splitting)
70 | - [`react-intl` - API cho format date, number and string](#react-intl---api-cho-format-date-number-and-string)
71 | - [Features - các tính năng](#features---các-tính-năng)
72 | - [Document](#document)
73 | - [Usage in this tutorial](#usage-in-this-tutorial)
74 | - [Redux: `redux, react-redux, redux-thunk`](#redux-redux-react-redux-redux-thunk)
75 | - [Installation](#installation-2)
76 | - [Usage](#usage)
77 | - [Fetch Data API to server node](#fetch-data-api-to-server-node)
78 | - [Create `services` to get API](#create-services-to-get-api)
79 | - [UI Awesome with React Component](#ui-awesome-with-react-component)
80 | - [Reveal Component on scroll: use `react-reveal`](#reveal-component-on-scroll-use-react-reveal)
81 | - [Installation](#installation-3)
82 | - [Support](#support)
83 | - [Reveal with React](#reveal-with-react)
84 | - [Animated.css with React](#animatedcss-with-react)
85 | - [How to use?](#how-to-use-2)
86 | - [Scroll animted to target - react-scrollchor](#scroll-animted-to-target---react-scrollchor)
87 | - [Installation](#installation-4)
88 | - [How to use?](#how-to-use-3)
89 | - [Datatable with `react-table`](#datatable-with-react-table)
90 | - [VS Code Extensions](#vs-code-extensions)
91 | - [Icons, Colors, View](#icons-colors-view)
92 | - [Snippets](#snippets)
93 | - [Intellisence](#intellisence)
94 | - [Lint Code, Formater](#lint-code-formater)
95 | - [Edit, Preview README - Markdown files](#edit-preview-readme---markdown-files)
96 | - [VS Code User Settings](#vs-code-user-settings)
97 |
98 |
99 |
100 |
101 |
102 | # Bắt đầu với `create-react-app`
103 | Nếu bạn mới bắt đầu sử dụng react hoặc chưa biết đến create-react-app thì mình nghĩ bạn nên sử dụng thằng này để làm quen với react, vì nó đã làm sẵn mọi thứ giúp ta, ta chỉ cần làm theo những gì ta muốn với công cụ này.
104 |
105 | Trước tiên, bạn nên cài package `create-react-app` mức global từ npm .
106 | `npm install create-react-app -g`
107 | hoặc nếu bạn dùng Ubuntu hay một số hệ điều hành khác, nó yêu cầu quyền root, bạn thêm `sudo` vào trước lệnh để thực thi.
108 |
109 | 1. Tạo mới project: `create-react-app react-app`
110 | 2. `npm start` or `yarn start`: start môi trường dev.
111 | 3. `npm build` or `yarn build` build production.
112 |
113 | Trong bài này, mình sử dụng `yarn`, các bạn có thể sử dụng `npm` cũng được theo đúng cú pháp của `npm`.
114 |
115 |
116 |
117 |
118 | # Thiết lập biến môi trường (environment variables)
119 | Tạo các file lưu trữ biến môi trường, những file này theo như create-react-app nói nó sẽ nhận ra các biên được khai báo trong các file này.
120 |
121 | 1. Trong terminal tại root của project: `touch .env .env.development .env.production`
122 | 2. In `.env.development`: `REACT_APP_ENV=development`
123 | 3. In `.env.production` : `REACT_APP_ENV=production`
124 |
125 | **Note:** chỉ mầy biến với prefix là `REACT_APP_` thì thằng `create-react-app` mới hiểu và đọc được, còn sử dụng nó thì mình nói sau.
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | # Post-Processing CSS
134 | Khi viết CSS, ta thường quan tâm đến các thuộc tính hỗ trợ trên nhiều trình duyệt . Tuy nhiên `create-react-app` sẽ lo cho ta việc này, do đó ta có thể yên tâm khi viết CSS 1 cách đơn giản.
135 | Đây là lời trích từ document của react:
136 |
137 | > This project setup minifies your CSS and adds vendor prefixes to it automatically through Autoprefixer so you don’t need to worry about it.
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | # CSS Preprocessor (Sass, Less etc.)
146 | Nếu bạn nào đã dùng qua SASS , LESS, SCSS thì cũng biết sự lợi hại và tiện ích của những thằng này. Do đó nếu có thể tích hợp vào React thì khá thú vị.
147 | `create-react-app` cũng hỗ trợ ta việc này, bằng cách thực hiện các bước sau:
148 |
149 | 1. In terminal: `yarn add node-sass-chokidar npm-run-all`
150 | 2. In file `package.json`:
151 | ```json
152 | {
153 | "scripts": {
154 | - "start": "react-scripts start",
155 | - "build": "react-scripts build",
156 | + "start": "npm-run-all -p watch-css start-js",
157 | + "build": "npm-run-all build-css build-js",
158 | + "start-js": "react-scripts start",
159 | + "build-js": "react-scripts build",
160 | + "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
161 | + "build-css": "node-sass-chokidar src/ -o src/",
162 | }
163 | }
164 | ```
165 | 3. In file `.gitignore`:
166 |
167 | ```
168 | # auto generated files (sass, less, ...)
169 | src/**/*.css
170 | ```
171 |
172 | Lúc này khi ta start lên, khi có thay đổi gì ở file sass, thì nó sẽ tự build lại các file css cho ta và browser tự động được refresh.
173 |
174 | Còn trong file .gitignore, ta thêm các file tự động sinh ra do sass để tránh gây conflict không cần thiết khi nhiều người commit.
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | # Tạo server Node.JS
185 | Nhiều lúc, ta cũng muốn sử dụng node cho thằng react :)
186 | ## Use `express` to initialization
187 |
188 | ```bash
189 | mkdir server
190 | cd server
191 | express
192 | ```
193 |
194 | ## Configuration
195 |
196 | 1. Rename `app.js` to `server.js`
197 | 2. Join `server.js` and `./bin/www`
198 | 3. Move `server.js` to root app
199 | 4. Insert dependencies in `package.json` (which is generated by `express`) to `package.json` in root (which is generated by `create-react-app`)
200 | 5. Remove dependencies not use (`serve-favicon`, `jade`, `ejs`, etc.)
201 | 6. Remove all file in `server`, execpt `routes/index.js`
202 | 7. Correct and customize file `server.js`
203 |
204 |
205 | ## Install dependencies package
206 |
207 | `yarn`
208 |
209 | ## Install package `cors`
210 |
211 | Ta install package `cors` để cross từ port 3000 localhost tới port 4200 localhost.
212 | + `localhost:3000` (client-side, là port thằng react)
213 | + `localhost:4200` (server-side, là port của node express)
214 |
215 | `yarn add cors`
216 |
217 | ## Start server-client
218 |
219 | `yarn start` or `npm start`: start client side (react): `localhost:3000`
220 |
221 | `node server`: start server-side (node express): `localhost:4200`
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 | # Environment cho react app
232 | Lúc ta phát triển (dev), ta sử dụng node ở port 4200, còn react ở port 3000, do đó để react có thể gọi request đến port 4200, ngoài sử dụng `cors` như ở trên, ta cũng cần sử dụng biên môi trường (đã thiết lập ở bước trên) để lấy dữ liệu từ server node. Ngoài ra ta cũng có thể dùng proxy (tham khảo thêm google cách này).
233 |
234 | Như đã nói ở trên, chỉ các biến `REACT_APP_` được khai báo trong các file tương ứng thì react mới biết được. Cụ thể ta dùng biến `REACT_APP_ENV` để phân biệt môi trường của server, nếu là production thì không cần phinh phức.
235 |
236 | 1. Create environment files:
237 | In your terminal:
238 | ```bash
239 | mkdir src/environments
240 | cd src/environments
241 | touch env.development.js env.production.js index.js
242 | ```
243 | 2. Edit the files as source code. `baseUrl` is url to server.
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 | # Cấu trúc thư mục `src` trong react app
252 |
253 | ## Styles
254 | Tạo thư mục `styles` trong `src/` để chứa các biến variables, mixins, classes, common styles, or theme, etc. cho app react:
255 | + `_variables.scss`: khai báo các variables .
256 | + `_mixins.scss`: khai báo các mixins (dùng sass hoặc less)
257 | + `_classes.scss`: khai báo 1 số class hữu ích.
258 | + `index.scss`: import các file `_` vào file này, để file `index.scss` ở ngoài thư thư mục tương ứng, còn trong file `index.js`, ta import style này vào `./styles/index.css`
259 | + Nếu app của bạn sử dụng theme (như AdminLTE, Bootstrap, Material, Angular, Datatables, Charts, ...), ta ghi đề những style cần với file prefix là `_` và import vô `index.scss`
260 |
261 | ## Library and packages
262 | Trong thư mục `src`, ta tạo thư mục `lib` để chứa các thư viện và package ta dùng trong app, chẳng hạn như jQuery, Bootstrap, Font-Awesome, Ionicons, Material, ...
263 | + Tạo file `index.js` trong `lib` để import các file trong thư mục này
264 | + Trong file `index.js` ngoài thư mục app của ta, ta import thư mục `lib` vừa tạo chỉ bằng dòng `import './lib';`
265 |
266 |
267 | ## Utility service
268 | Ta cũng tạo thư mục `services` để chứa các tiện ích của app. Việc triển khai thư mục này ta sẽ bàn sau.
269 |
270 | ## Reducers - Actions
271 | Nếu ta sử dụng `redux`, ta cũng cần tạo 2 thư mục `actions` và `reducers`. Cụ thể triển khai ta sẽ bàn sau.
272 |
273 | ## Components
274 | Ta tạo `components` để chứa các components của app, trong đó ta chia ra thành:
275 |
276 | ### Layout Components
277 | Tạo thư mục `layout` để chứa luồng thực thi của app. Trong `layout` ta tạo hai file `App.js` và `App.scss`, ngoài ra còn chứa các thư mục `Header`, `Footer`, `Sidebar`, `Menu`, `Body` tương ứng cho việc điều hướng app.
278 |
279 |
280 | ### Common Components
281 | Ta tạo `common` để chứa các components dùng chung được sử dụng nhiều lần như `Loading`, `Modal`, `Alert`, `Notification`, `Box`, ...
282 |
283 | ### Pages Components
284 | Tạo `pages` để chứa các trang của 1 single page app, như `Home`, `Dashboard`, `Profile`, `Form`, `Terms of Service`, `Support`, `Page not found`, `Error page`,..
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 | # jQuery
293 |
294 | ## Installation
295 | 1. In terminal: `yarn add jquery`
296 | 2. In terminal: `touch src/lib/jquery.js`: tạo file jquery config
297 | 3. COnfig file này như sau:
298 |
299 | ```js
300 | import $ from 'jquery';
301 |
302 | // config jquery variables for other lib use jQuery (such as bootstrap)
303 | window.$ = $;
304 | window.jQuery = $;
305 | ```
306 |
307 | ## How to use?
308 | 1. In `lib/index.js`, import by: `import './jquery';`
309 | 2. In `index.js` at ngoài app, `import './lib';` (nếu như bạn chưa import).
310 | 3. Trong mỗi component, để sử dungj jquery mà react không báo lỗi, ta cần import: `import $ from 'jquery';`
311 | 4. jquery chỉ sử dụng kể từ `componentDidMount()` trong vòng đời của 1 component react:
312 | 5. [View Demo here](https://huynhsamha.github.io/react-configure/jquery)
313 | 6. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-jquery/DemoJquery.jsx)
314 |
315 |
316 | ```javascript
317 | componentDidMount() {
318 | // jQuery should declare at here
319 | $(document).ready(() => {
320 | $('#alert').click(() => alert('This is alert be jQuery'));
321 | });
322 | }
323 | ```
324 |
325 |
326 | ## Recommend
327 | Chỉ nên dùng jquery khi thực sự cần thiết. vì react đã hỗ trợ khá đủ.
328 |
329 |
330 |
331 |
332 |
333 |
334 | # Bootstrap 3, 4
335 |
336 |
337 | ## Sử dụng cùng với jquery
338 | ### Installation
339 | 1. In terminal: `yarn add bootstrap` (thêm @version cho version bạn sử dụng)
340 | 2. In terminal: `mkdir src/lib` (nếu đã tạo thì bỏ qua)
341 | 3. In terminal: `touch src/lib/bootstrap.js`
342 | 4. Cấu hình file này như sau (mình đang dùng bootstrap 4):
343 |
344 | ```javascript
345 | import 'bootstrap/dist/css/bootstrap.min.css';
346 | import 'bootstrap/dist/js/bootstrap.bundle.min.js';
347 | ```
348 |
349 | ### How to use?
350 | 1. In `lib/index.js`, import by: `import './bootstrap';`
351 | 2. In `index.js` at root, `import './lib';` (if you don't have).
352 | 3. Trong component, ta có thể sử dụng bootstrap 3, 4 như document của bootstrap.
353 | 4. View demo with component `DemoBootstrap`.
354 | 5. [View Demo here](https://huynhsamha.github.io/react-configure/bootstrap)
355 | 6. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-bootstrap/DemoBootstrap.jsx)
356 |
357 |
358 |
359 |
360 | ## Sử dụng thông qua React Component - `reactstrap`
361 | `reactstrap` là một package react cho bootstrap, tương đối ổn so với bootstrap nhưng không phải là hoàn thiện.
362 | Bạn có thể google package này để xem qua doc của nó.
363 |
364 | Cũng có nhiều framework khác cho react, xây dụng sẵn các component cần thiết cho react, bạn có thể google các framewro hoặc package tương ứng.
365 |
366 | ### Installation and Usage
367 | 1. In terminal: `yarn add reactstrap@next`
368 | 2. Only import Component to use as reactstrap document
369 | 3. View demo with component `DemoReactstrap`.
370 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/reactstrap)
371 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-reactstrap/DemoReactstrap.jsx)
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 | # Font Awesome
381 | ## Thông qua `index.html`
382 | Ta có thể include trực tiếp thông qua `index/html` bằng cdn, hoặc download rồi include vào.
383 |
384 | ## Sử dụng npm package
385 |
386 | 1. In terminal: `yarn add font-awesome`
387 | 2. Create file `lib/font-awesome.js` and add line `import 'font-awesome/css/font-awesome.min.css';`
388 | 3. In `lib/index.js`, import by: `import './font-awesome';`
389 | 4. In `index.js` at root, `import './lib';` (if you don't have).
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 | # Animate.css
399 | ## Install and configure
400 | 1. `yarn add animate.css`
401 | 2. In `lib/` tạo `animate-css.js` và thêm `import 'animate.css';`
402 | 3. In `index.js`, import bằng `import './animate-css';`
403 |
404 | ## Custom duration time
405 | 1. Tùy chỉnh thời gian animation bằng scss config trong `style/`:
406 | 2. Tạo file `_animate.scss` như source code
407 | 3. In `index.scss`: `@import './animate.scss';`
408 | 4. File này sẽ tạo ra các class sau:
409 | ```
410 | .animated.duration-100
411 | .animated.duration-200
412 | ...
413 | .animated.duration-1100
414 | .animated.duration-1200
415 | ...
416 | .animated.duration-3000
417 | ```
418 |
419 | ## How to use
420 | Example:
421 | ```html
422 |
423 |
ABCDEFGHIJKLMNOP
424 | ABCDEFGHIJKLMNOP
425 | ABCDEFGHIJKLMNOP
426 |
427 | ABCDEFGHIJKLMNOP
428 | ABCDEFGHIJKLMNOP
429 | ABCDEFGHIJKLMNOP
430 |
431 | ABCDEFGHIJKLMNOP
432 | ABCDEFGHIJKLMNOP
433 | ```
434 |
435 |
436 | ## Demo
437 | + View demo at component `DemoAnimateCss`
438 | + [View Demo here](https://huynhsamha.github.io/react-configure/animate-css)
439 | + [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-animate-css/DemoAnimateCss.jsx)
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 | # `react-router-dom` (router)
449 | `react-router-dom` được sử dụng cho 1 Single Page Application (SPA).
450 |
451 | 1. In terminal: `yarn add react-router-dom`
452 | 2. Bạn xem implement trong `components/layout/body`
453 | 3. Cũng có thể xem ở `components/pages/demo-react-router`
454 | 4. Documents is available at [React Router Dom](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom)
455 |
456 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-router)
457 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-router/DemoReactRouter.jsx)
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 | # `react-loadable` (code-splitting)
466 | `code-splitting` là một kỹ thuật tăng tốc độ của single page app. Nó sẽ lazy loading, tức chờ cho điến khi người dùng click vào component đó nó mới thực sự load component đó lên. Điều này giúp ứng dụng của ta load nhanh ở lần chạy đầu tiên khi người dùng chưa cần vào các component này.
467 |
468 | create-react-app cũng hỗ trợ ta trong việc code-splitting, do đó ta không nên bỏ qua kỹ thuật này,
469 | ## Installation, Usage
470 |
471 | `react-loadable` hỗ trợ code-splitting:
472 | + `create-react-app` sẽ bundle script file mới, khi được gọi, nó mới load file này.
473 |
474 | 1. In terminal: `yarn add react-loadable react-router-dom`
475 | 2. Tạo 1 Loading component (view components/common/loading/)
476 | 3. Khi sử dụng Loadable với loading component, các thuộc tính cần quan tâm cho component này:
477 | `{ isLoading: true, pastDelay: false, timedOut: false, error: null }`
478 | 4. View `components/page/demo-loadable-component` to sample implement.
479 | 5. Component `DemoLoadableComponent` (is not loadable) and `LoadableDemoComponent` (is loadable)
480 |
481 | ## Test Loadable Components - code-splitting
482 | 1. Inspect element trong trình duyệt
483 | 2. Chọn tab network
484 | 3. Click filter JS
485 | 4. Refresh page
486 | 5. lúc đầu chỉ thấy file `bundle.js` và 1 số file js khác.
487 | 6. Click component hỗ trợ loadable, ta sẽ thấy `*.chunk.js` is loaded. Đây là lazy loading component
488 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-loadable)
489 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-router/DemoReactRouter.jsx)
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 | # `react-intl` - API cho format date, number and string
500 | Internationalize React apps. Thư viện này cung cấp các React components and API để format dates, numbers, and strings, bao gồm pluralization (số nhiều) và handling translations (chuyến đổi).
501 |
502 | ## Features - các tính năng
503 | + Display numbers with separators.
504 | + Display dates and times correctly.
505 | + Display dates relative to "now".
506 | + Pluralize labels in strings.
507 | + Support for 150+ languages.
508 | + Runs in the browser and Node.js.
509 | + Built on standards.
510 |
511 | ## Document
512 | You can view document at here: [https://github.com/yahoo/react-intl](https://github.com/yahoo/react-intl)
513 |
514 |
515 | ## Usage in this tutorial
516 | 1. In `index.js`, ta import và dùng provider cho App component:
517 |
518 | ```jsx
519 | import { IntlProvider } from 'react-intl';
520 |
521 | ReactDOM.render(
522 |
523 |
524 |
525 |
526 |
527 | ,
528 |
529 | document.getElementById('root')
530 | );
531 | ```
532 |
533 | 2. Trong từng component, ta import component of `react-intl` để sử dụng. Bạn có thể xem demo sử dụng ở demo phần redux.
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 | # Redux: `redux, react-redux, redux-thunk`
544 | Redux là 1 kỹ thuật ta không thể bỏ qua khi làm việc với react.
545 | ## Installation
546 | `yarn add redux react-redux redux-thunk`
547 |
548 | ## Usage
549 | 1. In `src`, tạo:
550 | + `actions/action-types.js`: định nghĩa tên action
551 | + `actions/index.js`: định nghĩa các action
552 | + `reducers/`: khai báo các reducer
553 | + `reducers/[name].js`: định nghĩa các action cụ thể.
554 | + `reducers/index.js`: combine các reducer của redux, sau đó sẽ được createStore.
555 |
556 | 2. In `index.js`:
557 | + `import { Provider } from 'react-redux';`: dùng Provider để store redux
558 | + `import { createStore, applyMiddleware } from 'redux';`: dùng createStore và middleware `thunk` cho createStore
559 | + `import thunk from 'redux-thunk';`: middleware cho createStore, support async function
560 | + `import allReducers from './reducers';`: reducers sau khi combined
561 | + `const store = createStore(allReducers, applyMiddleware(thunk));`: createStore với combined reducer, và apply middleware thunk
562 | + Hiện tại bạn không cần quan tâm reducers `Users`, ta sẽ sử dụng cái này sau.
563 |
564 | 3. In `reducers/index.js`: combine reducers:
565 | + In this tutorial, I demo with Items and Users (users is used for other section demo).
566 | ```js
567 | import { combineReducers } from 'redux';
568 |
569 | import Items from './items';
570 | import Users from './users';
571 |
572 | const reducers = combineReducers({
573 | Items,
574 | Users
575 | });
576 |
577 | export default reducers;
578 | ```
579 |
580 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/redux)
581 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-redux/DemoRedux.jsx)
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 | # Fetch Data API to server node
597 | ## Create `services` to get API
598 | 1. `mkdir src/services` (if you have not)
599 | 2. `touch db-service.js auth-service.js` (db- to get database, auth- to authentication user)
600 | 3. Example with `db-service.js`:
601 | + `import Env from './../environments';`: to get `baseUrl` with environments
602 | + `export default class DbService` as static class
603 | + set baseUrl to get API:
604 | ```jsx
605 | static baseUrl() { return Env.baseUrl; }
606 | static parseUrl(url) { return DbService.baseUrl() + url; }
607 | ```
608 |
609 | Example `get` API:
610 | ```js
611 | static getItems = () => {
612 | let url = DbService.parseUrl('/api/items');
613 | console.log(url);
614 | return fetch(url).then(res => res.json());
615 | }
616 | ```
617 |
618 | Example `Post` API:
619 | ```js
620 | static addItem = (item) => {
621 | let url = DbService.parseUrl('/api/items');
622 | return fetch(url, {
623 | method: 'POST',
624 | headers: {
625 | 'Accept': 'application/json',
626 | 'Content-Type': 'application/json'
627 | },
628 | body: JSON.stringify(item)
629 | }).then(res => res.json());
630 | }
631 | ```
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 | # UI Awesome with React Component
647 |
648 |
649 | ## Reveal Component on scroll: use `react-reveal`
650 |
651 | Tạo animation khi người dụng scroll tới element. Khá hữu ích.
652 |
653 | ### Installation
654 | `yarn add react-reveal`
655 |
656 | ### Support
657 |
658 | #### Reveal with React
659 | ```
660 | Fade
661 | Flip
662 | Rotate
663 | Zoom
664 | Bounce
665 | Slide
666 | Roll
667 |
668 | left/right/top/bottom
669 | fadeOut
670 | ```
671 | #### Animated.css with React
672 | ```
673 | Jump
674 | Flash
675 | HeadShake
676 | Jello
677 | Pulse
678 | RubberBand
679 | Shake
680 | Spin
681 | Swing
682 | Tada
683 | ```
684 |
685 | ### How to use?
686 | 1. Use http://www.react-reveal.com/examples/.
687 | 2. View demo with component `DemoReactReveal`.
688 |
689 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-reveal)
690 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-reveal/DemoReactReveal.jsx)
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 | ## Scroll animted to target - react-scrollchor
701 |
702 | Tạo animation khi người dùng click và chuyển tới 1 element nào đó.
703 |
704 | ### Installation
705 | `yarn add react-scrollchor`
706 |
707 |
708 | ### How to use?
709 | 1. Use https://github.com/bySabi/react-scrollchor
710 | 2. View demo with component `DemoReactScrollchor`.
711 |
712 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-scrollchor)
713 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-scrollchor/DemoReactScrollchor.jsx)
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 | # Datatable with `react-table`
722 | 1. Xem demo: [Demo](https://huynhsamha.github.io/react-configure/react-table)
723 | 2. Xem implementation trong [`demo-react-table` - Implementation](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-table/DemoReactTable.jsx)
724 | 3. Ta dùng [`react-table`](https://react-table.js.org/#/story/readme) with features:
725 | + Lightweight at 11kb (and just 2kb more for styles)
726 | + Fully customizable (JSX, templates, state, styles, callbacks)
727 | + Client-side & Server-side pagination
728 | + Multi-sort
729 | + Filters
730 | + Pivoting & Aggregation
731 | + Minimal design & easily themeable
732 | + Fully controllable via optional props and callbacks
733 | 4. Mình cũng dùng thêm `react-select` và `react-datepicker` với `moment`. You can view docs for these package here:
734 | + [`react-select` - Demo](http://jedwatson.github.io/react-select/)
735 | + [`react-select` - Docs](https://github.com/JedWatson/react-select)
736 | + [`react-datepicker` - Demo](https://reactdatepicker.com/)
737 | + [`react-datepicker` - Docs](https://github.com/Hacker0x01/react-datepicker)
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 | # VS Code Extensions
749 | Làm việc với react thì không thể thiếu các extension cần thiết nếu bạn đang sử dụng visual studio code (VS Code)
750 |
751 | Các bạn chỉ đơn giản install extension và config nếu cần thiết.
752 |
753 | ## Icons, Colors, View
754 | - [vscode-icons](https://marketplace.visualstudio.com/items?itemName=robertohuertasm.vscode-icons)
755 | - [Bracket Pair Colorizer](https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer)
756 |
757 | ## Snippets
758 | - [ES7 React/Redux/GraphQL/React-Native snippets](https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets)
759 | - [JavaScript (ES6) code snippets](https://marketplace.visualstudio.com/items?itemName=xabikos.JavaScriptSnippets)
760 | - [Bootstrap 3 Snippets](https://marketplace.visualstudio.com/items?itemName=wcwhitehead.bootstrap-3-snippets)
761 | - [Bootstrap 4 & Font awesome snippets](https://marketplace.visualstudio.com/items?itemName=thekalinga.bootstrap4-vscode)
762 | - [Font-awesome codes for html](https://marketplace.visualstudio.com/items?itemName=medzhidov.font-awesome-codes-html)
763 | - [Font-awesome codes for css](https://marketplace.visualstudio.com/items?itemName=medzhidov.font-awesome-codes-css)
764 | - [HTML Snippets](https://marketplace.visualstudio.com/items?itemName=abusaidm.html-snippets)
765 | - [HTML CSS suppport](https://marketplace.visualstudio.com/items?itemName=ecmel.vscode-html-css)
766 |
767 | ## Intellisence
768 | - [npm](https://marketplace.visualstudio.com/items?itemName=eg2.vscode-npm-script)
769 | - [npm Intellisence](https://marketplace.visualstudio.com/items?itemName=christian-kohler.npm-intellisense)
770 | - [Path Intellisense](https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense)
771 | - [SCSS IntelliSence](https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-scss)
772 | - [Auto Close Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-close-tag)
773 | - [Auto Rename Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag)
774 | - [IntelliSense for CSS class names](https://marketplace.visualstudio.com/items?itemName=Zignd.html-css-class-completion)
775 |
776 | ## Lint Code, Formater
777 | - [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
778 | - [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig)
779 | - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
780 | - [TSLint](https://marketplace.visualstudio.com/items?itemName=eg2.tslint)
781 | - [Sass](https://marketplace.visualstudio.com/items?itemName=robinbentley.sass-indented)
782 | - [Sass Formatter](https://marketplace.visualstudio.com/items?itemName=sasa.vscode-sass-format)
783 | - [Beautify css/sass/scss/less](https://marketplace.visualstudio.com/items?itemName=michelemelluso.code-beautifier)
784 |
785 |
786 | ## Edit, Preview README - Markdown files
787 | - [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one)
788 | - [Markdown Preview Enhanced](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced)
789 | - [Markdown PDF](https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf)
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 | # VS Code User Settings
822 | Cũng nên setting một số config cho VS Code, tạo nên coding style chuẩn:
823 |
824 | 1. Enter `Ctrl + Shift P`
825 | 2. Search `user settings`
826 | 3. Choose `Preferences: Open User Settings` and enter.
827 | 4. Edit your file `User Settings` by following lines:
828 | (you can search in `Default Settings` and customize your style)
829 |
830 | ```json
831 | {
832 | "workbench.iconTheme": "vscode-icons",
833 | "workbench.startupEditor": "newUntitledFile",
834 | "window.zoomLevel": 0,
835 | "editor.fontSize": 13,
836 | "eslint.autoFixOnSave": true,
837 | "tslint.autoFixOnSave": true,
838 | "editor.formatOnSave": false,
839 | "editor.renderWhitespace": "boundary",
840 | "editor.quickSuggestions": {
841 | "other": true,
842 | "comments": true,
843 | "strings": true
844 | },
845 | "terminal.integrated.cursorStyle": "line",
846 | "terminal.integrated.fontSize": 13,
847 | "terminal.integrated.fontFamily": "",
848 | "vsicons.projectDetection.autoReload": true,
849 | }
850 | ```
851 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-configure
2 |
3 |
4 | Necessary configure for [create-react-app](https://github.com/facebook/create-react-app) with [redux](https://redux.js.org/docs/basics/UsageWithReact.html),
5 | react-redux,
6 | redux-thunk,
7 | react-router,
8 | react-router-dom,
9 | sass,
10 | code spliting,
11 | jQuery,
12 | bootstrap,
13 | react-loadable,
14 | react-scrollchor,
15 | react-intl,
16 | react-select,
17 | react-datepicker,
18 | react-table,
19 | moment,
20 | ...
21 |
22 |
23 |
24 |  [**Vietnamese version here**](https://github.com/huynhsamha/react-configure/blob/master/README.VN.md)
25 |
26 |
27 |
28 |
29 | ## Table of contents:
30 | - [Start with `create-react-app`](#start-with-create-react-app)
31 | - [Config environment variables](#config-environment-variables)
32 | - [Post-Processing CSS:](#post-processing-css)
33 | - [CSS Preprocessor (Sass, Less, etc.)](#css-preprocessor-sass-less-etc)
34 | - [Create Node.JS server](#create-nodejs-server)
35 | - [Use `express` to initialization](#use-express-to-initialization)
36 | - [Configuration](#configuration)
37 | - [Install dependencies package](#install-dependencies-package)
38 | - [Install package `cors`](#install-package-cors)
39 | - [Start server-client](#start-server-client)
40 | - [Environment for react app](#environment-for-react-app)
41 | - [Organize `src` react app](#organize-src-react-app)
42 | - [Styles](#styles)
43 | - [Library and packages](#library-and-packages)
44 | - [Utility service](#utility-service)
45 | - [Reducers - Actions](#reducers---actions)
46 | - [Components](#components)
47 | - [Layout Components](#layout-components)
48 | - [Common Components](#common-components)
49 | - [Pages Components](#pages-components)
50 | - [jQuery](#jquery)
51 | - [Installation](#installation)
52 | - [How to use?](#how-to-use)
53 | - [Recommend](#recommend)
54 | - [Bootstrap 3, 4](#bootstrap-3-4)
55 | - [Use along with jQuery](#use-along-with-jquery)
56 | - [Installation](#installation)
57 | - [How to use?](#how-to-use)
58 | - [Use via React Component - `reactstrap`](#use-via-react-component---reactstrap)
59 | - [Installation and Usage](#installation-and-usage)
60 | - [Recommend](#recommend)
61 | - [Font Awesome](#font-awesome)
62 | - [Add via `index.html`](#add-via-indexhtml)
63 | - [Add via npm package](#add-via-npm-package)
64 | - [Animate.css](#animatecss)
65 | - [Install and configure](#install-and-configure)
66 | - [Custom duration time](#custom-duration-time)
67 | - [How to use](#how-to-use)
68 | - [Demo](#demo)
69 | - [`react-router-dom` (router)](#react-router-dom-router)
70 | - [`react-loadable` (code-splitting)](#react-loadable-code-splitting)
71 | - [Installation, Usage](#installation-usage)
72 | - [Test Loadable Components - code-splitting](#test-loadable-components---code-splitting)
73 | - [`react-intl` - API to format date, number and string](#react-intl---api-to-format-date-number-and-string)
74 | - [Features](#features)
75 | - [Document](#document)
76 | - [Usage in this tutorial](#usage-in-this-tutorial)
77 | - [Redux: `redux, react-redux, redux-thunk`](#redux-redux-react-redux-redux-thunk)
78 | - [Installation](#installation)
79 | - [Usage](#usage)
80 | - [Fetch Data API to server node](#fetch-data-api-to-server-node)
81 | - [Create `services` to get API](#create-services-to-get-api)
82 | - [UI Awesome with React Component](#ui-awesome-with-react-component)
83 | - [Reveal Component on scroll: use `react-reveal`](#reveal-component-on-scroll-use-react-reveal)
84 | - [Installation](#installation)
85 | - [Support](#support)
86 | - [Reveal with React](#reveal-with-react)
87 | - [Animated.css with React](#animatedcss-with-react)
88 | - [How to use?](#how-to-use)
89 | - [Scroll animated to target - react-scrollchor](#scroll-animated-to-target---react-scrollchor)
90 | - [Installation](#installation)
91 | - [How to use?](#how-to-use)
92 | - [Datatable with `react-table`](#datatable-with-react-table)
93 | - [VS Code Extensions](#vs-code-extensions)
94 | - [Icons, Colors, View](#icons-colors-view)
95 | - [Snippets](#snippets)
96 | - [Intellisence](#intellisence)
97 | - [Lint Code, Formater](#lint-code-formater)
98 | - [Edit, Preview README - Markdown files](#edit-preview-readme---markdown-files)
99 | - [VS Code User Settings](#vs-code-user-settings)
100 |
101 |
102 |
103 |
104 | # Start with `create-react-app`
105 | In this step, you should have `create-react-app` is installed globally.
106 |
107 | 1. Create a new app: `create-react-app react-app`
108 | 2. use `npm start` or `yarn start` to start development
109 | 3. use `npm build` or `yarn build` to build production
110 |
111 | In this tutorial, I will use `yarn`, you can also use `npm`.
112 |
113 |
114 |
115 |
116 | # Config environment variables
117 | Create environment files, `create-react-app` will use them.
118 |
119 | 1. In terminal at root: `touch .env .env.development .env.production`
120 | 2. In `.env.development`: `REACT_APP_ENV=development`
121 | 3. In `.env.production` : `REACT_APP_ENV=production`
122 |
123 | You can also set new environment variable.
124 | **Note:** only variable with prefix `REACT_APP_` can use in `create-react-app`
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | # Post-Processing CSS:
133 | As `create-react-app` said:
134 |
135 | > This project setup minifies your CSS and adds vendor prefixes to it automatically through Autoprefixer so you don’t need to worry about it.
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | # CSS Preprocessor (Sass, Less, etc.)
144 |
145 | 1. In terminal: `yarn add node-sass-chokidar npm-run-all`
146 | 2. In file `package.json`:
147 | ```json
148 | {
149 | "scripts": {
150 | - "start": "react-scripts start",
151 | - "build": "react-scripts build",
152 | + "start": "npm-run-all -p watch-css start-js",
153 | + "build": "npm-run-all build-css build-js",
154 | + "start-js": "react-scripts start",
155 | + "build-js": "react-scripts build",
156 | + "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
157 | + "build-css": "node-sass-chokidar src/ -o src/",
158 | }
159 | }
160 | ```
161 | 3. In file `.gitignore`:
162 |
163 | ```
164 | # auto generated files (sass, less, ...)
165 | src/**/*.css
166 | ```
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | # Create Node.JS server
177 | Optional if you need a node.js server
178 |
179 | ## Use `express` to initialization
180 |
181 | ```bash
182 | mkdir server
183 | cd server
184 | express
185 | ```
186 |
187 | ## Configuration
188 |
189 | 1. Rename `app.js` to `server.js`
190 | 2. Join `server.js` and `./bin/www`
191 | 3. Move `server.js` to root app
192 | 4. Insert dependencies in `package.json` (which is generated by `express`) to `package.json` in root (which is generated by `create-react-app`)
193 | 5. Remove dependencies not use (`serve-favicon`, `jade`, `ejs`, etc.)
194 | 6. Remove all file in `server`, except `routes/index.js`
195 | 7. Correct and customize file `server.js`
196 |
197 |
198 | ## Install dependencies package
199 |
200 | `yarn`
201 |
202 | ## Install package `cors`
203 |
204 | For development, use package `cors` to cross `localhost:3000` (client-side, is react app) to `localhost:4200` (server-side, is node express)
205 |
206 | `yarn add cors`
207 |
208 | ## Start server-client
209 |
210 | `yarn start` or `npm start`: start client side (react): `localhost:3000`
211 |
212 | `node server`: start server-side (node express): `localhost:4200`
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 | # Environment for react app
223 | In development, because we use node server at port 4200, but client side is port 3000, so we should check out environment variable `REACT_APP_ENV` (which created in above steps) to fetch data from the server.
224 |
225 | 1. Create environment files:
226 | In your terminal:
227 | ```bash
228 | mkdir src/environments
229 | cd src/environments
230 | touch env.development.js env.production.js index.js
231 | ```
232 | 2. Edit the files as source code. `baseUrl` is url to server.
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 | # Organize `src` react app
241 |
242 | ## Styles
243 | Create `styles` in `src/` to contain variables, mixins, classes, common styles, or theme, etc. for your app:
244 | + `_variables.scss`: declare variables for style.
245 | + `_mixins.scss`: declare mixins for style
246 | + `_classes.scss`: declare some util classes for style
247 | + `index.scss`: import `_` files to this file, you should move `index.scss` (in root) to this folder and in `index.js`, you only import `./styles/index.css`
248 | + You also override some theme (such as AdminLTE, Bootstrap, Material, Angular, Datatables, Charts, ...) with files `_` and import to `index.scss`
249 |
250 | ## Library and packages
251 | Create `lib` in `src` to contain some library or package you use in this app, or config something with these packages (such as jQuery, Bootstrap, Font-Awesome, Ionicons, Material, ...):
252 | + You also create `index.js` in `lib` to import these files in folder.
253 | + In `index.js` in root, you only import by one line: `import './lib';`
254 |
255 | ## Utility service
256 | Create `services` to contain your services for app. Guides are below sections
257 |
258 | ## Reducers - Actions
259 | Create `actions`, `reducers` to do with `redux`. Guides are below sections
260 |
261 | ## Components
262 | Create `components` to contain components in app:
263 | Guides for these components is below sections
264 |
265 | ### Layout Components
266 | - Create `layout` in `components` to contain layout of app (flow).
267 | - Your `App.js`, `App.scss` also in here, which import `Header`, `Footer`, `Sidebar`, `Menu`, `Body`,... for Navigations and Router
268 |
269 | ### Common Components
270 | Create `common` in `components` to contain some components which are used a lot of times. Such as `Loading`, `Modal`, `Alert`, `Notification`, `Box`, ...
271 |
272 | ### Pages Components
273 | Create `pages` in `components` to contain some pages in app, which is route in component `Body`, such as `Home`, `Dashboard`, `Profile`, `Form`, `Terms of Service`, `Support`, `Page not found`, `Error page`,...
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 | # jQuery
282 |
283 | ## Installation
284 | 1. In terminal: `yarn add jquery`
285 | 2. In terminal: `touch src/lib/jquery.js`
286 | 3. Edit created file by the following lines:
287 |
288 | ```js
289 | import $ from 'jquery';
290 |
291 | // config jquery variables for other lib use jQuery (such as bootstrap)
292 | window.$ = $;
293 | window.jQuery = $;
294 | ```
295 |
296 | ## How to use?
297 | 1. In `lib/index.js`, import by: `import './jquery';`
298 | 2. In `index.js` at root, `import './lib';` (if you don't have).
299 | 3. In the component, to use jQuery, you should import: `import $ from 'jquery';`
300 | 4. To use jquery function, only use from `componentDidMount()` in Lifecycle React components:
301 | 5. [View Demo here](https://huynhsamha.github.io/react-configure/jquery)
302 | 6. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-jquery/DemoJquery.jsx)
303 |
304 |
305 | ```javascript
306 | componentDidMount() {
307 | // jQuery should declare at here
308 | $(document).ready(() => {
309 | $('#alert').click(() => alert('This is alert be jQuery'));
310 | });
311 | }
312 | ```
313 |
314 |
315 | ## Recommend
316 | Not use jQuery if it's not needed
317 |
318 |
319 |
320 |
321 |
322 |
323 | # Bootstrap 3, 4
324 |
325 |
326 | ## Use along with jQuery
327 | ### Installation
328 | 1. In terminal: `yarn add bootstrap` (add @version you choose)
329 | 2. In terminal: `mkdir src/lib` (if you have `lib`, skip this step)
330 | 3. In terminal: `touch src/lib/bootstrap.js`
331 | 4. Edit created file as lines (In this tutorial, I use bootstrap 4):
332 |
333 | ```javascript
334 | import 'bootstrap/dist/css/bootstrap.min.css';
335 | import 'bootstrap/dist/js/bootstrap.bundle.min.js';
336 | ```
337 |
338 | ### How to use?
339 | 1. In `lib/index.js`, import by: `import './bootstrap';`
340 | 2. In `index.js` at root, `import './lib';` (if you don't have).
341 | 3. In the component, you can use bootstrap 3, 4 as document available
342 | 4. View demo with component `DemoBootstrap`.
343 | 5. [View Demo here](https://huynhsamha.github.io/react-configure/bootstrap)
344 | 6. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-bootstrap/DemoBootstrap.jsx)
345 |
346 |
347 |
348 |
349 | ## Use via React Component - `reactstrap`
350 |
351 | ### Installation and Usage
352 | 1. In terminal: `yarn add reactstrap@next`
353 | 2. Only import Component to use as reactstrap document
354 | 3. View demo with component `DemoReactstrap`.
355 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/reactstrap)
356 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-reactstrap/DemoReactstrap.jsx)
357 |
358 | ## Recommend
359 | 1. I think you should use `reactstrap` if you want to use some component in react, with event handlers.
360 | 2. If you need some style in bootstrap, you can use directly and don't need to use `jQuery`
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 | # Font Awesome
369 | ## Add via `index.html`
370 |
371 | You can include via file `index.html` in folder `public` via `CDN` or download and `link stylesheet`
372 |
373 |
374 | ## Add via npm package
375 |
376 | 1. In terminal: `yarn add font-awesome`
377 | 2. Create file `lib/font-awesome.js` and add line `import 'font-awesome/css/font-awesome.min.css';`
378 | 3. In `lib/index.js`, import by: `import './font-awesome';`
379 | 4. In `index.js` at root, `import './lib';` (if you don't have).
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 | # Animate.css
389 | ## Install and configure
390 | 1. `yarn add animate.css`
391 | 2. In `lib/` create file `animate-css.js` and add `import 'animate.css';`
392 | 3. In `index.js`, also import by line `import './animate-css';`
393 |
394 | ## Custom duration time
395 | 1. Custom duration of animation by file scss config in `style/`:
396 | 2. Create file `_animate.scss` as source code
397 | 3. In `index.scss`: `@import './animate.scss';`
398 | 4. This file will create classes style to custom time duration:
399 | ```
400 | .animated.duration-100
401 | .animated.duration-200
402 | ...
403 | .animated.duration-1100
404 | .animated.duration-1200
405 | ...
406 | .animated.duration-3000
407 | ```
408 |
409 | ## How to use
410 | Example:
411 | ```html
412 |
413 | ABCDEFGHIJKLMNOP
414 | ABCDEFGHIJKLMNOP
415 | ABCDEFGHIJKLMNOP
416 |
417 | ABCDEFGHIJKLMNOP
418 | ABCDEFGHIJKLMNOP
419 | ABCDEFGHIJKLMNOP
420 |
421 | ABCDEFGHIJKLMNOP
422 | ABCDEFGHIJKLMNOP
423 | ```
424 |
425 |
426 | ## Demo
427 | + View demo at component `DemoAnimateCss`
428 | + [View Demo here](https://huynhsamha.github.io/react-configure/animate-css)
429 | + [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-animate-css/DemoAnimateCss.jsx)
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 | # `react-router-dom` (router)
439 | `react-router-dom` is used for route Single Page Application (SPA), not loading again page.
440 |
441 | 1. In terminal: `yarn add react-router-dom`
442 | 2. You can view implement in `components/layout/body`
443 | 3. You also view implement in `components/pages/demo-react-router`
444 | 4. The Document is available at [React Router Dom](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom)
445 |
446 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-router)
447 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-router/DemoReactRouter.jsx)
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 | # `react-loadable` (code-splitting)
456 |
457 | ## Installation, Usage
458 |
459 | `react-loadable` is useful for code-splitting:
460 | + Lazy load components until it's called by user, it speeds up your Single Page App (SPA).
461 | + `create-react-app` will bundle a new script file, when it's called, it will import this file to app.
462 |
463 | 1. In terminal: `yarn add react-loadable react-router-dom`
464 | 2. Create Loading component (view components/common/loading/)
465 | 3. When use Loadable with loading component, it will add props to this component, such as:
466 | `{ isLoading: true, pastDelay: false, timedOut: false, error: null }`
467 | 4. View `components/page/demo-loadable-component` to sample implement.
468 | 5. Component `DemoLoadableComponent` (is not loadable) and `LoadableDemoComponent` (is loadable)
469 |
470 | ## Test Loadable Components - code-splitting
471 | 1. Inspect element in the browser
472 | 2. Choose tab network
473 | 3. Click filter JS
474 | 4. Refresh page
475 | 5. First only `bundle.js` and some js file
476 | 6. Click component which loadable, you see `*.chunk.js` is loaded. That is lazy loading component
477 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-loadable)
478 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-router/DemoReactRouter.jsx)
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 | # `react-intl` - API to format date, number and string
489 | Internationalize React apps. This library provides React components and an API to format dates, numbers, and strings, including pluralization and handling translations.
490 |
491 | ## Features
492 | + Display numbers with separators.
493 | + Display dates and times correctly.
494 | + Display dates relative to "now".
495 | + Pluralize labels in strings.
496 | + Support for 150+ languages.
497 | + Runs in the browser and Node.js.
498 | + Built on standards.
499 |
500 | ## Document
501 | You can view the document here: [https://github.com/yahoo/react-intl](https://github.com/yahoo/react-intl)
502 |
503 |
504 | ## Usage in this tutorial
505 | 1. In `index.js`, we import and use provider for App component:
506 |
507 | ```jsx
508 | import { IntlProvider } from 'react-intl';
509 |
510 | ReactDOM.render(
511 |
512 |
513 |
514 |
515 |
516 | ,
517 |
518 | document.getElementById('root')
519 | );
520 | ```
521 |
522 | 2. In specific component, you can import component of `react-intl` to use. You can view 1 demo about this in demo redux with format date.
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 | # Redux: `redux, react-redux, redux-thunk`
533 |
534 | ## Installation
535 | `yarn add redux react-redux redux-thunk`
536 |
537 | ## Usage
538 | 1. In `src`, create dir and files:
539 | + `actions/action-types.js`: declare action name as const
540 | + `actions/index.js`: declare actions for redux
541 | + `reducers/`: declare reducers
542 | + `reducers/[name].js`: declare action for a specific object.
543 | + `reducers/index.js`: to combine reducer with redux, after that is to createStore.
544 |
545 | 2. In `index.js`:
546 | + `import { Provider } from 'react-redux';`: use Provider to store redux
547 | + `import { createStore, applyMiddleware } from 'redux';`: use createStore and middleware `thunk` with createStore
548 | + `import thunk from 'redux-thunk';`: middleware for createStore, support async function
549 | + `import allReducers from './reducers';`: reducers after combined
550 | + `const store = createStore(allReducers, applyMiddleware(thunk));`: createStore with combined reducer, and apply middleware thunk
551 | + You don't care about other reducers, such as `Users`
552 |
553 | 3. In `reducers/index.js`: combine reducers:
554 | + In this tutorial, I demo with Items and Users (users is used for other section demos).
555 | ```js
556 | import { combineReducers } from 'redux';
557 |
558 | import Items from './items';
559 | import Users from './users';
560 |
561 | const reducers = combineReducers({
562 | Items,
563 | Users
564 | });
565 |
566 | export default reducers;
567 | ```
568 |
569 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/redux)
570 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-redux/DemoRedux.jsx)
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 | # Fetch Data API to the server node
586 | ## Create `services` to get API
587 | 1. `mkdir src/services` (if you have not)
588 | 2. `touch db-service.js auth-service.js` (db- to get database, auth- to authentication user)
589 | 3. Example with `db-service.js`:
590 | + `import Env from './../environments';`: to get `baseUrl` with environments
591 | + `export default class DbService` as static class
592 | + set baseUrl to get API:
593 | ```jsx
594 | static baseUrl() { return Env.baseUrl; }
595 | static parseUrl(url) { return DbService.baseUrl() + url; }
596 | ```
597 |
598 | Example `get` API:
599 | ```js
600 | static getItems = () => {
601 | let url = DbService.parseUrl('/api/items');
602 | console.log(url);
603 | return fetch(url).then(res => res.json());
604 | }
605 | ```
606 |
607 | Example `Post` API:
608 | ```js
609 | static addItem = (item) => {
610 | let url = DbService.parseUrl('/api/items');
611 | return fetch(url, {
612 | method: 'POST',
613 | headers: {
614 | 'Accept': 'application/json',
615 | 'Content-Type': 'application/json'
616 | },
617 | body: JSON.stringify(item)
618 | }).then(res => res.json());
619 | }
620 | ```
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 | # UI Awesome with React Component
636 |
637 |
638 | ## Reveal Component on scroll: use `react-reveal`
639 |
640 | Animation to show component when user scroll to view.
641 |
642 | ### Installation
643 | `yarn add react-reveal`
644 |
645 | ### Support
646 |
647 | #### Reveal with React
648 | ```
649 | Fade
650 | Flip
651 | Rotate
652 | Zoom
653 | Bounce
654 | Slide
655 | Roll
656 |
657 | left/right/top/bottom
658 | fadeOut
659 | ```
660 | #### Animated.css with React
661 | ```
662 | Jump
663 | Flash
664 | HeadShake
665 | Jello
666 | Pulse
667 | RubberBand
668 | Shake
669 | Spin
670 | Swing
671 | Tada
672 | ```
673 |
674 | ### How to use?
675 | 1. Use http://www.react-reveal.com/examples/.
676 | 2. View demo with component `DemoReactReveal`.
677 |
678 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-reveal)
679 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-reveal/DemoReactReveal.jsx)
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 | ## Scroll animated to target - react-scrollchor
690 |
691 | Animation to scroll to a component when user clicks to the link.
692 |
693 | ### Installation
694 | `yarn add react-scrollchor`
695 |
696 |
697 | ### How to use?
698 | 1. Use https://github.com/bySabi/react-scrollchor
699 | 2. View demo with component `DemoReactScrollchor`.
700 |
701 | 4. [View Demo here](https://huynhsamha.github.io/react-configure/react-scrollchor)
702 | 5. [View Implementation here](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-scrollchor/DemoReactScrollchor.jsx)
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 | # Datatable with `react-table`
711 | 1. View demo for this guide here: [Demo](https://huynhsamha.github.io/react-configure/react-table)
712 | 2. View implementation in [`demo-react-table` - Implementation](https://github.com/huynhsamha/react-configure/blob/master/src/components/pages/demo-react-table/DemoReactTable.jsx)
713 | 3. In this guide, we use [`react-table`](https://react-table.js.org/#/story/readme) with features:
714 | + Lightweight at 11kb (and just 2kb more for styles)
715 | + Fully customizable (JSX, templates, state, styles, callbacks)
716 | + Client-side & Server-side pagination
717 | + Multi-sort
718 | + Filters
719 | + Pivoting & Aggregation
720 | + Minimal design & easily themeable
721 | + Fully controllable via optional props and callbacks
722 | 4. In this guide, we also use `react-select` and `react-datepicker` with `moment`. You can view docs for these packages here:
723 | + [`react-select` - Demo](http://jedwatson.github.io/react-select/)
724 | + [`react-select` - Docs](https://github.com/JedWatson/react-select)
725 | + [`react-datepicker` - Demo](https://reactdatepicker.com/)
726 | + [`react-datepicker` - Docs](https://github.com/Hacker0x01/react-datepicker)
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 | # VS Code Extensions
738 | I think the following extensions are helpful for development:
739 |
740 | ## Icons, Colors, View
741 | - [vscode-icons](https://marketplace.visualstudio.com/items?itemName=robertohuertasm.vscode-icons)
742 | - [Bracket Pair Colorizer](https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer)
743 |
744 | ## Snippets
745 | - [ES7 React/Redux/GraphQL/React-Native snippets](https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets)
746 | - [JavaScript (ES6) code snippets](https://marketplace.visualstudio.com/items?itemName=xabikos.JavaScriptSnippets)
747 | - [Bootstrap 3 Snippets](https://marketplace.visualstudio.com/items?itemName=wcwhitehead.bootstrap-3-snippets)
748 | - [Bootstrap 4 & Font awesome snippets](https://marketplace.visualstudio.com/items?itemName=thekalinga.bootstrap4-vscode)
749 | - [Font-awesome codes for html](https://marketplace.visualstudio.com/items?itemName=medzhidov.font-awesome-codes-html)
750 | - [Font-awesome codes for css](https://marketplace.visualstudio.com/items?itemName=medzhidov.font-awesome-codes-css)
751 | - [HTML Snippets](https://marketplace.visualstudio.com/items?itemName=abusaidm.html-snippets)
752 | - [HTML CSS support](https://marketplace.visualstudio.com/items?itemName=ecmel.vscode-html-css)
753 |
754 | ## Intellisence
755 | - [npm](https://marketplace.visualstudio.com/items?itemName=eg2.vscode-npm-script)
756 | - [npm Intellisence](https://marketplace.visualstudio.com/items?itemName=christian-kohler.npm-intellisense)
757 | - [Path Intellisense](https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense)
758 | - [SCSS IntelliSence](https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-scss)
759 | - [Auto Close Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-close-tag)
760 | - [Auto Rename Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag)
761 | - [IntelliSense for CSS class names](https://marketplace.visualstudio.com/items?itemName=Zignd.html-css-class-completion)
762 |
763 | ## Lint Code, Formater
764 | - [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
765 | - [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig)
766 | - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
767 | - [TSLint](https://marketplace.visualstudio.com/items?itemName=eg2.tslint)
768 | - [Sass](https://marketplace.visualstudio.com/items?itemName=robinbentley.sass-indented)
769 | - [Sass Formatter](https://marketplace.visualstudio.com/items?itemName=sasa.vscode-sass-format)
770 | - [Beautify css/sass/scss/less](https://marketplace.visualstudio.com/items?itemName=michelemelluso.code-beautifier)
771 |
772 |
773 | ## Edit, Preview README - Markdown files
774 | - [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one)
775 | - [Markdown Preview Enhanced](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced)
776 | - [Markdown PDF](https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf)
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 | # VS Code User Settings
809 |
810 | I think you also setting your VSCode by following steps:
811 |
812 | 1. Enter `Ctrl + Shift P`
813 | 2. Search `user settings`
814 | 3. Choose `Preferences: Open User Settings` and enter.
815 | 4. Edit your file `User Settings` by following lines:
816 | (you can search in `Default Settings` and customize your style)
817 |
818 | ```json
819 | {
820 | "workbench.iconTheme": "vscode-icons",
821 | "workbench.startupEditor": "newUntitledFile",
822 | "window.zoomLevel": 0,
823 | "editor.fontSize": 13,
824 | "eslint.autoFixOnSave": true,
825 | "tslint.autoFixOnSave": true,
826 | "editor.formatOnSave": false,
827 | "editor.renderWhitespace": "boundary",
828 | "editor.quickSuggestions": {
829 | "other": true,
830 | "comments": true,
831 | "strings": true
832 | },
833 | "terminal.integrated.cursorStyle": "line",
834 | "terminal.integrated.fontSize": 13,
835 | "terminal.integrated.fontFamily": "",
836 | "vsicons.projectDetection.autoReload": true,
837 | }
838 | ```
839 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-app",
3 | "version": "1.0.0",
4 | "private": true,
5 | "homepage": "https://huynhsamha.github.io/react-configure",
6 | "scripts": {
7 | "start": "npm-run-all -p watch-css start-js",
8 | "build": "npm-run-all build-css build-js",
9 | "start-js": "react-scripts start",
10 | "build-js": "react-scripts build",
11 | "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
12 | "build-css": "node-sass-chokidar src/ -o src/",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject",
15 | "eslint": "eslint --ext=js --ext=jsx server.js src/ server/",
16 | "eslint:fix": "eslint --ext=js --ext=jsx server.js src/ server/ --fix",
17 | "predeploy": "yarn build",
18 | "deploy": "gh-pages -d build"
19 | },
20 | "dependencies": {
21 | "animate.css": "^3.6.1",
22 | "babel-eslint": "^8.2.1",
23 | "body-parser": "~1.18.2",
24 | "bootstrap": "^4.0.0",
25 | "cookie-parser": "~1.4.3",
26 | "cors": "^2.8.4",
27 | "debug": "~2.6.9",
28 | "express": "~4.15.5",
29 | "font-awesome": "^4.7.0",
30 | "jquery": "^3.3.1",
31 | "match-sorter": "^2.2.0",
32 | "moment": "^2.20.1",
33 | "morgan": "~1.9.0",
34 | "node-sass-chokidar": "0.0.3",
35 | "npm-run-all": "^4.1.2",
36 | "prop-types": "^15.6.0",
37 | "react": "^16.2.0",
38 | "react-datepicker": "^1.1.0",
39 | "react-dom": "^16.2.0",
40 | "react-intl": "^2.4.0",
41 | "react-loadable": "^5.3.1",
42 | "react-redux": "^5.0.6",
43 | "react-reveal": "^1.0.0",
44 | "react-router-dom": "^4.2.2",
45 | "react-scripts": "1.1.0",
46 | "react-scrollchor": "^4.2.1",
47 | "react-select": "^1.2.1",
48 | "react-table": "^6.7.6",
49 | "reactstrap": "^5.0.0-beta",
50 | "redux": "^3.7.2",
51 | "redux-thunk": "^2.2.0",
52 | "uniqid": "^4.1.1"
53 | },
54 | "devDependencies": {
55 | "eslint": "^4.17.0",
56 | "eslint-config-airbnb": "^16.1.0",
57 | "eslint-plugin-import": "^2.8.0",
58 | "eslint-plugin-jsx-a11y": "^6.0.3",
59 | "eslint-plugin-react": "^7.6.1",
60 | "gh-pages": "^1.1.0"
61 | },
62 | "engines": {
63 | "node": ">=6.10.0 <=10.21.0",
64 | "npm": ">=3.10.8"
65 | },
66 | "keywords": [
67 | "react",
68 | "create-react-app",
69 | "code-splitting",
70 | "redux",
71 | "redux-thunk",
72 | "reactjs",
73 | "react-router",
74 | "react-redux",
75 | "react-router-dom",
76 | "starter-kit",
77 | "sass",
78 | "step",
79 | "react-loadable",
80 | "react-scrollchor",
81 | "scroll",
82 | "react-intl",
83 | "animate.css",
84 | "animate",
85 | "react-select",
86 | "moment",
87 | "momentjs",
88 | "react-datepicker",
89 | "datepicker",
90 | "create-react-app-configure",
91 | "react-configure"
92 | ]
93 | }
94 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huynhsamha/react-configure/076320259ff3524da352cfb9b62068d12affb627/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
33 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var express = require('express');
4 | var path = require('path');
5 | var logger = require('morgan');
6 | var cookieParser = require('cookie-parser');
7 | var bodyParser = require('body-parser');
8 | var http = require('http');
9 | var cors = require('cors');
10 |
11 | var app = express();
12 |
13 | app.use(logger('dev'));
14 | app.use(bodyParser.json());
15 | app.use(bodyParser.urlencoded({ extended: false }));
16 | app.use(cookieParser());
17 | app.use(express.static(path.join(__dirname, 'build'))); // use for deploy production with build/
18 |
19 | app.use(cors());
20 |
21 | var route = require('./server/routes');
22 |
23 | app.use(route);
24 |
25 | // catch 404 and forward to error handler
26 | app.use((req, res, next) => {
27 | var err = new Error('Not Found');
28 | err.status = 404;
29 | next(err);
30 | });
31 |
32 | // error handler
33 | app.use((err, req, res, next) => {
34 | // set locals, only providing error in development
35 | res.locals.message = err.message;
36 | res.locals.error = req.app.get('env') === 'development' ? err : {};
37 |
38 | // render the error page
39 | res.status(err.status || 500);
40 | res.render('error');
41 | });
42 |
43 | var port = process.env.PORT || '4200';
44 | app.set('port', port);
45 |
46 | var server = http.createServer(app);
47 |
48 | server.listen(port, () => console.log(`Running on localhost:${port}`));
49 |
--------------------------------------------------------------------------------
/server/routes/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 |
3 | var router = express.Router();
4 |
5 | /* GET home page. */
6 | router.get('/', (req, res, next) => {
7 | res.render('index', { title: 'Express' });
8 | });
9 |
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/src/actions/action-types.js:
--------------------------------------------------------------------------------
1 | export default {
2 | ADD_ITEM: 'ADD_ITEM',
3 | REMOVE_ITEM: 'REMOVE_ITEM',
4 | MOVE_ITEM: 'MOVE_ITEM',
5 |
6 | REMOVE_USER: 'REMOVE_USER',
7 |
8 | ADD_TODO: 'ADD_TODO',
9 | REMOVE_TODO: 'REMOVE_TODO',
10 | DONE_TODO: 'DONE_TODO',
11 | MODIFY_TODO: 'MODIFY_TODO'
12 | };
13 |
--------------------------------------------------------------------------------
/src/actions/index.js:
--------------------------------------------------------------------------------
1 | import actionTypes from './action-types';
2 |
3 | export const addItem = item => ({
4 | type: actionTypes.ADD_ITEM,
5 | item
6 | });
7 |
8 | export const removeItem = id => ({
9 | type: actionTypes.REMOVE_ITEM,
10 | id
11 | });
12 |
13 | export const editItem = (id, newItem) => ({
14 | type: actionTypes.EDIT_ITEM,
15 | id,
16 | newItem
17 | });
18 |
19 | export const moveItem = (id, isUp) => ({
20 | type: actionTypes.MOVE_ITEM,
21 | id,
22 | isUp
23 | });
24 |
25 | export const removeUser = id => ({
26 | type: actionTypes.REMOVE_USER,
27 | id
28 | });
29 |
30 |
31 | export const addTodo = newTodo => ({
32 | type: actionTypes.ADD_TODO,
33 | newTodo
34 | });
35 |
36 | export const removeTodo = id => ({
37 | type: actionTypes.REMOVE_TODO,
38 | id
39 | });
40 |
41 | export const doneTodo = (id, isDone) => ({
42 | type: actionTypes.DONE_TODO,
43 | id, isDone
44 | });
45 |
46 | export const modifyTodo = (id, newTodo) => ({
47 | type: actionTypes.MODIFY_TODO,
48 | id, newTodo
49 | });
50 |
--------------------------------------------------------------------------------
/src/components/common/loading/Loading.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | import './Loading.css';
5 |
6 | const propTypes = {
7 | error: PropTypes.bool,
8 | timeOut: PropTypes.bool,
9 | pastDelay: PropTypes.bool
10 | };
11 |
12 | const defaultProps = {
13 | error: false, timeOut: false, pastDelay: false
14 | };
15 |
16 | class Loading extends Component {
17 | constructor(props) {
18 | super(props);
19 |
20 | this.state = {};
21 | }
22 |
23 | render() {
24 | /**
25 | * console.log(this.props);
26 | * {isLoading: true, pastDelay: false, timedOut: false, error: null}
27 | */
28 | if (this.props.error) {
29 | return Error
;
30 | } else if (this.props.timeOut) {
31 | return Time out
;
32 | } else if (!this.props.pastDelay) {
33 | // delay Loading Component show on screen 200ms (be default, can be set in Loadable)
34 | // if after 200ms, component has just loaded, Loading will show.
35 | return null;
36 | }
37 | return (
38 |
39 |
40 | Loading...
41 |
42 |
43 | );
44 | }
45 | }
46 |
47 | Loading.propTypes = propTypes;
48 | Loading.defaultProps = defaultProps;
49 |
50 | export default Loading;
51 |
--------------------------------------------------------------------------------
/src/components/common/loading/Loading.scss:
--------------------------------------------------------------------------------
1 | .Loading {
2 | position: fixed;
3 | top: 0;
4 | left: 0;
5 | width: 100%;
6 | height: 100%;
7 | background-color: rgba(0,0,0,0.7);
8 | .LoadingText {
9 | color: white;
10 | font-size: 25px;
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | transform: translate(-50%, -50%);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/components/layout/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './App.css';
3 |
4 | import Header from './header/Header';
5 | import Footer from './footer/Footer';
6 | import Body from './body/Body';
7 |
8 | class App extends Component {
9 |
10 | constructor(props) {
11 | super(props);
12 |
13 | this.state = {};
14 | }
15 |
16 | render() {
17 | return (
18 |
19 |
20 |
21 |
22 |
23 | );
24 | }
25 | }
26 |
27 | export default App;
28 |
--------------------------------------------------------------------------------
/src/components/layout/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | height: 100%;
3 | width: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/components/layout/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render( , div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/src/components/layout/body/Body.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
3 |
4 | import LifeCycleReactComponent from './../../pages/lifecycle-component';
5 | import DemoJquery from './../../pages/demo-jquery/DemoJquery';
6 | import DemoBootstrap from './../../pages/demo-bootstrap/DemoBootstrap';
7 | import DemoReactstrap from './../../pages/demo-reactstrap/DemoReactstrap';
8 | import DemoLoadableComponent from './../../pages/demo-loadable-component/LoadableDemoComponent';
9 | import DemoReactRouter from './../../pages/demo-react-router/DemoReactRouter';
10 | import DemoReactReveal from './../../pages/demo-react-reveal/DemoReactReveal';
11 | import DemoReactScrollchor from './../../pages/demo-react-scrollchor/DemoReactScrollchor';
12 | import DemoRedux from './../../pages/demo-redux/DemoRedux';
13 | import DemoAnimateCss from './../../pages/demo-animate-css/DemoAnimateCss';
14 | import DemoReactTable from './../../pages/demo-react-table/DemoReactTable';
15 |
16 | import('./Body.css').then().catch(err => console.log(err));
17 |
18 | export default class Body extends Component {
19 | render() {
20 | return (
21 |
22 |
23 |
24 |
25 |
26 |
27 | Demo Jquery
28 | Demo Bootstrap
29 | Demo Reactstrap
30 | Demo React Router
31 | Demo react-loadable
32 | Demo react-reveal
33 | Demo react-scrollchor
34 | Demo Redux
35 | Demo animate.css
36 | Demo react-table
37 | Go to link not found
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | 404 Page Not Found
} />
56 |
57 |
58 |
59 |
60 |
61 |
62 | );
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/layout/body/Body.scss:
--------------------------------------------------------------------------------
1 | .Body {
2 | width: 100%;
3 | margin: 0 auto;
4 | line-height: 1.5;
5 | padding: 30px 0px;
6 |
7 | .Body-left {
8 | border-right: #cacaca 1.5px solid;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/components/layout/footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './Footer.css';
3 |
4 | export default class Footer extends Component {
5 |
6 | render() {
7 | return (
8 |
9 | Footer
10 |
11 | );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/layout/footer/Footer.scss:
--------------------------------------------------------------------------------
1 | @import './../../../styles/variables.scss';
2 | .Footer {
3 | position: fixed;
4 | bottom: 0;
5 | left: 0;
6 | width: 100%;
7 | min-height: 30px;
8 | line-height: 30px;
9 | background-color: $blue;
10 | text-align: center;
11 | font-family: $font-family-Open-Sans;
12 | font-weight: 900;
13 | font-size: $font-size-medium;
14 | color: white;
15 | letter-spacing: 2px;
16 | text-transform: uppercase;
17 | z-index: $z-index-max;
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/layout/header/Header.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './Header.css';
3 |
4 | export default class Header extends Component {
5 | render() {
6 | return (
7 |
8 | Header
9 |
10 | );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/layout/header/Header.scss:
--------------------------------------------------------------------------------
1 | @import './../../../styles/variables.scss';
2 | .Header {
3 | width: 100%;
4 | height: 30px;
5 | line-height: 30px;
6 | background-color: $green;
7 | text-align: center;
8 | font-family: $font-family-Open-Sans;
9 | font-weight: 900;
10 | font-size: $font-size-medium;
11 | color: white;
12 | z-index: $z-index-max;
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/pages/demo-animate-css/DemoAnimateCss.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | import('./DemoAnimateCss.css');
5 |
6 | export default class DemoAnimateCss extends Component {
7 | constructor(props) {
8 | super(props);
9 |
10 | document.title = 'Demo Animate.css';
11 | }
12 |
13 | render() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 | bounceIn 1.0s
21 |
22 |
23 |
24 |
25 | bounceInUp 2.5s
26 |
27 |
28 |
29 |
30 | bounceOut 2.9s
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | fadeIn 1.2s
40 |
41 |
42 |
43 |
44 | fadeInUp 0.7s
45 |
46 |
47 |
48 |
49 | fadeOutDown 2.7s
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | lightSpeedIn 1.7s
59 |
60 |
61 |
62 |
63 | rotateIn 1.0s
64 |
65 |
66 |
67 |
68 | zoomIn 1.4s
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | jackInTheBox 3.0s
78 |
79 |
80 |
81 |
82 | rollIn 2.9s
83 |
84 |
85 |
86 |
87 | bounceOut 1.3s
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | flash 2.3s
97 |
98 |
99 |
100 |
101 | rubberBand 2.6s
102 |
103 |
104 |
105 |
106 | jello 2.5s
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | shake 2.9s
116 |
117 |
118 |
119 |
120 | tada 2.6s
121 |
122 |
123 |
124 |
125 | wobble 2.5s
126 |
127 |
128 |
129 |
130 | );
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/components/pages/demo-animate-css/DemoAnimateCss.scss:
--------------------------------------------------------------------------------
1 | .Animate-CSS {
2 | .box {
3 | margin-top: 15px;
4 | height: 70px;
5 | line-height: 70px;
6 | text-align: center;
7 | padding: 10px;
8 | div.animated {
9 | background-color: #99c1fa;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/pages/demo-bootstrap/DemoBootstrap.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import $ from 'jquery';
4 | import 'bootstrap';
5 | /**
6 | * import 'bootstrap'; is unnecessary
7 | * If import, we can see method Bootstrap from $ variable
8 | * such as: $('#modalAlert').modal('hide');
9 | * We still use this method if not import.
10 | */
11 |
12 | export default class DemoBootstrap extends Component {
13 | constructor(props) {
14 | super(props);
15 |
16 | document.title = 'Demo Bootstrap';
17 | this.onClickReceviceAlert = this.onClickReceviceAlert.bind(this);
18 | }
19 |
20 | componentDidMount() {
21 | $('#btnToggle').tooltip();
22 | }
23 |
24 | onClickReceviceAlert() {
25 | alert('This is alert');
26 | $('#modalAlert').modal('hide');
27 | }
28 |
29 | render() {
30 | return (
31 |
32 |
42 | Launch demo modal
43 |
44 |
45 |
46 |
47 |
48 |
49 |
Warning
50 |
51 | ×
52 |
53 |
54 |
55 | Do you want to get an alert?
56 |
57 |
58 | Close
59 | OK
60 |
61 |
62 |
63 |
64 |
65 | );
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/components/pages/demo-jquery/DemoJquery.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import $ from 'jquery';
4 |
5 | import('./DemoJquery.css');
6 |
7 | export default class DemoJquery extends Component {
8 | constructor(props) {
9 | super(props);
10 |
11 | document.title = 'Demo Jquery';
12 | }
13 |
14 | componentDidMount() {
15 | $('#btnToggle').click(() => {
16 | console.log('Toggle');
17 | const $banner = $('#banner');
18 | $banner.slideToggle();
19 | });
20 | }
21 |
22 | render() {
23 | return (
24 |
25 |
Click to toggle image
26 |
27 |
28 |
33 |
34 |
35 | );
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/pages/demo-jquery/DemoJquery.scss:
--------------------------------------------------------------------------------
1 | @import './../../../styles/variables.scss';
2 |
3 | .DemoJquery {
4 | .jq-button {
5 | $bg: #134bd0;
6 | padding: 6px 20px;
7 | background-color: $bg;
8 | border-radius: 30px;
9 | border: 2px $bg solid;
10 | color: white;
11 | transition-duration: 0.2s;
12 | outline: none;
13 | margin-bottom: 20px;
14 | cursor: pointer;
15 | &:hover {
16 | background-color: white;
17 | border-radius: 0px;
18 | padding: 6px 50px;
19 | color: $bg;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/pages/demo-loadable-component/DemoLoadableComponent.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | export default class DemoLoadableComponent extends Component {
4 | constructor(props) {
5 | super(props);
6 |
7 | document.title = 'Loadable Component';
8 | }
9 |
10 | render() {
11 | return (
12 | Loadable Component
13 | );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/pages/demo-loadable-component/LoadableDemoComponent.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Loadable from 'react-loadable';
3 | import Loading from './../../common/loading/Loading';
4 |
5 | const LoadableComponent = Loadable({
6 | loader: () => import('./DemoLoadableComponent.jsx'),
7 | loading: Loading,
8 | delay: 300, // default is 200
9 | timeout: 10000
10 | });
11 |
12 | export default class LoadableDemoComponent extends Component {
13 | render() {
14 | return ;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-reveal/DemoReactReveal.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Fade, Flip, Rotate, Zoom, Slide, Roll, Bounce, LightSpeed } from 'react-reveal';
3 |
4 | const style = {
5 | width: '84%',
6 | margin: '25px auto',
7 | textAlign: 'justify'
8 | };
9 |
10 | export default class DemoReactReveal extends Component {
11 | constructor(props) {
12 | super(props);
13 |
14 | document.title = 'React Reveal';
15 |
16 | const text = 'One of the best ways to learn how to do anything new (including software APIs!) is to get your hands dirty as quickly as possible. These examples will show you how to perform tasks ranging from something as simple as applying DataTables to an HTML table, right the way through to doing server-side processing with pipelining and custom plug-in functions.';
17 |
18 | this.repeat = [];
19 | for (let i = 0; i < 1000; i++) this.repeat.push({ id: i, text });
20 | }
21 |
22 | render() {
23 | return (
24 |
25 | {this.repeat.map((o, i) => {
26 | const step = 50;
27 | if (i < step) {
28 | return (
29 |
37 | {o.text}
38 |
39 | );
40 | } else if (i < step * 2) {
41 | return (
42 |
50 | {o.text}
51 |
52 | );
53 | } else if (i < step * 3) {
54 | return (
55 |
63 | {o.text}
64 |
65 | );
66 | } else if (i < step * 4) {
67 | return (
68 |
76 | {o.text}
77 |
78 | );
79 | } else if (i < step * 5) {
80 | return (
81 |
89 | {o.text}
90 |
91 | );
92 | } else if (i < step * 6) {
93 | return (
94 |
102 | {o.text}
103 |
104 | );
105 | } else if (i < step * 7) {
106 | return (
107 |
115 | {o.text}
116 |
117 | );
118 | } else if (i < step * 8) {
119 | return (
120 |
128 | {o.text}
129 |
130 | );
131 | } else {
132 | return (
133 |
141 | {o.text}
142 |
143 | );
144 | }
145 | })}
146 |
147 | );
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-router/DemoReactRouter.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
4 | import LoadableImage from './LoadableImage';
5 | import Text from './Text';
6 | import UserList from './UserList';
7 | import UserProfile from './UserProfile';
8 |
9 | const propTypes = {
10 | location: PropTypes.object.isRequired,
11 | match: PropTypes.object.isRequired
12 | };
13 |
14 | class DemoReactRouter extends Component {
15 | constructor(props) {
16 | super(props);
17 |
18 | document.title = 'Demo React Router';
19 |
20 | console.log(this.props.location);
21 | console.log(this.props.match);
22 | // example:
23 | // {pathname: "/4", search: "", hash: "", state: undefined, key: "6hvrlm"}
24 | // {path: "/:userID", url: "/4", isExact: true, params: {userID: 4}}
25 | }
26 |
27 | render() {
28 | return (
29 |
30 |
31 |
32 |
33 | Loadable Image
34 | Unloadable Text
35 | User List
36 | Go to link not found
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | 404 Page Not Found
} />
45 |
46 |
47 |
48 |
49 | );
50 | }
51 | }
52 |
53 | DemoReactRouter.propTypes = propTypes;
54 |
55 | export default DemoReactRouter;
56 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-router/Images.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Fade, Zoom } from 'react-reveal';
3 |
4 | export default class Images extends Component {
5 |
6 | constructor(props) {
7 | super(props);
8 |
9 | document.title = 'Images';
10 | }
11 |
12 | render() {
13 | const array = [];
14 | for (let i = 0; i < 50; i++) array.push(i);
15 | const text = 'One of the best ways to learn how to do anything new (including software APIs!) is to get your hands dirty as quickly as possible. These examples will show you how to perform tasks ranging from something as simple as applying DataTables to an HTML table, right the way through to doing server-side processing with pipelining and custom plug-in functions.';
16 | return (
17 |
18 | {array.map(o =>
19 | (
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | ))}
30 |
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-router/LoadableImage.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Loadable from 'react-loadable';
3 | import Loading from './../../common/loading/Loading';
4 |
5 | const LoadableComponent = Loadable({
6 | loader: () => import('./Images.jsx'),
7 | loading: Loading
8 | });
9 |
10 | export default class LoadableImage extends Component {
11 | render() {
12 | return ;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-router/Text.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Fade, Zoom } from 'react-reveal';
3 |
4 | export default class Images extends Component {
5 |
6 | constructor(props) {
7 | super(props);
8 |
9 | document.title = 'Text';
10 |
11 | const text = 'One of the best ways to learn how to do anything new (including software APIs!) is to get your hands dirty as quickly as possible. These examples will show you how to perform tasks ranging from something as simple as applying DataTables to an HTML table, right the way through to doing server-side processing with pipelining and custom plug-in functions.';
12 |
13 | this.repeat = [];
14 | for (let i = 0; i < 1000; i++) this.repeat.push({ id: i, text });
15 | }
16 |
17 | render() {
18 | const text = 'One of the best ways to learn how to do anything new (including software APIs!) is to get your hands dirty as quickly as possible. These examples will show you how to perform tasks ranging from something as simple as applying DataTables to an HTML table, right the way through to doing server-side processing with pipelining and custom plug-in functions.';
19 | return (
20 |
21 | {this.repeat.map(o =>
22 | (o.id % 2 ?
23 |
{o.text}
:
24 |
{o.text}
))
25 | }
26 |
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-router/UserList.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router-dom';
3 | import { connect } from 'react-redux';
4 | import PropTypes from 'prop-types';
5 | import * as Actions from './../../../actions';
6 |
7 | class UserList extends Component {
8 |
9 | constructor(props) {
10 | super(props);
11 |
12 | document.title = 'User List';
13 | }
14 |
15 | handleClickRemoveUser(user) {
16 | const res = window.confirm(`Do you want to remove ${user.name}`);
17 | if (res) {
18 | this.props.removeUser(user.id);
19 | }
20 | }
21 |
22 | render() {
23 |
24 |
25 | return (
26 |
27 |
28 |
29 |
30 | #
31 | ID
32 | Email
33 | Name
34 | Address
35 | Salary ($)
36 | Action
37 |
38 |
39 |
40 | {this.props.userList.map((o, i) => (
41 |
42 | {i}
43 | {o.id}
44 | {o.email}
45 | {o.name}
46 | {o.address}
47 | {o.salary}
48 |
49 |
50 |
51 |
52 |
53 |
54 | { this.handleClickRemoveUser(o); }}
56 | role="button" tabIndex={0} onKeyUp={() => { }}
57 | style={{ cursor: 'pointer' }}
58 | >
59 |
60 |
61 |
62 |
63 | ))}
64 |
65 |
66 |
67 | );
68 | }
69 | }
70 |
71 | UserList.propTypes = {
72 | userList: PropTypes.array,
73 | removeUser: PropTypes.func.isRequired
74 | };
75 |
76 | UserList.defaultProps = {
77 | userList: []
78 | };
79 |
80 | const mapStateToProps = state => ({
81 | userList: state.Users
82 | });
83 |
84 | const mapDispatchToProps = dispatch => ({
85 | removeUser: (userID) => {
86 | dispatch(Actions.removeUser(userID));
87 | }
88 | });
89 |
90 | export default connect(mapStateToProps, mapDispatchToProps)(UserList);
91 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-router/UserProfile.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { connect } from 'react-redux';
4 |
5 |
6 | const propTypes = {
7 | match: PropTypes.object.isRequired,
8 | getUser: PropTypes.array.isRequired
9 | };
10 |
11 | class UserProfile extends Component {
12 | constructor(props) {
13 | super(props);
14 |
15 | this.userID = this.props.match.params.userID;
16 |
17 | this.user = this.props.getUser;
18 | console.log(this.user);
19 |
20 | if (this.user && this.user.length > 0) this.user = this.user[0];
21 | else this.user = {};
22 |
23 | document.title = `User ${this.user.name}`;
24 | }
25 |
26 | render() {
27 | return (
28 |
29 | Hello {this.user.name},
30 |
31 | );
32 | }
33 | }
34 |
35 | UserProfile.propTypes = propTypes;
36 |
37 | const mapStateToProps = (state, ownProps) => ({
38 | getUser: state.Users.filter(o => o.id == ownProps.match.params.userID)
39 | });
40 |
41 | export default connect(mapStateToProps)(UserProfile);
42 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-scrollchor/DemoReactScrollchor.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Scrollchor from 'react-scrollchor';
3 |
4 | import('./DemoReactScrollchor.css');
5 |
6 | const timeScroll = 300;
7 |
8 | function NavBarHeader() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 | Introduction(current)
25 |
26 |
27 |
28 |
32 | Installation
33 |
34 |
35 |
36 |
40 | Usage
41 |
42 |
43 |
44 |
48 | Image
49 |
50 |
51 |
52 |
56 | Footer
57 |
58 |
59 |
60 |
61 |
62 | );
63 | }
64 |
65 | function SectionIntro() {
66 | return (
67 |
68 |
react-scrollchor
69 |
70 |
A React component for scroll to #hash links with smooth animations. Scrollchor is a mix of Scroll and Anchor, a joke name for a useful component.
71 |
See it in action:
72 |
79 |
hash
is the id
of a HTML tag on current page.
80 |
81 |
82 |
83 | );
84 | }
85 |
86 | function SectionInstall() {
87 | return (
88 |
89 |
Installation
90 |
91 |
npm
92 |
npm install react-scrollchor --save
93 |
94 |
Dependencies
95 |
User should provide their own React package
96 |
fbjs is a collection of utility libraries created by React Team. It include useful modules like warning and invariant
97 |
98 |
99 |
100 | );
101 | }
102 |
103 | function SectionUsage() {
104 | return (
105 |
106 |
Usage
107 |
108 |
import Scrollchor from 'react-scrollchor';
109 |
110 | );
111 | }
112 |
113 | function SectionImage() {
114 | return (
115 |
116 |
Image React
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | );
125 | }
126 |
127 | function SectionFooter() {
128 | return (
129 |
134 | );
135 | }
136 |
137 | export default class DemoReactScrollChor extends Component {
138 |
139 | constructor(props) {
140 | super(props);
141 |
142 | document.title = 'Demo React Scrollchor';
143 | }
144 |
145 | render() {
146 | return (
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 | );
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-scrollchor/DemoReactScrollchor.scss:
--------------------------------------------------------------------------------
1 | @import './../../../styles/variables.scss';
2 |
3 | .DemoReactScrollchor {
4 | width: 100%;
5 | padding: 15px 10px;
6 | border: $blue 2px solid;
7 | position: relative;
8 |
9 | nav {
10 | font-size: $font-size-medium;
11 | position: absolute;
12 | top: 0px;
13 | left: 0px;
14 | width: 100%;
15 | img {
16 | border-radius: 6px;
17 | width: 35px;
18 | height: 35px;
19 | object-fit: cover;
20 | }
21 | }
22 |
23 | padding-top: 40px;
24 |
25 | .app-section {
26 | width: 100%;
27 | padding: 20px 10px;
28 | margin-top: 30px;
29 | &.footer {
30 | padding: 12px;
31 | background-color: $orange;
32 | a {
33 | color: white !important;
34 | font-size: $font-size-medium;
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-table/DemoReactTable.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { connect } from 'react-redux';
4 | import * as Actions from './../../../actions';
5 |
6 | import { FormattedDate, FormattedRelative, FormattedPlural } from 'react-intl';
7 |
8 | import ReactTable from 'react-table';
9 | import 'react-table/react-table.css';
10 |
11 | import matchSorter from 'match-sorter';
12 |
13 | import ModalEditTodo from './ModalEditTodo';
14 |
15 | import './style.css';
16 |
17 | const propTypes = {
18 | todos: PropTypes.array,
19 | removeTodo: PropTypes.func.isRequired
20 | };
21 |
22 | const defaultProps = {
23 | todos: []
24 | };
25 |
26 |
27 | class DemoReactTable extends Component {
28 |
29 | constructor(props) {
30 | super(props);
31 |
32 | document.title = 'Demo react-table';
33 |
34 | this.state = {
35 | modalIsOpen: false,
36 | modalData: {}
37 | };
38 |
39 | this.toggleModalEdit = this.toggleModalEdit.bind(this);
40 |
41 | console.log(this.props.todos);
42 | }
43 |
44 | onClickRemoveTodo(rowInfo) {
45 | console.log(rowInfo);
46 | const data = rowInfo.row;
47 | const res = window.confirm(`Do you want to remove todo ${data.id}`);
48 | if (res) {
49 | this.props.removeTodo(data.id);
50 | }
51 | }
52 |
53 | onClickEditTodo(rowInfo) {
54 | // console.log(rowInfo);
55 | const data = rowInfo.row;
56 | this.toggleModalEdit(data);
57 | }
58 |
59 | toggleModalEdit(data) {
60 | this.setState({
61 | modalIsOpen: !this.state.modalIsOpen,
62 | modalData: data
63 | });
64 | }
65 |
66 |
67 | renderModal() {
68 | return (
69 |
74 | );
75 | }
76 |
77 | render() {
78 |
79 | const { todos } = this.props;
80 |
81 | const columns = [
82 | {
83 | Header: props => ID ,
84 | accessor: 'id',
85 | minWidth: 80,
86 | filterAll: true,
87 | id: 'id',
88 | filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['id'] })
89 | },
90 | {
91 | Header: props => Content ,
92 | accessor: 'content',
93 | minWidth: 100,
94 | filterAll: true,
95 | id: 'content',
96 | filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['content'] })
97 | },
98 | {
99 | Header: props => Duration ,
100 | accessor: 'duration',
101 | maxWidth: 85,
102 | resizable: false,
103 | Cell: props => (
104 |
105 | {props.value}
106 |
107 | ),
108 | filterAll: true,
109 | id: 'duration',
110 | filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['duration'] })
111 | },
112 | {
113 | Header: props => Date Start ,
114 | accessor: 'dateStart',
115 | minWidth: 100,
116 | Cell: props => (
117 |
118 |
119 |
120 | )
121 | },
122 | {
123 | Header: props => Date End ,
124 | accessor: 'dateEnd',
125 | minWidth: 100,
126 | Cell: props => (
127 |
128 |
129 |
130 | )
131 | },
132 | {
133 | Header: props => Status ,
134 | accessor: 'process',
135 | width: 150,
136 | Cell: props => (
137 |
145 |
66 ? '#85cc00'
150 | : props.value > 33 ? '#ffbf00' : '#ff2e00',
151 | borderRadius: '2px',
152 | transition: 'all .2s ease-out',
153 | textAlign: 'center',
154 | color: '#fff',
155 | fontWeight: 900,
156 | fontSize: 12,
157 | display: 'table'
158 | }}
159 | >
160 | {props.value}%
161 |
162 |
163 | ),
164 | Filter: ({ filter, onChange }) => (
165 | { }}
167 | onChange={event => onChange(event.target.value)}
168 | style={{ width: '100%' }}
169 | value={filter ? filter.value : 'all'}
170 | >
171 | Show All
172 | Done
173 | Positive
174 | Doing
175 | Slow
176 | Plan
177 |
178 | ),
179 | filterMethod: (filter, row) => {
180 | const data = row[filter.id];
181 | switch (filter.value) {
182 | case 'all': return true;
183 | case '100': return data == 100;
184 | case '67-99': return data > 66 && data < 100;
185 | case '34-66': return data > 33 && data < 67;
186 | case '1-33': return data > 0 && data < 34;
187 | case '0': return data == 0;
188 | default: return false;
189 | }
190 | }
191 | },
192 | {
193 | Header: '',
194 | width: 30,
195 | filterable: false,
196 | sortable: false,
197 | resizable: false,
198 | id: 'btn-edit',
199 | Cell: props => (
200 |
201 |
202 |
203 |
204 |
205 | )
206 | },
207 | {
208 | Header: '',
209 | width: 30,
210 | filterable: false,
211 | sortable: false,
212 | resizable: false,
213 | id: 'btn-remove',
214 | Cell: props => (
215 |
216 |
217 |
218 |
219 |
220 | )
221 | }
222 | ];
223 |
224 | return (
225 |
226 |
Todos List
227 | {
234 | const id = filter.pivotId || filter.id;
235 | if (row[id] === undefined) return true;
236 | const data = String(row[id]).toLowerCase().trim();
237 | const text = String(filter.value).toLowerCase().trim();
238 | return data.includes(text);
239 | }}
240 | noDataText="No anything found"
241 | className="-striped -highlight react-table"
242 | getTdProps={(state, rowInfo, column) => ({
243 | onClick: (e) => {
244 | console.log(state);
245 | console.log(column);
246 | console.log(rowInfo);
247 | switch (column.id) {
248 | case 'btn-remove': return this.onClickRemoveTodo(rowInfo);
249 | case 'btn-edit': return this.onClickEditTodo(rowInfo);
250 | }
251 | }
252 | })}
253 | />
254 |
255 | {this.renderModal()}
256 |
257 | );
258 | }
259 | }
260 |
261 | DemoReactTable.propTypes = propTypes;
262 | DemoReactTable.defaultProps = defaultProps;
263 |
264 | const mapStateToProps = state => ({
265 | todos: state.Todos
266 | });
267 |
268 | const mapDispatchToProps = dispatch => ({
269 | removeTodo: id => dispatch(Actions.removeTodo(id))
270 | });
271 |
272 | export default connect(mapStateToProps, mapDispatchToProps)(DemoReactTable);
273 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-table/ModalEditTodo.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { connect } from 'react-redux';
4 | import * as Actions from './../../../actions';
5 |
6 | import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
7 |
8 | import Select from 'react-select';
9 | import 'react-select/dist/react-select.css';
10 |
11 | import DatePicker from 'react-datepicker';
12 | import 'react-datepicker/dist/react-datepicker.css';
13 | // import 'react-datepicker/dist/react-datepicker-cssmodules.css';
14 |
15 | import moment from 'moment';
16 |
17 |
18 | class ModalEditTodo extends Component {
19 |
20 | constructor(props) {
21 | super(props);
22 |
23 | this.processOptions = [];
24 | for (let i = 0; i < 101; i++) this.processOptions.push({
25 | value: `${i}`, label: `${i}%`
26 | });
27 |
28 | this.durationOptions = [];
29 | for (let i = 1; i < 900; i++) this.durationOptions.push({
30 | value: `${i}`, label: i + (i == 1 ? ' day' : ' days')
31 | });
32 |
33 | this.state = {
34 | process: 0,
35 | content: '',
36 | duration: 0,
37 | dateStart: moment(),
38 | dateEnd: moment()
39 | };
40 |
41 | this.handleChangeContent = this.handleChangeContent.bind(this);
42 | this.handleChangeProcess = this.handleChangeProcess.bind(this);
43 | this.handleChangeDuration = this.handleChangeDuration.bind(this);
44 | this.handleChangeDateStart = this.handleChangeDateStart.bind(this);
45 | this.handleChangeDateEnd = this.handleChangeDateEnd.bind(this);
46 | this.onSave = this.onSave.bind(this);
47 | this.onCancle = this.onCancle.bind(this);
48 | }
49 |
50 | componentWillReceiveProps(nextProps) {
51 | const { data } = nextProps;
52 |
53 | const process = data.process && this.processOptions.filter(o => o.value == data.process)[0];
54 | const duration = data.duration && this.durationOptions.filter(o => o.value == data.duration)[0];
55 |
56 | this.setState({
57 | process,
58 | duration,
59 | content: data.content,
60 | dateStart: moment(data.dateStart || new Date()),
61 | dateEnd: moment(data.dateEnd || new Date())
62 | });
63 | }
64 |
65 | onSave() {
66 | const res = window.confirm('Do you want to save with your edition?');
67 | if (res) {
68 | const newTodo = {
69 | content: this.state.content,
70 | process: parseInt(this.state.process.value, 10),
71 | duration: parseInt(this.state.duration.value, 10),
72 | dateStart: this.state.dateStart.toDate(),
73 | dateEnd: this.state.dateEnd.toDate()
74 | };
75 | // console.log(newTodo);
76 | this.props.modifyTodo(this.props.data.id, newTodo);
77 | this.props.toggle();
78 | }
79 | }
80 |
81 | onCancle() {
82 | const res = window.confirm('Do you want to close without saving your edtion?');
83 | if (res) {
84 | this.props.toggle();
85 | }
86 | }
87 |
88 | handleChangeContent(event) {
89 | this.setState({ content: event.target.value });
90 | }
91 |
92 | handleChangeProcess(process) {
93 | this.setState({ process });
94 | }
95 |
96 | syncDurationAfterSetDate() {
97 | console.log('syncDurationAfterSetDate');
98 | const diff = this.state.dateEnd.diff(this.state.dateStart);
99 | // console.log(diff);
100 | const days = moment.duration(diff).asDays();
101 | // console.log(days);
102 | const duration = this.durationOptions.filter(o => o.value == days)[0];
103 | // console.log(duration);
104 | this.setState({ duration });
105 | }
106 |
107 | handleChangeDuration(duration) {
108 | console.log('handleChangeDuration');
109 | const days = duration.value;
110 | const dateEnd = this.state.dateStart.clone();
111 | dateEnd.add(days, 'days');
112 | console.log(dateEnd);
113 | this.setState({ dateEnd }, () => this.syncDurationAfterSetDate());
114 | }
115 |
116 | handleChangeDateStart(dateStart) {
117 | console.log('handleChangeDateStart');
118 | this.setState({ dateStart }, () => this.syncDurationAfterSetDate());
119 | }
120 |
121 | handleChangeDateEnd(dateEnd) {
122 | console.log('handleChangeDa(teEnd');
123 | this.setState({ dateEnd }, () => this.syncDurationAfterSetDate());
124 | }
125 |
126 | renderFormEdit() {
127 | return (
128 |
206 | );
207 | }
208 |
209 | render() {
210 | return (
211 |
212 | Edit Todo
213 |
214 | {this.renderFormEdit()}
215 |
216 |
217 | Save {' '}
218 | Cancel
219 |
220 |
221 | );
222 | }
223 | }
224 |
225 | ModalEditTodo.propTypes = {
226 | data: PropTypes.object,
227 | isOpen: PropTypes.bool.isRequired,
228 | toggle: PropTypes.func,
229 | modifyTodo: PropTypes.func.isRequired
230 | };
231 |
232 | ModalEditTodo.defaultProps = {
233 | data: {},
234 | toggle: () => { }
235 | };
236 |
237 | const mapStateToProps = state => ({
238 | });
239 |
240 | const mapDispatchToProps = dispatch => ({
241 | modifyTodo: (id, newTodo) => dispatch(Actions.modifyTodo(id, newTodo))
242 | });
243 |
244 | export default connect(mapStateToProps, mapDispatchToProps)(ModalEditTodo);
245 |
--------------------------------------------------------------------------------
/src/components/pages/demo-react-table/style.scss:
--------------------------------------------------------------------------------
1 | @import './../../../styles/variables.scss';
2 |
3 | .ReactTable {
4 | background-color: rgb(245, 245, 245);
5 | padding: 25px 5px;
6 |
7 | .react-table {
8 | font-size: $font-size-small;
9 |
10 | .tb-header {
11 | font-weight: 900;
12 | }
13 |
14 | .tb-cell {
15 | &.tb-buttons {
16 | width: 100%;
17 | height: 16px;
18 | font-size: 16px;
19 | span.tb-button {
20 | }
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/pages/demo-reactstrap/DemoReactstrap.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Collapse, Button, CardBody, Card } from 'reactstrap';
3 |
4 | export default class DemoReactstrap extends Component {
5 | constructor(props) {
6 | super(props);
7 |
8 | document.title = 'Demo Reactstrap';
9 |
10 | this.toggle = this.toggle.bind(this);
11 | this.state = { collapse: false };
12 | }
13 |
14 | toggle() {
15 | this.setState({ collapse: !this.state.collapse });
16 | }
17 |
18 | render() {
19 | return (
20 |
21 |
Toggle collapse image
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/components/pages/demo-redux/DemoRedux.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'react-redux';
3 | import ItemTable from './ItemTable';
4 | import FormAddItem from './FormAddItem';
5 |
6 | export default class DemoRedux extends Component {
7 | constructor(props) {
8 | super(props);
9 |
10 | document.title = 'Demo Redux';
11 | }
12 |
13 | render() {
14 | return (
15 |
16 |
17 |
18 |
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/pages/demo-redux/FormAddItem.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { connect } from 'react-redux';
4 | import * as Actions from './../../../actions';
5 | import { Col, Button, Form, FormGroup, Label, Input } from 'reactstrap';
6 |
7 | const propTypes = {
8 | addItem: PropTypes.func.isRequired
9 | };
10 |
11 | class FormAddItem extends Component {
12 | constructor(props) {
13 | super(props);
14 |
15 | this.item = {
16 | name: null, leave: null, price: null
17 | };
18 |
19 | this.onClickAddItem = this.onClickAddItem.bind(this);
20 | }
21 |
22 | onClickAddItem() {
23 | // create new item, not pass one object is this.item (as redux)
24 | const newItem = { ...this.item };
25 | this.props.addItem(newItem);
26 | }
27 |
28 | render() {
29 | return (
30 |
31 |
32 |
33 | Name
34 |
35 | { this.item.name = e.target.value; }}
41 | />
42 |
43 |
44 |
45 |
46 |
47 |
48 | Leave
49 |
50 | { this.item.leave = e.target.value; }}
56 | />
57 |
58 |
59 |
60 |
61 |
62 |
63 | Price
64 |
65 | { this.item.price = e.target.value; }}
71 | />
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | Add
80 |
81 |
82 |
83 |
84 | );
85 | }
86 | }
87 |
88 | FormAddItem.propTypes = propTypes;
89 |
90 | const mapStateToProps = state => ({});
91 |
92 | const mapDispatchToProps = dispatch => ({
93 | addItem: (item) => {
94 | dispatch(Actions.addItem(item));
95 | }
96 | });
97 |
98 | export default connect(mapStateToProps, mapDispatchToProps)(FormAddItem);
99 |
--------------------------------------------------------------------------------
/src/components/pages/demo-redux/ItemTable.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { connect } from 'react-redux';
4 | import { Table } from 'reactstrap';
5 | import * as Actions from './../../../actions';
6 | import { FormattedDate } from 'react-intl';
7 |
8 | const propTypes = {
9 | removeItem: PropTypes.func.isRequired,
10 | moveItem: PropTypes.func.isRequired,
11 | items: PropTypes.array
12 | };
13 |
14 | const defaultProps = {
15 | items: []
16 | };
17 |
18 | class ItemTable extends Component {
19 | constructor(props) {
20 | super(props);
21 |
22 | document.title = 'Demo Redux';
23 |
24 | this.handleRemoveItem = this.handleRemoveItem.bind(this);
25 | this.handleMoveUpItem = this.handleMoveUpItem.bind(this);
26 | this.handleMoveDownItem = this.handleMoveDownItem.bind(this);
27 | }
28 |
29 | handleRemoveItem(id) {
30 | this.props.removeItem(id);
31 | }
32 |
33 | handleMoveUpItem(id) {
34 | this.props.moveItem(id, true);
35 | }
36 |
37 | handleMoveDownItem(id) {
38 | this.props.moveItem(id, false);
39 | }
40 |
41 | render() {
42 |
43 | const styleBtnFA = {
44 | cursor: 'pointer'
45 | };
46 |
47 | return (
48 |
49 |
50 |
51 |
52 | #
53 | ID
54 | Name
55 | Date
56 | Leave
57 | Price
58 | Action
59 |
60 |
61 |
62 | {this.props.items.map((o, i) =>
63 | (
64 |
65 | {i}
66 | {o.id}
67 | {o.name}
68 |
69 |
75 |
76 | {o.leave}
77 | {o.price}
78 |
79 |
80 | this.handleMoveUpItem(o.id)}
83 | onKeyDown={() => { }} role="button" tabIndex={0}
84 | style={styleBtnFA}
85 | />
86 |
87 |
88 |
89 | this.handleMoveDownItem(o.id)}
92 | onKeyDown={() => { }} role="button" tabIndex={0}
93 | style={styleBtnFA}
94 | />
95 |
96 |
97 |
98 | this.handleRemoveItem(o.id)}
101 | onKeyDown={this.onKey} role="button" tabIndex={0}
102 | style={styleBtnFA}
103 | />
104 |
105 |
106 | ))}
107 |
108 |
109 |
110 | );
111 | }
112 |
113 | }
114 |
115 | ItemTable.propTypes = propTypes;
116 | ItemTable.defaultProps = defaultProps;
117 |
118 | const mapStateToProps = state => ({
119 | items: state.Items
120 | });
121 |
122 | const mapDispatchToProps = dispatch => ({
123 | removeItem: (id) => {
124 | dispatch(Actions.removeItem(id));
125 | },
126 | moveItem: (id, isUp) => {
127 | dispatch(Actions.moveItem(id, isUp));
128 | }
129 | });
130 |
131 | export default connect(mapStateToProps, mapDispatchToProps)(ItemTable);
132 |
--------------------------------------------------------------------------------
/src/components/pages/lifecycle-component.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export default class LifeCycleComponent extends Component {
5 |
6 | constructor(props) {
7 | super(props);
8 |
9 | document.title = 'Life Cycle Component';
10 |
11 | console.log('contructor');
12 | }
13 |
14 | componentWillMount() {
15 | console.log('componentWillMount');
16 | }
17 |
18 | componentDidMount() {
19 | console.log('componentDidMount');
20 | }
21 |
22 | componentWillReceiveProps() {
23 | console.log('componentWillReceiveProps');
24 | }
25 |
26 | shouldComponentUpdate() {
27 | console.log('shouldComponentUpdate');
28 | }
29 |
30 | componentWillUpdate() {
31 | console.log('componentWillUpdate');
32 | }
33 |
34 | componentDidUpdate() {
35 | console.log('componentDidUpdate');
36 | }
37 |
38 | componentWillUnmount() {
39 | console.log('componentWillUnmount');
40 | }
41 |
42 | render() {
43 | return (
44 |
45 |
46 | This is demo Life Cycle of React Component
47 |
48 |
49 |
View Console from Browser to view life cycle component
50 |
51 | );
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/environments/env.development.js:
--------------------------------------------------------------------------------
1 | export default {
2 | baseUrl: 'http://localhost:4200'
3 | };
4 |
--------------------------------------------------------------------------------
/src/environments/env.production.js:
--------------------------------------------------------------------------------
1 | export default {
2 | baseUrl: ''
3 | };
4 |
--------------------------------------------------------------------------------
/src/environments/index.js:
--------------------------------------------------------------------------------
1 | import envDev from './env.development';
2 | import envProd from './env.production';
3 |
4 | let Env;
5 |
6 | if (process.env.REACT_APP_ENV == 'development') {
7 | Env = envDev;
8 | } else if (process.env.REACT_APP_ENV == 'production') {
9 | Env = envProd;
10 | }
11 |
12 | export default Env;
13 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import { createStore, applyMiddleware } from 'redux';
5 | import thunk from 'redux-thunk';
6 | import { IntlProvider } from 'react-intl';
7 |
8 | // Libs
9 | import './lib';
10 |
11 | // Styles
12 | import './styles/index.css';
13 |
14 | // Components
15 | import App from './components/layout/App';
16 | import registerServiceWorker from './registerServiceWorker';
17 |
18 | // Config redux
19 | import allReducers from './reducers';
20 |
21 | const store = createStore(allReducers, applyMiddleware(thunk));
22 |
23 | ReactDOM.render(
24 |
25 |
26 |
27 |
28 |
29 | ,
30 |
31 | document.getElementById('root')
32 | );
33 |
34 | registerServiceWorker();
35 |
--------------------------------------------------------------------------------
/src/lib/animate.css.js:
--------------------------------------------------------------------------------
1 | import 'animate.css';
2 |
--------------------------------------------------------------------------------
/src/lib/bootstrap.js:
--------------------------------------------------------------------------------
1 | import 'bootstrap/dist/css/bootstrap.min.css';
2 | import 'bootstrap/dist/js/bootstrap.bundle.min.js';
3 |
--------------------------------------------------------------------------------
/src/lib/font-awesome.js:
--------------------------------------------------------------------------------
1 | import 'font-awesome/css/font-awesome.min.css';
2 |
--------------------------------------------------------------------------------
/src/lib/index.js:
--------------------------------------------------------------------------------
1 | import './jquery';
2 | import './bootstrap';
3 | import './font-awesome';
4 | import './animate.css';
5 |
--------------------------------------------------------------------------------
/src/lib/jquery.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 |
3 | // config jquery variables for other lib use jQuery (such as bootstrap)
4 | window.$ = $;
5 | window.jQuery = $;
6 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 |
3 | import Items from './items';
4 | import Users from './users';
5 | import Todos from './todos';
6 |
7 | const reducers = combineReducers({
8 | Items,
9 | Users,
10 | Todos
11 | });
12 |
13 | export default reducers;
14 |
--------------------------------------------------------------------------------
/src/reducers/items.js:
--------------------------------------------------------------------------------
1 | import actionTypes from '../actions/action-types';
2 |
3 | const initialState = [];
4 |
5 | function toHex(input) {
6 | var hash = '',
7 | alphabet = '0123456789abcdef',
8 | alphabetLength = alphabet.length;
9 |
10 | do {
11 | hash = alphabet[input % alphabetLength] + hash;
12 | input = parseInt(input / alphabetLength, 10);
13 | } while (input);
14 |
15 | return hash;
16 | }
17 |
18 | let currentID = 0;
19 |
20 | function nextID() {
21 | return toHex((++currentID) * 199999999).toUpperCase();
22 | }
23 |
24 | for (let i = 0; i < 10; i++) initialState.push({
25 | id: nextID(),
26 | name: `Item ${i}`,
27 | leave: i * 20,
28 | price: i * 8521 + (20 - i) * 1958,
29 | date: new Date(2018, i % 12, i * 197 % 28 + 1)
30 | });
31 |
32 | const reducer = (state = initialState, action) => {
33 |
34 | switch (action.type) {
35 |
36 | case actionTypes.ADD_ITEM:
37 | const { item } = action;
38 | item.id = nextID();
39 | item.date = new Date();
40 | console.log(item);
41 | return [...state, item];
42 |
43 | case actionTypes.REMOVE_ITEM:
44 | return state.filter((o, i) => o.id !== action.id);
45 |
46 | case actionTypes.EDIT_ITEM:
47 | return state.map((item, idx) => {
48 | if (item.id !== action.id) return item;
49 | return { ...item, ...action.newItem };
50 | });
51 |
52 | case actionTypes.MOVE_ITEM:
53 | const { id, isUp } = action;
54 | const srcItem = state.filter(o => o.id == id)[0];
55 | let idx = state.indexOf(srcItem);
56 | if (isUp) {
57 | if (idx == 0) return state;
58 | const tarItem = state[--idx];
59 | return [
60 | ...state.slice(0, idx),
61 | { ...srcItem },
62 | { ...tarItem },
63 | ...state.slice(idx + 2)
64 | ];
65 | } else {
66 | if (idx == state.length - 1) return state;
67 | const tarItem = state[idx + 1];
68 | return [
69 | ...state.slice(0, idx),
70 | { ...tarItem },
71 | { ...srcItem },
72 | ...state.slice(idx + 2)
73 | ];
74 | }
75 |
76 | default:
77 | return state;
78 | }
79 | };
80 |
81 | export default reducer;
82 |
--------------------------------------------------------------------------------
/src/reducers/todos.js:
--------------------------------------------------------------------------------
1 | import actionTypes from '../actions/action-types';
2 | import uniqid from 'uniqid';
3 |
4 | const baseActions = [
5 | 'Find out', 'Learn', 'Practice', 'Review', 'Build prject', 'Guide', 'Present'
6 | ];
7 | const baseObjects = [
8 | 'React', 'React Native', 'AngularJS', 'Angular 2', 'Angular 4', 'Angular 5', 'VueJS', 'EmberJS',
9 | 'SQL', 'MySql', 'Postgres SQL', 'SQL Server', 'MSSQL', 'Oracle SQL', 'MongoDB',
10 | 'NodeJS', 'PHP', 'Java', 'C++', 'Python', 'Go', 'Ruby', 'Objective-C', 'Android', 'iOS',
11 | 'C#', 'ASP.net'
12 | ];
13 |
14 | const todoList = [];
15 |
16 | for (let i = 0; i < baseActions.length; i++)
17 | for (let j = 0; j < baseObjects.length; j++) {
18 | const num = i * baseActions.length + j;
19 | const action = baseActions[i];
20 | const object = baseObjects[j];
21 | const yyyy = 2015 + j % 4,
22 | mm = num % 12,
23 | dd = num * 1999999 % 29;
24 | const duration = i * 5 + (baseActions.length - i) * 3;
25 | const dateStart = new Date(yyyy, mm, dd);
26 | const dateEnd = new Date(dateStart.getTime() + duration * 86400000);
27 | const process = (num * 199997 + Math.round(Math.random() * 1999997)) % 101;
28 | todoList.push({
29 | id: uniqid.time().toUpperCase(),
30 | content: `${action} ${object}`,
31 | duration,
32 | dateStart,
33 | dateEnd,
34 | process
35 | });
36 | }
37 |
38 | const initialState = todoList;
39 |
40 | const reducer = (state = initialState, action) => {
41 | switch (action.type) {
42 | case actionTypes.ADD_TODO:
43 | return [...state, action.newTodo];
44 |
45 | case actionTypes.REMOVE_TODO:
46 | return state.filter(o => o.id !== action.id);
47 |
48 | case actionTypes.DONE_TODO:
49 | return state.map((o) => {
50 | if (o.id != action.id) return o;
51 | return { ...o, done: action.isDone };
52 | });
53 |
54 | case actionTypes.MODIFY_TODO:
55 | console.log(action);
56 | return state.map((o) => {
57 | if (o.id != action.id) return o;
58 | return { ...o, ...action.newTodo };
59 | });
60 |
61 | default:
62 | return state;
63 | }
64 | };
65 |
66 | export default reducer;
67 |
--------------------------------------------------------------------------------
/src/reducers/users.js:
--------------------------------------------------------------------------------
1 | import actionTypes from '../actions/action-types';
2 |
3 | const userList = [];
4 | for (let i = 0; i < 100; i++) {
5 | userList.push({
6 | id: i,
7 | name: `User ${i}`,
8 | email: `user-${i}@gmail.com`,
9 | salary: i * 975 + (100 - i) * 285,
10 | address: `Street ${100 - i}`
11 | });
12 | }
13 |
14 | const initialState = userList;
15 |
16 | const reducer = (state = initialState, action) => {
17 | switch (action.type) {
18 | case actionTypes.REMOVE_USER:
19 | return state.filter(o => o.id != action.id);
20 | default:
21 | return state;
22 | }
23 | };
24 |
25 | export default reducer;
26 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(window.location.hostname === 'localhost' ||
12 | // [::1] is the IPv6 localhost address.
13 | window.location.hostname === '[::1]' ||
14 | // 127.0.0.1/8 is considered localhost for IPv4.
15 | window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));
16 |
17 | export default function register() {
18 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
19 | // The URL constructor is available in all browsers that support SW.
20 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
21 | if (publicUrl.origin !== window.location.origin) {
22 | // Our service worker won't work if PUBLIC_URL is on a different origin
23 | // from what our page is served on. This might happen if a CDN is used to
24 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
25 | return;
26 | }
27 |
28 | window.addEventListener('load', () => {
29 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
30 |
31 | if (isLocalhost) {
32 | // This is running on localhost. Lets check if a service worker still exists or not.
33 | checkValidServiceWorker(swUrl);
34 |
35 | // Add some additional logging to localhost, pointing developers to the
36 | // service worker/PWA documentation.
37 | navigator.serviceWorker.ready.then(() => {
38 | console.log('This web app is being served cache-first by a service ' +
39 | 'worker. To learn more, visit https://goo.gl/SC7cgQ');
40 | });
41 | } else {
42 | // Is not local host. Just register service worker
43 | registerValidSW(swUrl);
44 | }
45 | });
46 | }
47 | }
48 |
49 | function registerValidSW(swUrl) {
50 | navigator.serviceWorker
51 | .register(swUrl)
52 | .then((registration) => {
53 | registration.onupdatefound = () => {
54 | const installingWorker = registration.installing;
55 | installingWorker.onstatechange = () => {
56 | if (installingWorker.state === 'installed') {
57 | if (navigator.serviceWorker.controller) {
58 | // At this point, the old content will have been purged and
59 | // the fresh content will have been added to the cache.
60 | // It's the perfect time to display a "New content is
61 | // available; please refresh." message in your web app.
62 | console.log('New content is available; please refresh.');
63 | } else {
64 | // At this point, everything has been precached.
65 | // It's the perfect time to display a
66 | // "Content is cached for offline use." message.
67 | console.log('Content is cached for offline use.');
68 | }
69 | }
70 | };
71 | };
72 | })
73 | .catch((error) => {
74 | console.error('Error during service worker registration:', error);
75 | });
76 | }
77 |
78 | function checkValidServiceWorker(swUrl) {
79 | // Check if the service worker can be found. If it can't reload the page.
80 | fetch(swUrl)
81 | .then((response) => {
82 | // Ensure service worker exists, and that we really are getting a JS file.
83 | if (
84 | response.status === 404 ||
85 | response.headers.get('content-type').indexOf('javascript') === -1
86 | ) {
87 | // No service worker found. Probably a different app. Reload the page.
88 | navigator.serviceWorker.ready.then((registration) => {
89 | registration.unregister().then(() => {
90 | window.location.reload();
91 | });
92 | });
93 | } else {
94 | // Service worker found. Proceed as normal.
95 | registerValidSW(swUrl);
96 | }
97 | })
98 | .catch(() => {
99 | console.log('No internet connection found. App is running in offline mode.');
100 | });
101 | }
102 |
103 | export function unregister() {
104 | if ('serviceWorker' in navigator) {
105 | navigator.serviceWorker.ready.then((registration) => {
106 | registration.unregister();
107 | });
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/services/auth-service.js:
--------------------------------------------------------------------------------
1 | import Env from './../environments';
2 |
3 | export class AuthService {
4 |
5 | static baseUrl() { return Env.baseUrl; }
6 | static parseUrl(url) { return AuthService.baseUrl() + url; }
7 |
8 | }
9 |
10 | export default AuthService;
11 |
--------------------------------------------------------------------------------
/src/services/db-service.js:
--------------------------------------------------------------------------------
1 | import Env from './../environments';
2 |
3 | export default class DbService {
4 |
5 | static baseUrl() { return Env.baseUrl; }
6 | static parseUrl(url) { return DbService.baseUrl() + url; }
7 |
8 | static getItems() {
9 | const url = DbService.parseUrl('/api/items');
10 | console.log(url);
11 | return fetch(url).then(res => res.json());
12 | }
13 |
14 | static addItem(item) {
15 | const url = DbService.parseUrl('/api/items');
16 | return fetch(url, {
17 | method: 'POST',
18 | headers: {
19 | 'Accept': 'application/json',
20 | 'Content-Type': 'application/json'
21 | },
22 | body: JSON.stringify(item)
23 | }).then(res => res.json());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/services/util-service.js:
--------------------------------------------------------------------------------
1 | export default class UtilService {
2 | // stuff something here, e.g.
3 | }
4 |
--------------------------------------------------------------------------------
/src/styles/_animate.scss:
--------------------------------------------------------------------------------
1 | /* custom lib animate.css */
2 |
3 | /*
4 | from 0.1s to 3s with step 0.1s
5 | generated classes:
6 | .animated.duration-100
7 | .animated.duration-200
8 | ...
9 | .animated.duration-1100
10 | .animated.duration-1200
11 | ...
12 | .animated.duration-3000
13 | */
14 |
15 | @for $i from 1 through 30 {
16 |
17 | $suffix: $i * 100;
18 |
19 | $time: $i / 10;
20 |
21 | .animated.duration-#{$suffix} {
22 | animation-duration: #{$time}s;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/styles/_classes.scss:
--------------------------------------------------------------------------------
1 | /**
2 | |--------------------------------------------------
3 | | You can add or/and custom your global classes here
4 | |--------------------------------------------------
5 | */
6 |
7 | .fontRoboto {
8 | font-family: $font-family-Roboto;
9 | }
10 |
11 | .fontOpenSans {
12 | font-family: $font-family-Open-Sans;
13 | }
14 |
15 | .fontNunito {
16 | font-family: $font-family-Nunito;
17 | }
18 |
19 | .fontExtraSmall {
20 | font-size: $font-size-extra-small;
21 | }
22 |
23 | .fontSmall {
24 | font-size: $font-size-small;
25 | }
26 |
27 | .fontNormal {
28 | font-size: $font-size-normal;
29 | }
30 |
31 | .fontMedium {
32 | font-size: $font-size-medium;
33 | }
34 |
35 | .fontLarge {
36 | font-size: $font-size-large;
37 | }
38 |
39 | .fontExtraLarge {
40 | font-size: $font-size-extra-large;
41 | }
42 |
43 | .cursorPointer {
44 | cursor: pointer;
45 | }
46 |
47 | .cursorNotAllowed {
48 | cursor: not-allowed
49 | }
50 |
51 | .cursorCrosshair {
52 | cursor: crosshair;
53 | }
54 |
--------------------------------------------------------------------------------
/src/styles/_mixins.scss:
--------------------------------------------------------------------------------
1 | /**
2 | |--------------------------------------------------
3 | | You can add or/and custom your mixins here
4 | |--------------------------------------------------
5 | */
6 |
7 | @mixin arrow-up($size, $color) {
8 | width: 0;
9 | height: 0;
10 | border-left: $size solid transparent;
11 | border-right: $size solid transparent;
12 |
13 | border-bottom: $size solid $color;
14 | }
15 |
16 | @mixin arrow-down($size, $color) {
17 | width: 0;
18 | height: 0;
19 | border-left: $size solid transparent;
20 | border-right: $size solid transparent;
21 |
22 | border-top: $size solid $color;
23 | }
24 |
25 | @mixin arrow-left($size, $color) {
26 | width: 0;
27 | height: 0;
28 | border-top: $size solid transparent;
29 | border-bottom: $size solid transparent;
30 |
31 | border-right: $size solid $color;
32 | }
33 |
34 | @mixin arrow-right($size, $color) {
35 | width: 0;
36 | height: 0;
37 | border-top: $size solid transparent;
38 | border-bottom: $size solid transparent;
39 |
40 | border-left: $size solid $color;
41 | }
42 |
--------------------------------------------------------------------------------
/src/styles/_variables.scss:
--------------------------------------------------------------------------------
1 | /**
2 | |--------------------------------------------------
3 | | You can add and/or custom your global variable here
4 | |--------------------------------------------------
5 | */
6 |
7 | // FONT SIZE GLOBAL
8 | $font-size: 16px;
9 | $font-size-extra-small: 0.7rem;
10 | $font-size-small: 0.8rem;
11 | $font-size-normal: 1rem;
12 | $font-size-medium: 1.2rem;
13 | $font-size-large: 1.5rem;
14 | $font-size-extra-large: 2rem;
15 |
16 | // FONT FAMILY GLOBAL
17 | $font-family-Roboto: 'Roboto', sans-serif;
18 | $font-family-Nunito: 'Nunito', sans-serif;
19 | $font-family-Open-Sans: 'Open Sans', sans-serif;
20 |
21 | // COLOR GLOBAL
22 | $red: #dd4b39;
23 | $orange: #FF851B;
24 | $purple: #605ca8;
25 | $blue: #0073b7;
26 | $green: #00a65a;
27 | $navy: #001F3F;
28 |
29 | $color-primary: $purple;
30 | $color-success: $green;
31 | $color-info: $blue;
32 | $color-warning: $orange;
33 | $color-dander: $red;
34 |
35 | // Z INDEX
36 | $z-index-base: 500;
37 | $z-index-min: $z-index-base - 500;
38 | $z-index-max: $z-index-base + 500;
39 |
--------------------------------------------------------------------------------
/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @import './variables.scss';
2 | @import './mixins.scss';
3 | @import './classes.scss';
4 | @import './animate.scss';
5 |
6 | /**
7 | |--------------------------------------------------
8 | | You can style your app here
9 | |--------------------------------------------------
10 | */
11 |
12 | html,
13 | body {
14 | width: 100% !important;
15 | height: 100% !important;
16 | font-size: $font-size;
17 | line-height: initial;
18 | }
19 |
20 | body {
21 | margin: 0px;
22 | padding: 0px;
23 | font-family: $font-family-Nunito;
24 | background-color: #e9e9e9;
25 | }
26 |
27 | h1, h2, h3, h4, h5, h6 {
28 | font-weight: 900;
29 | font-family: $font-family-Roboto;
30 | }
31 |
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | const a = 5;
2 | const b = 9;
3 |
4 | const c = () => {
5 |
6 |
7 | console.log('object');
8 |
9 |
10 | };
11 |
--------------------------------------------------------------------------------