mirror of
https://github.com/usatiuk/ustk-todolist.git
synced 2025-10-28 15:47:48 +01:00
animate add todo/filter selector
This commit is contained in:
40
app.js
40
app.js
@@ -3,12 +3,12 @@ const express = require('express');
|
|||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const morgan = require('morgan');
|
const morgan = require('morgan');
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
const config = require('./config');
|
|
||||||
const db = require('./config/db');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const hsts = require('hsts');
|
const hsts = require('hsts');
|
||||||
const compression = require('compression');
|
const compression = require('compression');
|
||||||
const { redirectToHTTPS } = require('express-http-to-https');
|
const { redirectToHTTPS } = require('express-http-to-https');
|
||||||
|
const db = require('./config/db');
|
||||||
|
const config = require('./config');
|
||||||
|
|
||||||
require('./models/TodoList');
|
require('./models/TodoList');
|
||||||
require('./models/User');
|
require('./models/User');
|
||||||
@@ -74,22 +74,26 @@ app.use((req, res) => {
|
|||||||
|
|
||||||
// handle errors
|
// handle errors
|
||||||
app.use((error, req, res, next) => {
|
app.use((error, req, res, next) => {
|
||||||
switch (error.name) {
|
if (error.code) {
|
||||||
case 'ValidationError':
|
res.status(error.code);
|
||||||
case 'MissingPasswordError':
|
} else {
|
||||||
case 'BadRequest':
|
switch (error.name) {
|
||||||
case 'BadRequestError':
|
case 'ValidationError':
|
||||||
res.status(400);
|
case 'MissingPasswordError':
|
||||||
break;
|
case 'BadRequest':
|
||||||
case 'AuthenticationError':
|
case 'BadRequestError':
|
||||||
case 'UnauthorizedError':
|
res.status(400);
|
||||||
res.status(401);
|
break;
|
||||||
break;
|
case 'AuthenticationError':
|
||||||
case 'NotFound':
|
case 'UnauthorizedError':
|
||||||
res.status(404);
|
res.status(401);
|
||||||
break;
|
break;
|
||||||
default:
|
case 'NotFound':
|
||||||
res.status(500);
|
res.status(404);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res.status(500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res.json({ success: false, error });
|
res.json({ success: false, error });
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ class NotFoundError extends Error {
|
|||||||
Error.captureStackTrace(this, NotFoundError);
|
Error.captureStackTrace(this, NotFoundError);
|
||||||
this.name = 'NotFound';
|
this.name = 'NotFound';
|
||||||
this.text = text;
|
this.text = text;
|
||||||
|
this.code = 404;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ class BadRequestError extends Error {
|
|||||||
Error.captureStackTrace(this, NotFoundError);
|
Error.captureStackTrace(this, NotFoundError);
|
||||||
this.name = 'BadRequest';
|
this.name = 'BadRequest';
|
||||||
this.text = text;
|
this.text = text;
|
||||||
|
this.code = 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
146
package-lock.json
generated
146
package-lock.json
generated
@@ -1688,6 +1688,94 @@
|
|||||||
"typedarray": "^0.0.6"
|
"typedarray": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"concurrently": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-6XiIYtYzmGEccNZFkih5JOH92jLA4ulZArAYy5j1uDSdrPLB3KzdE8GW7t2fHPcg9ry2+5LP9IEYzXzxw9lFdA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"commander": "2.6.0",
|
||||||
|
"date-fns": "^1.23.0",
|
||||||
|
"lodash": "^4.5.1",
|
||||||
|
"read-pkg": "^3.0.0",
|
||||||
|
"rx": "2.3.24",
|
||||||
|
"spawn-command": "^0.0.2-1",
|
||||||
|
"supports-color": "^3.2.3",
|
||||||
|
"tree-kill": "^1.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"commander": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz",
|
||||||
|
"integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"has-flag": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"load-json-file": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"parse-json": "^4.0.0",
|
||||||
|
"pify": "^3.0.0",
|
||||||
|
"strip-bom": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parse-json": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"error-ex": "^1.3.1",
|
||||||
|
"json-parse-better-errors": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-type": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"pify": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pify": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"read-pkg": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"load-json-file": "^4.0.0",
|
||||||
|
"normalize-package-data": "^2.3.2",
|
||||||
|
"path-type": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "3.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
|
||||||
|
"integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"configstore": {
|
"configstore": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
|
||||||
@@ -1853,6 +1941,12 @@
|
|||||||
"whatwg-url": "^6.4.0"
|
"whatwg-url": "^6.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"date-fns": {
|
||||||
|
"version": "1.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
|
||||||
|
"integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
@@ -3514,14 +3608,12 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -3536,20 +3628,17 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -3666,8 +3755,7 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@@ -3679,7 +3767,6 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -3694,7 +3781,6 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@@ -3702,14 +3788,12 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@@ -3728,7 +3812,6 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@@ -3809,8 +3892,7 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@@ -3822,7 +3904,6 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@@ -3944,7 +4025,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@@ -5482,6 +5562,12 @@
|
|||||||
"integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=",
|
"integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"json-parse-better-errors": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"json-schema": {
|
"json-schema": {
|
||||||
"version": "0.2.3",
|
"version": "0.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||||
@@ -7593,6 +7679,12 @@
|
|||||||
"is-promise": "^2.1.0"
|
"is-promise": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rx": {
|
||||||
|
"version": "2.3.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz",
|
||||||
|
"integrity": "sha1-FPlQpCF9fjXapxu8vljv9o6ksrc=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"rx-lite": {
|
"rx-lite": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
|
||||||
@@ -8001,6 +8093,12 @@
|
|||||||
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
|
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"spawn-command": {
|
||||||
|
"version": "0.0.2-1",
|
||||||
|
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
|
||||||
|
"integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"spdx-correct": {
|
"spdx-correct": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
|
||||||
@@ -8527,6 +8625,12 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tree-kill": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"trim-right": {
|
"trim-right": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
"main": "app.js",
|
"main": "app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./app.js",
|
"start": "node ./app.js",
|
||||||
"debug": "cross-env NODE_ENV=development npx nodemon --inspect ./app.js",
|
"dev": "npx concurrently \"npm run server\" \"npm run client\" ",
|
||||||
"test": "cross-env NODE_ENV=test jest",
|
"client": "cd react && npm start",
|
||||||
|
"server": "npx cross-env NODE_ENV=development npx nodemon --inspect ./app.js",
|
||||||
|
"test": "npx cross-env NODE_ENV=test jest",
|
||||||
"heroku-postbuild": "cd react && npm install && npm run build"
|
"heroku-postbuild": "cd react && npm install && npm run build"
|
||||||
},
|
},
|
||||||
"cacheDirectories": [
|
"cacheDirectories": [
|
||||||
@@ -38,6 +40,7 @@
|
|||||||
"passport-local-mongoose": "^5.0.1"
|
"passport-local-mongoose": "^5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"concurrently": "^3.6.0",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"eslint": "^5.1.0",
|
"eslint": "^5.1.0",
|
||||||
"eslint-config-airbnb-base": "^13.0.0",
|
"eslint-config-airbnb-base": "^13.0.0",
|
||||||
|
|||||||
@@ -53,7 +53,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#inputs {
|
#inputs {
|
||||||
transition: 0.4s ease-in-out;
|
|
||||||
box-shadow: 0 2px 7px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 7px rgba(0, 0, 0, 0.1);
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import CssBaseline from '@material-ui/core/CssBaseline';
|
|||||||
import './Container.css';
|
import './Container.css';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
|
||||||
import TodosContainer from '../containers/TodosContainer';
|
import MainViewContainer from '../containers/MainViewContainer';
|
||||||
import LoginForm from './user/LoginForm';
|
import LoginForm from './user/LoginForm';
|
||||||
import SignupForm from './user/SignupForm';
|
import SignupForm from './user/SignupForm';
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ export default class App extends React.PureComponent {
|
|||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Router>
|
<Router>
|
||||||
<div id="container">
|
<div id="container">
|
||||||
<Route exact path="/" component={TodosContainer} />
|
<Route exact path="/" component={MainViewContainer} />
|
||||||
<Route path="/login" component={LoginForm} />
|
<Route path="/login" component={LoginForm} />
|
||||||
<Route path="/signup" component={SignupForm} />
|
<Route path="/signup" component={SignupForm} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React from 'react';
|
|||||||
import FilterLink from '../containers/FilterLink';
|
import FilterLink from '../containers/FilterLink';
|
||||||
import { VisibilityFilters } from '../actions/defs';
|
import { VisibilityFilters } from '../actions/defs';
|
||||||
|
|
||||||
function Filters() {
|
function Filters(styles) {
|
||||||
return (
|
return (
|
||||||
<div id="filters">
|
<div style={styles} id="filters">
|
||||||
<FilterLink filter={VisibilityFilters.SHOW_ALL}>all</FilterLink>
|
<FilterLink filter={VisibilityFilters.SHOW_ALL}>all</FilterLink>
|
||||||
<FilterLink filter={VisibilityFilters.SHOW_ACTIVE}>active</FilterLink>
|
<FilterLink filter={VisibilityFilters.SHOW_ACTIVE}>active</FilterLink>
|
||||||
<FilterLink filter={VisibilityFilters.SHOW_COMPLETED}>
|
<FilterLink filter={VisibilityFilters.SHOW_COMPLETED}>
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ import PropTypes from 'prop-types';
|
|||||||
import { Button } from '@material-ui/core';
|
import { Button } from '@material-ui/core';
|
||||||
import AddIcon from '@material-ui/icons/Add';
|
import AddIcon from '@material-ui/icons/Add';
|
||||||
|
|
||||||
function Input(props) {
|
function Input({ onClick, styles }) {
|
||||||
let input;
|
let input;
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
if (input.value.trim() !== '') {
|
if (input.value.trim() !== '') {
|
||||||
props.onClick(input.value);
|
onClick(input.value);
|
||||||
}
|
}
|
||||||
input.value = '';
|
input.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="inputs">
|
<div style={styles} id="inputs">
|
||||||
<input
|
<input
|
||||||
ref={node => {
|
ref={node => {
|
||||||
input = node;
|
input = node;
|
||||||
@@ -36,6 +36,7 @@ function Input(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Input.propTypes = {
|
Input.propTypes = {
|
||||||
|
styles: PropTypes.any.isRequired,
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
21
react/src/components/MainView.js
Normal file
21
react/src/components/MainView.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import TodosContainer from '../containers/TodosContainer';
|
||||||
|
|
||||||
|
export default class MainView extends React.PureComponent {
|
||||||
|
componentDidUpdate() {
|
||||||
|
const { user, history } = this.props;
|
||||||
|
if (!user.user && !user.dirty) {
|
||||||
|
history.replace('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <TodosContainer />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainView.propTypes = {
|
||||||
|
user: PropTypes.any.isRequired,
|
||||||
|
history: PropTypes.any.isRequired,
|
||||||
|
};
|
||||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import { Select, MenuItem } from '@material-ui/core';
|
import { Select, MenuItem } from '@material-ui/core';
|
||||||
import AddIcon from '@material-ui/icons/Add';
|
import AddIcon from '@material-ui/icons/Add';
|
||||||
import CheckIcon from '@material-ui/icons/Check';
|
import CheckIcon from '@material-ui/icons/Check';
|
||||||
import { Spring, animated } from 'react-spring';
|
import { Transition, animated } from 'react-spring';
|
||||||
|
|
||||||
import './Selector.css';
|
import './Selector.css';
|
||||||
|
|
||||||
@@ -28,65 +28,83 @@ export default function Selector({
|
|||||||
if (creating) {
|
if (creating) {
|
||||||
let input = null;
|
let input = null;
|
||||||
return (
|
return (
|
||||||
<div id="listselector" className="list--input">
|
<Transition
|
||||||
<input
|
native
|
||||||
ref={node => {
|
from={{ opacity: 0, maxHeight: 0 }}
|
||||||
input = node;
|
enter={{ opacity: 1, maxHeight: 64 }}
|
||||||
}}
|
leave={{ opacity: 0, maxHeight: 0 }}
|
||||||
id="input"
|
>
|
||||||
type="text"
|
{styles => (
|
||||||
onKeyPress={e => {
|
<animated.div
|
||||||
if (e.key === 'Enter') {
|
style={styles}
|
||||||
addList(input.value);
|
id="listselector"
|
||||||
}
|
className="list--input"
|
||||||
}}
|
>
|
||||||
/>
|
<input
|
||||||
<Spring native from={{ opacity: 0 }} to={{ opacity: 1 }}>
|
ref={node => {
|
||||||
{styles => (
|
input = node;
|
||||||
|
}}
|
||||||
|
id="input"
|
||||||
|
type="text"
|
||||||
|
onKeyPress={e => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
addList(input.value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<animated.button
|
<animated.button
|
||||||
style={{ ...button, ...styles }}
|
style={{ ...button, ...styles }}
|
||||||
onClick={() => input.value.trim() && addList(input.value)}
|
onClick={() => input.value.trim() && addList(input.value)}
|
||||||
>
|
>
|
||||||
<AddIcon style={icon} />
|
<AddIcon style={icon} />
|
||||||
</animated.button>
|
</animated.button>
|
||||||
)}
|
</animated.div>
|
||||||
</Spring>
|
)}
|
||||||
</div>
|
</Transition>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (editing) {
|
if (editing) {
|
||||||
let input = null;
|
let input = null;
|
||||||
return (
|
return (
|
||||||
<div id="listselector" className="list--input">
|
<Transition
|
||||||
<input
|
native
|
||||||
ref={node => {
|
from={{ opacity: 0, maxHeight: 0 }}
|
||||||
input = node;
|
enter={{ opacity: 1, maxHeight: 64 }}
|
||||||
}}
|
leave={{ opacity: 0, maxHeight: 0 }}
|
||||||
defaultValue={lists.lists[list].name}
|
>
|
||||||
id="input"
|
{styles => (
|
||||||
type="text"
|
<animated.div
|
||||||
onKeyPress={e => {
|
style={styles}
|
||||||
if (e.key === 'Enter') {
|
id="listselector"
|
||||||
editList(input.value);
|
className="list--input"
|
||||||
}
|
>
|
||||||
}}
|
<input
|
||||||
/>
|
ref={node => {
|
||||||
<Spring native from={{ opacity: 0 }} to={{ opacity: 1 }}>
|
input = node;
|
||||||
{styles => (
|
}}
|
||||||
|
defaultValue={lists.lists[list].name}
|
||||||
|
id="input"
|
||||||
|
type="text"
|
||||||
|
onKeyPress={e => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
editList(input.value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<animated.button
|
<animated.button
|
||||||
style={{ ...button, ...styles }}
|
style={{ ...button }}
|
||||||
onClick={() => input.value.trim() && editList(input.value)}
|
onClick={() => input.value.trim() && editList(input.value)}
|
||||||
>
|
>
|
||||||
<CheckIcon style={icon} />
|
<CheckIcon style={icon} />
|
||||||
</animated.button>
|
</animated.button>
|
||||||
)}
|
</animated.div>
|
||||||
</Spring>
|
)}
|
||||||
</div>
|
</Transition>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (list) {
|
if (list) {
|
||||||
return (
|
return (
|
||||||
<div id="listselector">
|
<animated.div id="listselector">
|
||||||
<Select
|
<Select
|
||||||
style={{ fontSize: '1.5rem', width: '100%' }}
|
style={{ fontSize: '1.5rem', width: '100%' }}
|
||||||
value={list}
|
value={list}
|
||||||
@@ -98,7 +116,7 @@ export default function Selector({
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</animated.div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,32 +1,35 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { Transition } from 'react-spring';
|
||||||
|
|
||||||
import InputContainer from '../containers/InputContainer';
|
import InputContainer from '../containers/InputContainer';
|
||||||
import TodoListContainer from '../containers/TodoListContainer';
|
import TodoListContainer from '../containers/TodoListContainer';
|
||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
import Filters from './Filters';
|
import Filters from './Filters';
|
||||||
|
|
||||||
export default class Todos extends React.PureComponent {
|
export default function Todos({ list }) {
|
||||||
componentDidUpdate() {
|
return (
|
||||||
const { user, history } = this.props;
|
<div id="todos">
|
||||||
if (!user.user && !user.dirty) {
|
<Header />
|
||||||
history.replace('/login');
|
<Transition
|
||||||
}
|
from={{ opacity: 0, maxHeight: 0 }}
|
||||||
}
|
enter={{ opacity: 1, maxHeight: 38 }}
|
||||||
|
leave={{ opacity: 0, maxHeight: 0 }}
|
||||||
render() {
|
>
|
||||||
return (
|
{list && (styles => <InputContainer styles={styles} />)}
|
||||||
<div id="todos">
|
</Transition>
|
||||||
<Header />
|
<TodoListContainer />
|
||||||
<InputContainer />
|
<Transition
|
||||||
<TodoListContainer />
|
from={{ opacity: 0, maxHeight: 0 }}
|
||||||
<Filters />
|
enter={{ opacity: 1, maxHeight: 32 }}
|
||||||
</div>
|
leave={{ opacity: 0, maxHeight: 0 }}
|
||||||
);
|
>
|
||||||
}
|
{list && Filters}
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Todos.propTypes = {
|
Todos.propTypes = {
|
||||||
history: PropTypes.object.isRequired,
|
list: PropTypes.bool.isRequired,
|
||||||
user: PropTypes.object.isRequired,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import { connect } from 'react-redux';
|
|||||||
import Input from '../components/Input';
|
import Input from '../components/Input';
|
||||||
import { addTodo } from '../actions/todos';
|
import { addTodo } from '../actions/todos';
|
||||||
|
|
||||||
|
function mapStateToProps(state, ownProps) {
|
||||||
|
return { ...ownProps };
|
||||||
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
onClick: text => dispatch(addTodo(text)),
|
onClick: text => dispatch(addTodo(text)),
|
||||||
@@ -10,6 +14,6 @@ function mapDispatchToProps(dispatch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
null,
|
mapStateToProps,
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
)(Input);
|
)(Input);
|
||||||
|
|||||||
12
react/src/containers/MainViewContainer.js
Normal file
12
react/src/containers/MainViewContainer.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import MainView from '../components/MainView';
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
user: state.user,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(connect(mapStateToProps)(MainView));
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { withRouter } from 'react-router-dom';
|
|
||||||
|
|
||||||
import Todos from '../components/Todos';
|
import Todos from '../components/Todos';
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
user: state.user,
|
list: Boolean(state.lists.list),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(connect(mapStateToProps)(Todos));
|
export default connect(mapStateToProps)(Todos);
|
||||||
|
|||||||
Reference in New Issue
Block a user