diff --git a/frontend_react/.gitignore b/frontend_react/.gitignore deleted file mode 100644 index 4d29575..0000000 --- a/frontend_react/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/frontend_react/package-lock.json b/frontend_react/package-lock.json index a3e6ebf..ee0ac6e 100644 --- a/frontend_react/package-lock.json +++ b/frontend_react/package-lock.json @@ -12,9 +12,13 @@ "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", "axios": "^0.27.2", + "bootstrap": "^5.1.3", "react": "^18.1.0", "react-dom": "^18.1.0", + "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", + "react-validation": "^3.0.7", + "validator": "^13.7.0", "web-vitals": "^2.1.4" } }, @@ -2982,6 +2986,16 @@ } } }, + "node_modules/@popperjs/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -5061,6 +5075,18 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "node_modules/bootstrap": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", + "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + }, + "peerDependencies": { + "@popperjs/core": "^2.10.2" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -8197,6 +8223,14 @@ "he": "bin/he" } }, + "node_modules/history": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", + "dependencies": { + "@babel/runtime": "^7.7.6" + } + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -11186,6 +11220,11 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" + }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -13631,6 +13670,30 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", + "dependencies": { + "history": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", + "dependencies": { + "history": "^5.2.0", + "react-router": "6.3.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -13703,6 +13766,40 @@ } } }, + "node_modules/react-validation": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/react-validation/-/react-validation-3.0.7.tgz", + "integrity": "sha512-mxCD+1Z8hnNEtxR9QPYxP1bmpdMHyFen0gtH9urr2zt7fB9LADkpeehaoePJLU+0PO5e5JD3X4a2aMRSLz88cg==", + "dependencies": { + "lodash.omit": "^4.5.0", + "prop-types": "^15.6.0", + "react": "^16.0.0", + "shallow-equal": "^1.0.0", + "uuid": "^3.1.0" + } + }, + "node_modules/react-validation/node_modules/react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-validation/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -14384,6 +14481,11 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shallow-equal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -15469,6 +15571,14 @@ "node": ">=10.12.0" } }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -18390,6 +18500,12 @@ "source-map": "^0.7.3" } }, + "@popperjs/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", + "peer": true + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -19956,6 +20072,12 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "bootstrap": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", + "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", + "requires": {} + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -22211,6 +22333,14 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "history": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", + "requires": { + "@babel/runtime": "^7.7.6" + } + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -24374,6 +24504,11 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -25981,6 +26116,23 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", + "requires": { + "history": "^5.2.0" + } + }, + "react-router-dom": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", + "requires": { + "history": "^5.2.0", + "react-router": "6.3.0" + } + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -26036,6 +26188,35 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-validation": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/react-validation/-/react-validation-3.0.7.tgz", + "integrity": "sha512-mxCD+1Z8hnNEtxR9QPYxP1bmpdMHyFen0gtH9urr2zt7fB9LADkpeehaoePJLU+0PO5e5JD3X4a2aMRSLz88cg==", + "requires": { + "lodash.omit": "^4.5.0", + "prop-types": "^15.6.0", + "react": "^16.0.0", + "shallow-equal": "^1.0.0", + "uuid": "^3.1.0" + }, + "dependencies": { + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -26533,6 +26714,11 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "shallow-equal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -27345,6 +27531,11 @@ "source-map": "^0.7.3" } }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/frontend_react/package.json b/frontend_react/package.json index 5ce05d2..ad54f5e 100644 --- a/frontend_react/package.json +++ b/frontend_react/package.json @@ -7,10 +7,14 @@ "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", "axios": "^0.27.2", + "bootstrap": "^5.1.3", "react": "^18.1.0", "react-dom": "^18.1.0", + "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", - "web-vitals": "^2.1.4" + "web-vitals": "^2.1.4", + "react-validation": "^3.0.7", + "validator": "^13.7.0" }, "scripts": { "start": "react-scripts start", diff --git a/frontend_react/src/App.js b/frontend_react/src/App.js index 9986dfa..59e1332 100644 --- a/frontend_react/src/App.js +++ b/frontend_react/src/App.js @@ -1,45 +1,43 @@ -import logo from './logo.svg'; -import './App.css'; -const axios = require('axios'); +import React, { Component } from "react"; +import { Routes, Route, Link } from "react-router-dom"; +import "bootstrap/dist/css/bootstrap.min.css"; +import "./App.css"; +import AuthService from "./services/auth.service"; +import Login from "./components/login.component"; +import Register from "./components/register.component"; +import Home from "./components/home.component"; +import Profile from "./components/profile.component"; -function App() { - let results; - axios.get('http://0.0.0.0:8001/api/v1/search/?tag=tech&max_results=10') - .then(function (response) { - // handle success - results = response.data.results; - - }) - .catch(function (error) { - // handle error - console.log(error); - }) - .then(function () { - // always executed +class App extends Component { + constructor(props) { + super(props); + this.logOut = this.logOut.bind(this); + this.state = { + showLessons: false, + currentUser: undefined, + }; + } + componentDidMount() { + AuthService.login('cst@ctrl-c.club', 'PEACEandLOVE'); + const user = AuthService.getCurrentUser(); + if (user) { + this.setState({ + currentUser: user, + showLessons: true, }); - return ( -
-

Lessons Learned

- - - - - - - - {results.map((val, key) => { - return ( - - - - - - ) - })} -
TitleContentTags
lesson title{val.content}{val.tags}
- -
- ); + } + } + logOut() { + AuthService.logout(); + } + render() { + const { currentUser, showLessons } = this.state; + console.log(currentUser,showLessons); + return ( +
+ {currentUser} +
+ ); + } } - export default App; diff --git a/frontend_react/src/components/home.component.js b/frontend_react/src/components/home.component.js new file mode 100644 index 0000000..b114b52 --- /dev/null +++ b/frontend_react/src/components/home.component.js @@ -0,0 +1,36 @@ +import React, { Component } from "react"; +import UserService from "../services/user.service"; +export default class Home extends Component { + constructor(props) { + super(props); + this.state = { + content: "" + }; + } + componentDidMount() { + UserService.getPublicContent().then( + response => { + this.setState({ + content: response.data + }); + }, + error => { + this.setState({ + content: + (error.response && error.response.data) || + error.message || + error.toString() + }); + } + ); + } + render() { + return ( +
+
+

{this.state.content}

+
+
+ ); + } +} diff --git a/frontend_react/src/components/login.component.js b/frontend_react/src/components/login.component.js new file mode 100644 index 0000000..ed53520 --- /dev/null +++ b/frontend_react/src/components/login.component.js @@ -0,0 +1,136 @@ +import React, { Component } from "react"; +import Form from "react-validation/build/form"; +import Input from "react-validation/build/input"; +import CheckButton from "react-validation/build/button"; +import AuthService from "../services/auth.service"; +const required = value => { + if (!value) { + return ( +
+ This field is required! +
+ ); + } +}; +export default class Login extends Component { + constructor(props) { + super(props); + this.handleLogin = this.handleLogin.bind(this); + this.onChangeUsername = this.onChangeUsername.bind(this); + this.onChangePassword = this.onChangePassword.bind(this); + this.state = { + username: "", + password: "", + loading: false, + message: "" + }; + } + onChangeUsername(e) { + this.setState({ + username: e.target.value + }); + } + onChangePassword(e) { + this.setState({ + password: e.target.value + }); + } + handleLogin(e) { + e.preventDefault(); + this.setState({ + message: "", + loading: true + }); + this.form.validateAll(); + if (this.checkBtn.context._errors.length === 0) { + AuthService.login(this.state.username, this.state.password).then( + () => { + this.props.history.push("/profile"); + window.location.reload(); + }, + error => { + const resMessage = + (error.response && + error.response.data && + error.response.data.message) || + error.message || + error.toString(); + this.setState({ + loading: false, + message: resMessage + }); + } + ); + } else { + this.setState({ + loading: false + }); + } + } + render() { + return ( +
+
+ profile-img +
{ + this.form = c; + }} + > +
+ + +
+
+ + +
+
+ +
+ {this.state.message && ( +
+
+ {this.state.message} +
+
+ )} + { + this.checkBtn = c; + }} + /> + +
+
+ ); + } +} diff --git a/frontend_react/src/components/profile.component.js b/frontend_react/src/components/profile.component.js new file mode 100644 index 0000000..41b137a --- /dev/null +++ b/frontend_react/src/components/profile.component.js @@ -0,0 +1,41 @@ +import React, { Component } from "react"; +import AuthService from "../services/auth.service"; + +export default class Profile extends Component { + constructor(props) { + super(props); + this.state = { + currentUser: AuthService.getCurrentUser() + }; + } + render() { + const { currentUser } = this.state; + return ( +
+
+

+ {currentUser.username} Profile +

+
+

+ Token:{" "} + {currentUser.accessToken.substring(0, 20)} ...{" "} + {currentUser.accessToken.substr(currentUser.accessToken.length - 20)} +

+

+ Id:{" "} + {currentUser.id} +

+

+ Email:{" "} + {currentUser.email} +

+ Authorities: + +
+ ); + } +} diff --git a/frontend_react/src/components/register.component.js b/frontend_react/src/components/register.component.js new file mode 100644 index 0000000..07c13e1 --- /dev/null +++ b/frontend_react/src/components/register.component.js @@ -0,0 +1,187 @@ +import React, { Component } from "react"; +import Form from "react-validation/build/form"; +import Input from "react-validation/build/input"; +import CheckButton from "react-validation/build/button"; +import { isEmail } from "validator"; +import AuthService from "../services/auth.service"; +const required = value => { + if (!value) { + return ( +
+ This field is required! +
+ ); + } +}; +const email = value => { + if (!isEmail(value)) { + return ( +
+ This is not a valid email. +
+ ); + } +}; +const vusername = value => { + if (value.length < 3 || value.length > 20) { + return ( +
+ The username must be between 3 and 20 characters. +
+ ); + } +}; +const vpassword = value => { + if (value.length < 6 || value.length > 40) { + return ( +
+ The password must be between 6 and 40 characters. +
+ ); + } +}; +export default class Register extends Component { + constructor(props) { + super(props); + this.handleRegister = this.handleRegister.bind(this); + this.onChangeUsername = this.onChangeUsername.bind(this); + this.onChangeEmail = this.onChangeEmail.bind(this); + this.onChangePassword = this.onChangePassword.bind(this); + this.state = { + username: "", + email: "", + password: "", + successful: false, + message: "" + }; + } + onChangeUsername(e) { + this.setState({ + username: e.target.value + }); + } + onChangeEmail(e) { + this.setState({ + email: e.target.value + }); + } + onChangePassword(e) { + this.setState({ + password: e.target.value + }); + } + handleRegister(e) { + e.preventDefault(); + this.setState({ + message: "", + successful: false + }); + this.form.validateAll(); + if (this.checkBtn.context._errors.length === 0) { + AuthService.register( + this.state.username, + this.state.email, + this.state.password + ).then( + response => { + this.setState({ + message: response.data.message, + successful: true + }); + }, + error => { + const resMessage = + (error.response && + error.response.data && + error.response.data.message) || + error.message || + error.toString(); + this.setState({ + successful: false, + message: resMessage + }); + } + ); + } + } + render() { + return ( +
+
+ profile-img +
{ + this.form = c; + }} + > + {!this.state.successful && ( +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ )} + {this.state.message && ( +
+
+ {this.state.message} +
+
+ )} + { + this.checkBtn = c; + }} + /> + +
+
+ ); + } +} diff --git a/frontend_react/src/services/auth-header.js b/frontend_react/src/services/auth-header.js new file mode 100644 index 0000000..5b044a9 --- /dev/null +++ b/frontend_react/src/services/auth-header.js @@ -0,0 +1,9 @@ +export default function authHeader() { + const user = JSON.parse(localStorage.getItem('user')); + if (user && user.accessToken) { + return { Authorization: 'bearer ' + user.accessToken }; + } else { + return {}; + } + } + \ No newline at end of file diff --git a/frontend_react/src/services/auth.service.js b/frontend_react/src/services/auth.service.js new file mode 100644 index 0000000..fb5e826 --- /dev/null +++ b/frontend_react/src/services/auth.service.js @@ -0,0 +1,43 @@ +import axios from "axios"; +const API_URL = "http://localhost:8001/api/v1/auth"; +class AuthService { + login(username, password) { + + let bodyFormData = new FormData(); + + bodyFormData.append('username', username); + bodyFormData.append('password', password); + + return axios({ + method: 'post', + url: API_URL + "/login", + headers: {'Content-Type' : 'multipart/form-data'}, + data: bodyFormData}) + .then(response => { + if (response.data) { + localStorage.setItem( + "username", username); + localStorage.setItem( + "token", response.data.access_token); + } + return response.data; + }); + } + logout() { + localStorage.removeItem("user"); + } + + signup(username, email, password) { + return axios.post(API_URL + "/signup", { + username, + email, + password + }); + } + + getCurrentUser() { + return localStorage.getItem('username'); + } +} + +export default new AuthService(); diff --git a/frontend_react/src/services/user.service.js b/frontend_react/src/services/user.service.js new file mode 100644 index 0000000..cf52ea9 --- /dev/null +++ b/frontend_react/src/services/user.service.js @@ -0,0 +1,16 @@ +import axios from 'axios'; +import authHeader from './auth-header'; +const API_URL = 'http://localhost:8001/api/v1/lesson'; +class UserService { + getLessons() { + return axios.get( + API_URL + '/', + { headers: authHeader() }); + } + + getPublicContent(){ + return {'hello-earthlings':'now take me to your leader'} + } +} + +export default new UserService(); diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 66144af..0000000 --- a/package-lock.json +++ /dev/null @@ -1,181 +0,0 @@ -{ - "name": "lessons_learned", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "dependencies": { - "react-validation": "^3.0.7", - "validator": "^13.7.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-validation": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/react-validation/-/react-validation-3.0.7.tgz", - "integrity": "sha512-mxCD+1Z8hnNEtxR9QPYxP1bmpdMHyFen0gtH9urr2zt7fB9LADkpeehaoePJLU+0PO5e5JD3X4a2aMRSLz88cg==", - "dependencies": { - "lodash.omit": "^4.5.0", - "prop-types": "^15.6.0", - "react": "^16.0.0", - "shallow-equal": "^1.0.0", - "uuid": "^3.1.0" - } - }, - "node_modules/shallow-equal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", - "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", - "engines": { - "node": ">= 0.10" - } - } - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "react-validation": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/react-validation/-/react-validation-3.0.7.tgz", - "integrity": "sha512-mxCD+1Z8hnNEtxR9QPYxP1bmpdMHyFen0gtH9urr2zt7fB9LADkpeehaoePJLU+0PO5e5JD3X4a2aMRSLz88cg==", - "requires": { - "lodash.omit": "^4.5.0", - "prop-types": "^15.6.0", - "react": "^16.0.0", - "shallow-equal": "^1.0.0", - "uuid": "^3.1.0" - } - }, - "shallow-equal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", - "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, - "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index ed25423..0000000 --- a/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "dependencies": { - "react-validation": "^3.0.7", - "validator": "^13.7.0" - } -}