diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0a6276eb..6f2b9a37 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ stages: - bundle variables: - VERSION: 0.0.6 + VERSION: 0.0.7 build-go: image: golang:1.16.2 diff --git a/docs/changelog.md b/docs/changelog.md index 19a35080..07be997e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,3 +1,6 @@ +# 0.0.7 +-Switch redux -> context. + # 0.0.6 - Fix hitting dashboard when logged out - Clean up app.js diff --git a/web/package-lock.json b/web/package-lock.json index a86fda08..de4226a5 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -19,21 +19,13 @@ "react": "^17.0.2", "react-bootstrap": "^1.5.2", "react-cookie": "^4.0.3", - "react-data-grid": "*", "react-dom": "^17.0.2", "react-redux": "^7.2.3", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "react-spinners": "^0.10.6", - "react-table": "^7.6.3", - "react-toast": "^1.0.1", - "react-toast-notifications": "^2.4.3", "react-toastify": "^7.0.3", - "reactstrap": "^8.9.0", - "redux": "^4.0.5", - "redux-persist": "^6.0.0", - "redux-thunk": "^2.3.0", - "web-vitals": "^1.1.1" + "reactstrap": "^8.9.0" }, "devDependencies": { "redux-devtools-extension": "^2.13.9", @@ -16328,18 +16320,6 @@ "react": ">= 16.3.0" } }, - "node_modules/react-data-grid": { - "version": "7.0.0-canary.38", - "resolved": "https://registry.npmjs.org/react-data-grid/-/react-data-grid-7.0.0-canary.38.tgz", - "integrity": "sha512-JjMyChuh9KxOtYmpxrOuPBI6EYIbNLn/+pjwoQYeD7d5vkWMURWWhyLX1NJkT5bt5LF2qxOSQiFf3G6YndxlAg==", - "dependencies": { - "clsx": "^1.1.1" - }, - "peerDependencies": { - "react": "^16.14 || ^17.0", - "react-dom": "^16.14 || ^17.0" - } - }, "node_modules/react-dev-utils": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", @@ -16733,39 +16713,6 @@ "react-dom": "^16.0.0 || ^17.0.0" } }, - "node_modules/react-table": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.6.3.tgz", - "integrity": "sha512-hfPF13zDLxPMpLKzIKCE8RZud9T/XrRTsaCIf8zXpWZIZ2juCl7qrGpo3AQw9eAetXV5DP7s2GDm+hht7qq5Dw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.3 || ^17.0.0-0" - } - }, - "node_modules/react-toast": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-toast/-/react-toast-1.0.1.tgz", - "integrity": "sha512-xqkO5ZJiJDOLxycZts7xi729blKw4frhg2I4bcIjT7mVlshxu0AsaHlKAdPhVeACAnn8nnamxg6zoYoC9BEjjg==", - "peerDependencies": { - "react": ">=16" - } - }, - "node_modules/react-toast-notifications": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/react-toast-notifications/-/react-toast-notifications-2.4.3.tgz", - "integrity": "sha512-Ya/i2dCjN95Ytb/pwbAVmDMSKQwGeeGOhUThtjFQx2XAFKE+fQnodLlIylhgZfsInxdUXPFGFnzTdGS8JafuLA==", - "dependencies": { - "@emotion/core": "^10.0.14", - "react-transition-group": "^4.4.1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - } - }, "node_modules/react-toastify": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-7.0.3.tgz", @@ -17011,14 +16958,6 @@ "redux": "^3.1.0 || ^4.0.0" } }, - "node_modules/redux-persist": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", - "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", - "peerDependencies": { - "redux": ">4.0.0" - } - }, "node_modules/redux-thunk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", @@ -20691,11 +20630,6 @@ "minimalistic-assert": "^1.0.0" } }, - "node_modules/web-vitals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.1.tgz", - "integrity": "sha512-jYOaqu01Ny1NvMwJ3dBJDUOJ2PGWknZWH4AUnvFOscvbdHMERIKT2TlgiAey5rVyfOePG7so2JcXXZdSnBvioQ==" - }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -35007,14 +34941,6 @@ "universal-cookie": "^4.0.0" } }, - "react-data-grid": { - "version": "7.0.0-canary.38", - "resolved": "https://registry.npmjs.org/react-data-grid/-/react-data-grid-7.0.0-canary.38.tgz", - "integrity": "sha512-JjMyChuh9KxOtYmpxrOuPBI6EYIbNLn/+pjwoQYeD7d5vkWMURWWhyLX1NJkT5bt5LF2qxOSQiFf3G6YndxlAg==", - "requires": { - "clsx": "^1.1.1" - } - }, "react-dev-utils": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", @@ -35331,27 +35257,6 @@ "@emotion/core": "^10.0.35" } }, - "react-table": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.6.3.tgz", - "integrity": "sha512-hfPF13zDLxPMpLKzIKCE8RZud9T/XrRTsaCIf8zXpWZIZ2juCl7qrGpo3AQw9eAetXV5DP7s2GDm+hht7qq5Dw==", - "requires": {} - }, - "react-toast": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-toast/-/react-toast-1.0.1.tgz", - "integrity": "sha512-xqkO5ZJiJDOLxycZts7xi729blKw4frhg2I4bcIjT7mVlshxu0AsaHlKAdPhVeACAnn8nnamxg6zoYoC9BEjjg==", - "requires": {} - }, - "react-toast-notifications": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/react-toast-notifications/-/react-toast-notifications-2.4.3.tgz", - "integrity": "sha512-Ya/i2dCjN95Ytb/pwbAVmDMSKQwGeeGOhUThtjFQx2XAFKE+fQnodLlIylhgZfsInxdUXPFGFnzTdGS8JafuLA==", - "requires": { - "@emotion/core": "^10.0.14", - "react-transition-group": "^4.4.1" - } - }, "react-toastify": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-7.0.3.tgz", @@ -35543,12 +35448,6 @@ "dev": true, "requires": {} }, - "redux-persist": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", - "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", - "requires": {} - }, "redux-thunk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", @@ -38488,11 +38387,6 @@ "minimalistic-assert": "^1.0.0" } }, - "web-vitals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.1.tgz", - "integrity": "sha512-jYOaqu01Ny1NvMwJ3dBJDUOJ2PGWknZWH4AUnvFOscvbdHMERIKT2TlgiAey5rVyfOePG7so2JcXXZdSnBvioQ==" - }, "webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", diff --git a/web/package.json b/web/package.json index 745e2036..44605bb0 100644 --- a/web/package.json +++ b/web/package.json @@ -14,21 +14,13 @@ "react": "^17.0.2", "react-bootstrap": "^1.5.2", "react-cookie": "^4.0.3", - "react-data-grid": "*", "react-dom": "^17.0.2", "react-redux": "^7.2.3", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "react-spinners": "^0.10.6", - "react-table": "^7.6.3", - "react-toast": "^1.0.1", - "react-toast-notifications": "^2.4.3", "react-toastify": "^7.0.3", - "reactstrap": "^8.9.0", - "redux": "^4.0.5", - "redux-persist": "^6.0.0", - "redux-thunk": "^2.3.0", - "web-vitals": "^1.1.1" + "reactstrap": "^8.9.0" }, "scripts": { "start": "react-scripts start", diff --git a/web/src/Actions/api.js b/web/src/Actions/api.js deleted file mode 100644 index 57e591d2..00000000 --- a/web/src/Actions/api.js +++ /dev/null @@ -1,18 +0,0 @@ -import ApiService from "../Services/api.service"; - -export const getStats = () => { - return ApiService.getStats().then( - (data) => { - return data.data; - } - ); -}; - -export const getRecentScrobbles = (id) => { - return ApiService.getRecentScrobbles(id).then( - (data) => { - return data.data; - } - ); -}; - diff --git a/web/src/Actions/auth.js b/web/src/Actions/auth.js deleted file mode 100644 index 8f37d2f4..00000000 --- a/web/src/Actions/auth.js +++ /dev/null @@ -1,105 +0,0 @@ -import { - REGISTER_SUCCESS, - REGISTER_FAIL, - LOGIN_SUCCESS, - LOGIN_FAIL, - LOGOUT, -} from "./types"; - - import { toast } from 'react-toastify'; - import jwt from 'jwt-decode' - import AuthService from "../Services/auth.service"; - import eventBus from "./eventBus"; - - export const register = (username, email, password) => (dispatch) => { - return AuthService.register(username, email, password).then( - (data) => { - if (data.message) { - toast.success('Successfully registered. Please sign in'); - dispatch({ - type: REGISTER_SUCCESS, - }); - - return Promise.resolve(); - } - - toast.error(data.error ? data.error: 'An Unknown Error has occurred') - dispatch({ - type: REGISTER_FAIL, - }); - - return Promise.reject(); - }, - (error) => { - const message = - (error.response && - error.response.data && - error.response.data.message) || - error.message || - error.toString(); - - toast.error(message); - - dispatch({ - type: REGISTER_FAIL, - }); - - return Promise.reject(); - } - ); - }; - - export const login = (username, password) => (dispatch) => { - return AuthService.login(username, password).then( - (data) => { - if (data.token) { - toast.success('Login Success'); - let user = jwt(data.token) - - dispatch({ - type: LOGIN_SUCCESS, - payload: { jwt: data.token, sub: user.sub, exp: user.exp }, - }); - return Promise.resolve(); - } - - toast.error(data.error ? data.error: 'An Unknown Error has occurred') - dispatch({ - type: LOGIN_FAIL, - }); - return Promise.reject(); - }, - (error) => { - const message = - (error.response && - error.response.data && - error.response.data.error) || - error.message || - error.toString(); - - toast.error('Error: ' + message) - dispatch({ - type: LOGIN_FAIL, - }); - - return Promise.reject(); - } - ); - }; - - export const logout = (dispatch) => { - // Clear local data - AuthService.logout() - - // window.location.pathname("/") - window.location.reload() - - // TODO; Clear Redux - ENABLE THIS WHEN I FIGURE OUT HOW 2 DISPATCH - // dispatch({ - // type: LOGOUT, - // payload: {}, - // }); - - // // Issue to all listeners to reload - eventBus.dispatch(LOGOUT); - }; diff --git a/web/src/Actions/eventBus.js b/web/src/Actions/eventBus.js deleted file mode 100644 index 17bfcd26..00000000 --- a/web/src/Actions/eventBus.js +++ /dev/null @@ -1,13 +0,0 @@ -const eventBus = { - on(event, callback) { - document.addEventListener(event, (e) => callback(e.detail)); - }, - dispatch(event, data) { - document.dispatchEvent(new CustomEvent(event, { detail: data })); - }, - remove(event, callback) { - document.removeEventListener(event, callback); - }, -}; - -export default eventBus \ No newline at end of file diff --git a/web/src/Actions/types.js b/web/src/Actions/types.js deleted file mode 100644 index 98fda989..00000000 --- a/web/src/Actions/types.js +++ /dev/null @@ -1,5 +0,0 @@ -export const REGISTER_SUCCESS = "REGISTER_SUCCESS"; -export const REGISTER_FAIL = "REGISTER_FAIL"; -export const LOGIN_SUCCESS = "LOGIN_SUCCESS"; -export const LOGIN_FAIL = "LOGIN_FAIL"; -export const LOGOUT = "LOGOUT"; diff --git a/web/src/Api/index.js b/web/src/Api/index.js new file mode 100644 index 00000000..213e5c7e --- /dev/null +++ b/web/src/Api/index.js @@ -0,0 +1,86 @@ +import axios from 'axios'; +import jwt from 'jwt-decode' +import { toast } from 'react-toastify'; + +function getHeaders() { + // Todo: move this to use Context values instead. + const user = JSON.parse(localStorage.getItem('user')); + + if (user && user.jwt) { + return { Authorization: 'Bearer ' + user.jwt }; + } else { + return {}; + } +} + +export const PostLogin = (formValues) => { + // const { setLoading, setUser } = useContext(AuthContext); + // setLoading(true) + return axios.post(process.env.REACT_APP_API_URL + "login", formValues) + .then((response) => { + if (response.data.token) { + let expandedUser = jwt(response.data.token) + let user = { + jwt: response.data.token, + uuid: expandedUser.sub, + exp: expandedUser.exp, + } + + // Set in local storage + localStorage.setItem('user', JSON.stringify(user)); + + // Set in context + // setUser(user) + + toast.success('Successfully logged in.'); + // setLoading(false) + return user; + } else { + toast.error(response.data.error ? response.data.error: 'An Unknown Error has occurred'); + // setLoading(false) + return null + } + }) +}; + +export const PostRegister = (formValues) => { + axios.post(process.env.REACT_APP_API_URL + "register", formValues) + .then((response) => { + if (response.data.token) { + toast.success('Successfully registered. Please sign in'); + + return Promise.resolve(); + } else { + toast.error(response.data.error ? response.data.error: 'An Unknown Error has occurred'); + + return Promise.reject(); + } + }) + .error((error) => { + const message = + (error.response && + error.response.data && + error.response.data.message) || + error.message || + error.toString(); + + toast.error(message ? message : 'An Unknown Error has occurred') + return Promise.reject(); + }); +}; + +export const getStats = () => { + return axios.get(process.env.REACT_APP_API_URL + "stats").then( + (data) => { + data.isLoading = false; + return data.data; + } + ); +}; + +export const getRecentScrobbles = (id) => { + return axios.get(process.env.REACT_APP_API_URL + "user/" + id + "/scrobbles", { headers: getHeaders() }) + .then((data) => { + return data.data; + }); +}; diff --git a/web/src/App.js b/web/src/App.js index 02c1c903..7c440fec 100644 --- a/web/src/App.js +++ b/web/src/App.js @@ -3,47 +3,36 @@ import Home from './Pages/Home'; import About from './Pages/About'; import Dashboard from './Pages/Dashboard'; -import Admin from './Pages/Admin'; import Profile from './Pages/Profile'; import Login from './Pages/Login'; import Settings from './Pages/Settings'; import Register from './Pages/Register'; import Navigation from './Components/Navigation'; -// import { logout } from './Actions/auth'; import { Route, Switch, withRouter } from 'react-router-dom'; -import { Component } from 'react'; import 'bootstrap/dist/css/bootstrap.min.css'; -class App extends Component { - constructor(props) { - super(props); - this.state = { - true: true, - }; - } +const App = () => { + let boolTrue = true - render() { return (
- + - -
); - } } + export default withRouter(App); \ No newline at end of file diff --git a/web/src/Components/HomeBanner.js b/web/src/Components/HomeBanner.js index c4a4cdf4..66332e4a 100644 --- a/web/src/Components/HomeBanner.js +++ b/web/src/Components/HomeBanner.js @@ -1,65 +1,45 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import '../App.css'; import './HomeBanner.css'; -import { getStats } from '../Actions/api'; +import { getStats } from '../Api/index'; import ClipLoader from 'react-spinners/ClipLoader' -class HomeBanner extends React.Component { - constructor(props) { - super(props); - this.state = { - isLoading: true, - userCount: 0, - scrobbleCount: 0, - trackCount: 0, - artistCount: 0, - }; - } +const HomeBanner = () => { + let [bannerData, setBannerData] = useState({}); + let [isLoading, setIsLoading] = useState(true); - componentDidMount() { + useEffect(() => { getStats() - .then((data) => { - this.setState({ - isLoading: false, - userCount: data.users, - scrobbleCount: data.scrobbles, - trackCount: data.tracks, - artistCount: data.artists, - }); - }) - .catch(() => { - this.setState({ - isLoading: false - }); - }); - } + .then(data => { + setBannerData(data); + setIsLoading(false); + }) + }, []) - render() { - return ( -
-
- {this.state.isLoading - ? - : {this.state.scrobbleCount}}
Scrobbles -
-
- {this.state.isLoading - ? - : {this.state.userCount}}
Users -
-
- {this.state.isLoading - ? - : {this.state.trackCount}}
Tracks -
-
- {this.state.isLoading - ? - : {this.state.artistCount}}
Artists -
+ return ( +
+
+ {isLoading + ? + : {bannerData.scrobbles}}
Scrobbles
- ); - } +
+ {isLoading + ? + : {bannerData.users}}
Users +
+
+ {isLoading + ? + : {bannerData.tracks}}
Tracks +
+
+ {isLoading + ? + : {bannerData.artists}}
Artists +
+
+ ); } export default HomeBanner; diff --git a/web/src/Components/Navigation.js b/web/src/Components/Navigation.js index f8f93239..b1dabd78 100644 --- a/web/src/Components/Navigation.js +++ b/web/src/Components/Navigation.js @@ -3,14 +3,8 @@ import { Navbar, NavbarBrand, Collapse, Nav, NavbarToggler, NavItem } from 'reac import { Link } from 'react-router-dom'; import logo from '../logo.png'; import './Navigation.css'; -import { connect } from 'react-redux'; -import { logout } from '../Actions/auth'; -import eventBus from "../Actions/eventBus"; -import { - LOGIN_SUCCESS, - LOGOUT, -} from "../Actions/types"; +import logout from '../Contexts/AuthContextProvider'; const menuItems = [ 'Home', @@ -45,17 +39,6 @@ class Navigation extends Component { }); } - eventBus.on(LOGIN_SUCCESS, () => - this.setState({ isLoggedIn: true }) - ); - - eventBus.on(LOGOUT, () => - this.setState({ isLoggedIn: false }) - ); - } - - componentWillUnmount() { - eventBus.remove(LOGIN_SUCCESS); } _handleClick(menuItem) { @@ -211,12 +194,4 @@ class Navigation extends Component { } } -function mapStateToProps(state) { - const { isLoggedIn } = state.auth; - - return { - isLoggedIn - }; -} - -export default connect(mapStateToProps)(Navigation); \ No newline at end of file +export default Navigation; \ No newline at end of file diff --git a/web/src/Contexts/AuthContext.js b/web/src/Contexts/AuthContext.js new file mode 100644 index 00000000..c5b074de --- /dev/null +++ b/web/src/Contexts/AuthContext.js @@ -0,0 +1,5 @@ +import React from 'react'; + +const AuthContext = React.createContext(); + +export default AuthContext; \ No newline at end of file diff --git a/web/src/Contexts/AuthContextProvider.js b/web/src/Contexts/AuthContextProvider.js new file mode 100644 index 00000000..b94905df --- /dev/null +++ b/web/src/Contexts/AuthContextProvider.js @@ -0,0 +1,65 @@ +import React, { useState, useEffect } from 'react'; +import { toast } from 'react-toastify'; +import AuthContext from './AuthContext'; + +import { PostLogin, PostRegister } from '../Api/index'; + +const AuthContextProvider = ({ children }) => { + const [user, setUser] = useState(); + const [loading, setLoading] = useState(false); + + useEffect(() => { + setLoading(true) + const user = JSON.parse(localStorage.getItem('user')); + if (user && user.jwt) { + setUser(user) + } + setLoading(false) + }, []); + + const Login = (formValues) => { + setLoading(true); + PostLogin(formValues).then(user => { + if (user) { + setUser(user); + const { history } = this.props; + history.push("/dashboard"); + } + setLoading(false); + }) + } + + const Register = (formValues) => { + const { history } = this.props; + + setLoading(true); + return PostRegister(formValues).then(response => { + if (response) { + history.push("/login"); + } + setLoading(false); + }); + }; + + const Logout = () => { + localStorage.removeItem("user"); + setUser(null) + toast.success('Successfully logged out.'); + }; + + return ( + + {children} + + ); +}; + +export default AuthContextProvider; \ No newline at end of file diff --git a/web/src/Pages/About.js b/web/src/Pages/About.js index 9e800c3a..cb9690ab 100644 --- a/web/src/Pages/About.js +++ b/web/src/Pages/About.js @@ -1,7 +1,7 @@ import '../App.css'; import './About.css'; -function About() { +const About = () => { return (

diff --git a/web/src/Pages/Admin.js b/web/src/Pages/Admin.js deleted file mode 100644 index e2927dfb..00000000 --- a/web/src/Pages/Admin.js +++ /dev/null @@ -1,45 +0,0 @@ -import React, { Component } from "react"; - -import UserService from "../Services/user.service"; - -class Admin extends Component { - constructor(props) { - super(props); - - this.state = { - content: "" - }; - } - - componentDidMount() { - UserService.getAdminBoard().then( - response => { - this.setState({ - content: response.data - }); - }, - error => { - this.setState({ - content: - (error.response && - error.response.data && - error.response.data.message) || - error.message || - error.toString() - }); - } - ); - } - - render() { - return ( -
-
-

{this.state.content}

-
-
- ); - } -} - -export default Admin; \ No newline at end of file diff --git a/web/src/Pages/Dashboard.js b/web/src/Pages/Dashboard.js index 20c0a08a..11f18038 100644 --- a/web/src/Pages/Dashboard.js +++ b/web/src/Pages/Dashboard.js @@ -1,8 +1,8 @@ import React from 'react'; import '../App.css'; import './Dashboard.css'; -import { connect } from 'react-redux'; -import { getRecentScrobbles } from '../Actions/api'; + +import { getRecentScrobbles } from '../Api/index'; import ScaleLoader from 'react-spinners/ScaleLoader'; import ScrobbleTable from "../Components/ScrobbleTable"; @@ -53,17 +53,4 @@ class Dashboard extends React.Component { } } -function mapStateToProps(state) { - const { isLoggedIn } = state.auth; - let uuid = null; - if (isLoggedIn) { - uuid = state.auth.user.uuid - } - - return { - isLoggedIn, - uuid, - }; -} - -export default connect(mapStateToProps)(Dashboard); +export default Dashboard; diff --git a/web/src/Pages/Login.js b/web/src/Pages/Login.js index 34e17791..6c04dad7 100644 --- a/web/src/Pages/Login.js +++ b/web/src/Pages/Login.js @@ -1,102 +1,57 @@ -import React from 'react'; +import React, { useContext } from 'react'; import '../App.css'; import './Login.css'; import { Button } from 'reactstrap'; import { Formik, Form, Field } from 'formik'; import ScaleLoader from 'react-spinners/ScaleLoader'; -import { connect } from 'react-redux'; -import { login } from '../Actions/auth'; -import eventBus from "../Actions/eventBus"; -import { LOGIN_SUCCESS } from '../Actions/types'; +import AuthContext from '../Contexts/AuthContext'; -class Login extends React.Component { - constructor(props) { - super(props); - this.state = {username: '', password: '', loading: false}; - } +const Login = () => { + let boolTrue = true; + let { Login, loading } = useContext(AuthContext); - componentDidMount() { - const { history, isLoggedIn } = this.props; - - if (isLoggedIn) { - history.push("/dashboard") - } - } - - handleLogin(values) { - this.setState({loading: true}); - - const { dispatch, history } = this.props; - - dispatch(login(values.username, values.password)) - .then(() => { - this.setState({ - loading: false, - isLoggedIn: true - }); - - eventBus.dispatch(LOGIN_SUCCESS, { isLoggedIn: true }); - history.push("/dashboard"); - }) - .catch(() => { - this.setState({ - loading: false - }); - }); - } - - render() { - let trueBool = true; - return ( -
-

- Login -

-
- this.handleLogin(values)} - > -
- -
- -

- -
-
-
+ return ( +
+

+ Login +

+
+ Login(values)} + > +
+ +
+ +

+ +
+
- ); - } +
+ ); } -function mapStateToProps(state) { - const { isLoggedIn } = state.auth; - return { - isLoggedIn - }; -} - -export default connect(mapStateToProps)(Login); +export default Login; diff --git a/web/src/Pages/Profile.js b/web/src/Pages/Profile.js index f87559b7..2d9e11da 100644 --- a/web/src/Pages/Profile.js +++ b/web/src/Pages/Profile.js @@ -1,7 +1,6 @@ import React from 'react'; import '../App.css'; import './Dashboard.css'; -import { connect } from 'react-redux'; class Profile extends React.Component { componentDidMount() { @@ -23,11 +22,4 @@ class Profile extends React.Component { } } -function mapStateToProps(state) { - const { isLoggedIn } = state.auth; - return { - isLoggedIn, - }; -} - -export default connect(mapStateToProps)(Profile); \ No newline at end of file +export default Profile; \ No newline at end of file diff --git a/web/src/Pages/Register.js b/web/src/Pages/Register.js index 2c1ed49c..97aaa9a5 100644 --- a/web/src/Pages/Register.js +++ b/web/src/Pages/Register.js @@ -3,9 +3,8 @@ import '../App.css'; import './Register.css'; import { Button } from 'reactstrap'; import ScaleLoader from "react-spinners/ScaleLoader"; -import { register } from '../Actions/auth'; +import register from '../Contexts/AuthContextProvider'; import { Formik, Field, Form } from 'formik'; -import { connect } from 'react-redux'; class Register extends React.Component { constructor(props) { @@ -115,11 +114,4 @@ class Register extends React.Component { } } -function mapStateToProps(state) { - const { isLoggedIn } = state.auth; - return { - isLoggedIn - }; -} - -export default connect(mapStateToProps)(Register); +export default Register; diff --git a/web/src/Pages/Settings.js b/web/src/Pages/Settings.js index e517b361..1d0ca5e3 100644 --- a/web/src/Pages/Settings.js +++ b/web/src/Pages/Settings.js @@ -2,15 +2,6 @@ import React from 'react'; import '../App.css'; import './Settings.css'; -import { useToasts } from 'react-toast-notifications'; - -function withToast(Component) { - return function WrappedComponent(props) { - const toastFuncs = useToasts() - return ; - } -} - class Settings extends React.Component { constructor(props) { super(props); @@ -33,4 +24,4 @@ class Settings extends React.Component { } } -export default withToast(Settings); +export default Settings; diff --git a/web/src/Reducers/auth.js b/web/src/Reducers/auth.js deleted file mode 100644 index df75c1e6..00000000 --- a/web/src/Reducers/auth.js +++ /dev/null @@ -1,53 +0,0 @@ -import { - REGISTER_SUCCESS, - REGISTER_FAIL, - LOGIN_SUCCESS, - LOGIN_FAIL, - LOGOUT, - } from "../Actions/types"; - - const user = JSON.parse(localStorage.getItem('user')); - - const initialState = user - ? { isLoggedIn: true, user: user } - : { isLoggedIn: false, user: null }; - - export default function authReducer(state = initialState, action) { - const { type, payload } = action; - - switch (type) { - case REGISTER_SUCCESS: - return { - ...state, - isLoggedIn: false, - }; - case REGISTER_FAIL: - return { - ...state, - isLoggedIn: false, - }; - case LOGIN_SUCCESS: - return { - ...state, - isLoggedIn: true, - user: { - jwt: payload.jwt, - uuid: payload.sub, - exp: payload.exp, - } - }; - case LOGIN_FAIL: - return { - ...state, - isLoggedIn: false, - }; - case LOGOUT: - return { - ...state, - isLoggedIn: false, - user: null, - }; - default: - return state; - } - } diff --git a/web/src/Reducers/index.js b/web/src/Reducers/index.js deleted file mode 100644 index 3df08848..00000000 --- a/web/src/Reducers/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { combineReducers } from "redux"; -import auth from "./auth"; - -export default combineReducers({ - auth, -}); diff --git a/web/src/Services/Actions.js b/web/src/Services/Actions.js deleted file mode 100644 index e69de29b..00000000 diff --git a/web/src/Services/api.service.js b/web/src/Services/api.service.js deleted file mode 100644 index 0a202c5a..00000000 --- a/web/src/Services/api.service.js +++ /dev/null @@ -1,14 +0,0 @@ -import axios from "axios"; -import authHeader from '../Services/auth-header'; - -class ApiService { - async getStats() { - return axios.get(process.env.REACT_APP_API_URL + "stats"); - } - - async getRecentScrobbles(id) { - return axios.get(process.env.REACT_APP_API_URL + "user/" + id + "/scrobbles", { headers: authHeader() }); - } -} - -export default new ApiService(); \ No newline at end of file diff --git a/web/src/Services/auth-header.js b/web/src/Services/auth-header.js deleted file mode 100644 index 75454e14..00000000 --- a/web/src/Services/auth-header.js +++ /dev/null @@ -1,9 +0,0 @@ -export default function authHeader() { - const user = JSON.parse(localStorage.getItem('user')); - - if (user && user.jwt) { - return { Authorization: 'Bearer ' + user.jwt }; - } else { - return {}; - } -} diff --git a/web/src/Services/auth.service.js b/web/src/Services/auth.service.js deleted file mode 100644 index 81ce31a6..00000000 --- a/web/src/Services/auth.service.js +++ /dev/null @@ -1,41 +0,0 @@ -import axios from "axios"; -import jwt from 'jwt-decode' // import dependency - -class AuthService { - async login(username, password) { - return axios - .post(process.env.REACT_APP_API_URL + "login", { username, password }) - .then((response) => { - if (response.data.token) { - let expandedUser = jwt(response.data.token) - let user = { - jwt: response.data.token, - uuid: expandedUser.sub, - exp: expandedUser.exp, - } - localStorage.setItem('user', JSON.stringify(user)) - } - - return response.data; - }); - } - - async logout() { - localStorage.removeItem("user"); - } - - async register(username, email, password) { - return axios - .post(process.env.REACT_APP_API_URL + "register", { - username, - email, - password, - }) - .then((response) => { - console.log(response) - return response.data; - }); - } -} - -export default new AuthService(); diff --git a/web/src/Services/user.service.js b/web/src/Services/user.service.js deleted file mode 100644 index 77b5391a..00000000 --- a/web/src/Services/user.service.js +++ /dev/null @@ -1,18 +0,0 @@ -import axios from 'axios'; -import authHeader from './auth-header'; - -class UserService { - getPublicContent() { - return axios.get(process.env.REACT_APP_API_URL + 'all'); - } - - getUserBoard() { - return axios.get(process.env.REACT_APP_API_URL + 'user', { headers: authHeader() }); - } - - getAdminBoard() { - return axios.get(process.env.REACT_APP_API_URL + 'admin', { headers: authHeader() }); - } -} - -export default new UserService(); diff --git a/web/src/index.js b/web/src/index.js index 03553c32..15dbe6a0 100644 --- a/web/src/index.js +++ b/web/src/index.js @@ -3,13 +3,14 @@ import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import { HashRouter } from 'react-router-dom'; + import { ToastContainer } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.min.css' -import { Provider } from 'react-redux'; -import store from "./store"; +import 'react-toastify/dist/ReactToastify.min.css'; + +import AuthContextProvider from './Contexts/AuthContextProvider'; ReactDOM.render( - + - , + , document.getElementById('root') ); diff --git a/web/src/store.js b/web/src/store.js deleted file mode 100644 index 03eff2c9..00000000 --- a/web/src/store.js +++ /dev/null @@ -1,13 +0,0 @@ -import { createStore, applyMiddleware } from "redux"; -import { composeWithDevTools } from "redux-devtools-extension"; -import thunk from "redux-thunk"; -import rootReducer from "./Reducers"; - -const middleware = [thunk]; - -const store = createStore( - rootReducer, - composeWithDevTools(applyMiddleware(...middleware)) -); - -export default store;