├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── public
├── favicon.ico
├── index.html
└── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── ColumnList.css
├── ColumnList.js
├── ConfirmDialog.js
├── If.js
├── MobileTearSheet.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | yarn.lock
3 | .DS_Store
4 | .idea/
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Vin Busquet
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React To-Do List
2 |
3 | This is a simple To-Do list app done with React. All tasks are saved into browser's local storage only. The app development
4 | was inspired by the first brazilian live coding of the [React Nanodegree Program](https://udacity.com/course/react-nanodegree--nd019).
5 |
6 |
7 |
8 | ## Demo
9 |
10 | [computationalcore.github.io/react-to-do-list](https://computationalcore.github.io/react-to-do-list)
11 |
12 | ## Getting Started
13 |
14 | These instructions will get you a copy of the project up and running on your local machine for development and testing
15 | purposes.
16 |
17 | ### Prerequisites
18 |
19 | The project can be built with npm or yarn, so choose one of the approach bellow in case you don't
20 | have any installed on your system.
21 |
22 | * npm is distributed with Node.js which means that when you download Node.js,
23 | you automatically get npm installed on your computer. [Download Node.js](https://nodejs.org/en/download/)
24 |
25 | or
26 |
27 | * Yarn is a package manager built by Facebook Team and seems to be faster than npm in general. [Download Yarn](https://yarnpkg.com/en/docs/install)
28 |
29 | ### Installing
30 |
31 | To download the project follow the instructions bellow
32 |
33 | ```
34 | git clone https://github.com/computationalcore/react-to-do-list
35 | cd myreads
36 | ```
37 |
38 | Install dependencies and run with:
39 |
40 | npm
41 | ```
42 | npm install
43 | npm start
44 | ```
45 | or
46 |
47 | yarn
48 | ```
49 | yarn install
50 | yarn start
51 | ```
52 |
53 | ## Versions
54 |
55 | v1.0
56 | * Default project implementation
57 |
58 | v1.1
59 | * Change to material UI based interface
60 | * Task transitions animations
61 | * Remove tasks capabilities
62 |
63 | ## Authors
64 | Vin Busquet
65 | * [https://github.com/computationalcore](https://github.com/computationalcore)
66 |
67 | ## License
68 |
69 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
70 |
71 |
72 | ## Acknowledgments
73 | * [Udacity](https://www.udacity.com/)
74 | * [Matheus Marsiglio](https://github.com/mtmr0x)
75 | * [Thales Moreira Carvalho](https://github.com/thalescomp)
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "to-do-list",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "material-ui": "^0.19.4",
7 | "prop-types": "^15.5.8",
8 | "react": "^15.6.1",
9 | "react-dom": "^15.6.1",
10 | "react-scripts": "1.0.14",
11 | "react-swipeable-views": "^0.12.10",
12 | "react-transition-group": "^1.2.1",
13 | "sort-by": "^1.2.0"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "build": "react-scripts build",
18 | "test": "react-scripts test --env=jsdom",
19 | "eject": "react-scripts eject"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalcore/react-to-do-list/9c19e5954b82d1420bc75f4300f650a6269b1142/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
83 | )
84 | };
85 |
86 | // Type checking the props of the component
87 | ColumnList.propTypes = propTypes;
88 |
89 | // Assign default values to the optional props
90 | ColumnList.defaultProps = defaultProps;
91 |
92 | export default ColumnList;
93 |
--------------------------------------------------------------------------------
/src/ConfirmDialog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import Dialog from 'material-ui/Dialog';
4 | import FlatButton from 'material-ui/FlatButton';
5 | import './App.css';
6 |
7 | /**
8 | * This object is used for type checking the props of the component.
9 | */
10 | const propTypes = {
11 | title: PropTypes.string.isRequired,
12 | message: PropTypes.string.isRequired,
13 | open: PropTypes.bool.isRequired,
14 | onCancel: PropTypes.func.isRequired,
15 | onConfirm: PropTypes.func.isRequired,
16 | };
17 |
18 | /**
19 | * This callback type is called `cancelCallback` and is displayed as a global symbol.
20 | *
21 | * @callback cancelCallback
22 | */
23 |
24 | /**
25 | * This callback type is called `confirmCallback` and is displayed as a global symbol.
26 | *
27 | * @callback confirmCallback
28 | */
29 |
30 | /**
31 | * @description Represents a material UI based Confirm Dialog.
32 | * @constructor
33 | * @param {Object} props - The props that were defined by the caller of this component.
34 | * @param {string} props.title - The message to be displayed by the dialog.
35 | * @param {boolean} props.open - The visibility of the dialog.
36 | * @param {cancelCallback} props.onCancel - The callback to execute when the user hits the cancel button.
37 | * @param {confirmCallback} props.onConfirm - The callback to execute when the user hits the confirm button.
38 | */
39 | function ConfirmDialog(props) {
40 |
41 | // Confirm Dialog buttons
42 | const dialogActions = [
43 | ,
48 | ,
55 | ];
56 |
57 | return (
58 |
59 |
67 |
68 | );
69 | }
70 |
71 | // Type checking the props of the component
72 | ConfirmDialog.propTypes = propTypes;
73 |
74 | export default ConfirmDialog;
--------------------------------------------------------------------------------
/src/If.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Evaluate expression and return object or false.
3 | * It is used to replace ternary operations to make the JSX more readable and debuggable.
4 | * @param {boolean} test
5 | * @param {Object|boolean} children
6 | * @constructor
7 | */
8 | const If = ({ test, children}) => test ? children: false;
9 |
10 | export default If;
11 |
--------------------------------------------------------------------------------
/src/MobileTearSheet.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | /**
5 | * This object is used for type checking the props of the component.
6 | */
7 | const propTypes = {
8 | children: PropTypes.object.isRequired,
9 | };
10 |
11 | /**
12 | * Represents a component that adds a zigzag-bottomed outline to a material-ui list component.
13 | * @param {Object} props - The props that were defined by the caller of this component.
14 | * @param {Object} props.children - Children component.
15 | * @returns {XML}
16 | * @constructor
17 | */
18 | const MobileTearSheet = (props) => {
19 |
20 | const height = "100%";
21 | const styles = {
22 | root: {
23 | margin: '0 auto',
24 | maxWidth: 500,
25 | width: '100%',
26 | },
27 | container: {
28 | border: 'solid 1px #d9d9d9',
29 | borderBottom: 'none',
30 | height: height,
31 | overflow: 'hidden',
32 | },
33 | bottomTear: {
34 | display: 'block',
35 | position: 'relative',
36 | marginTop: -10,
37 | maxWidth: 500,
38 | },
39 | };
40 |
41 | return (
42 |
43 |
44 | {props.children}
45 |
46 |
47 |
62 |
63 |
64 | );
65 | };
66 |
67 | // Type checking the props of the component
68 | MobileTearSheet.propTypes = propTypes;
69 |
70 | export default MobileTearSheet;
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/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(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Lets check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl);
38 | } else {
39 | // Is not local host. Just register service worker
40 | registerValidSW(swUrl);
41 | }
42 | });
43 | }
44 | }
45 |
46 | function registerValidSW(swUrl) {
47 | navigator.serviceWorker
48 | .register(swUrl)
49 | .then(registration => {
50 | registration.onupdatefound = () => {
51 | const installingWorker = registration.installing;
52 | installingWorker.onstatechange = () => {
53 | if (installingWorker.state === 'installed') {
54 | if (navigator.serviceWorker.controller) {
55 | // At this point, the old content will have been purged and
56 | // the fresh content will have been added to the cache.
57 | // It's the perfect time to display a "New content is
58 | // available; please refresh." message in your web app.
59 | console.log('New content is available; please refresh.');
60 | } else {
61 | // At this point, everything has been precached.
62 | // It's the perfect time to display a
63 | // "Content is cached for offline use." message.
64 | console.log('Content is cached for offline use.');
65 | }
66 | }
67 | };
68 | };
69 | })
70 | .catch(error => {
71 | console.error('Error during service worker registration:', error);
72 | });
73 | }
74 |
75 | function checkValidServiceWorker(swUrl) {
76 | // Check if the service worker can be found. If it can't reload the page.
77 | fetch(swUrl)
78 | .then(response => {
79 | // Ensure service worker exists, and that we really are getting a JS file.
80 | if (
81 | response.status === 404 ||
82 | response.headers.get('content-type').indexOf('javascript') === -1
83 | ) {
84 | // No service worker found. Probably a different app. Reload the page.
85 | navigator.serviceWorker.ready.then(registration => {
86 | registration.unregister().then(() => {
87 | window.location.reload();
88 | });
89 | });
90 | } else {
91 | // Service worker found. Proceed as normal.
92 | registerValidSW(swUrl);
93 | }
94 | })
95 | .catch(() => {
96 | console.log(
97 | 'No internet connection found. App is running in offline mode.'
98 | );
99 | });
100 | }
101 |
102 | export function unregister() {
103 | if ('serviceWorker' in navigator) {
104 | navigator.serviceWorker.ready.then(registration => {
105 | registration.unregister();
106 | });
107 | }
108 | }
109 |
--------------------------------------------------------------------------------