- Switch redux -> Context
- Remove excess packages
This commit is contained in:
Daniel Mason 2021-03-31 19:14:22 +13:00
parent ebd88b3bb0
commit 65c092e4ee
Signed by: idanoo
GPG Key ID: 387387CDBC02F132
14 changed files with 293 additions and 397 deletions

View File

@ -8,6 +8,7 @@ variables:
build-go: build-go:
image: golang:1.16.2 image: golang:1.16.2
stage: build stage: build
only: master
script: script:
- go build -o goscrobble cmd/go-scrobble/*.go - go build -o goscrobble cmd/go-scrobble/*.go
artifacts: artifacts:
@ -21,6 +22,7 @@ build-go:
build-react: build-react:
image: node:15.12.0 image: node:15.12.0
stage: build stage: build
only: master
script: script:
- cd web - cd web
- npm install - npm install
@ -33,6 +35,7 @@ build-react:
bundle: bundle:
image: bash:latest image: bash:latest
stage: bundle stage: bundle
only: master
variables: variables:
GIT_STRATEGY: none GIT_STRATEGY: none
before_script: before_script:

View File

@ -1,5 +1,7 @@
# 0.0.7 # 0.0.7
-Switch redux -> context. - Switch redux -> Context
- Remove excess packages
# 0.0.6 # 0.0.6
- Fix hitting dashboard when logged out - Fix hitting dashboard when logged out

View File

@ -61,10 +61,8 @@ func createUser(req *RegisterRequest, ip net.IP) error {
// Check username is valid // Check username is valid
if !isUsernameValid(req.Username) { if !isUsernameValid(req.Username) {
log.Println("user is invalid")
return errors.New("Username contains invalid characters") return errors.New("Username contains invalid characters")
} }
log.Println("user is valid")
// If set an email.. validate it! // If set an email.. validate it!
if req.Email != "" { if req.Email != "" {

View File

@ -24,30 +24,26 @@ export const PostLogin = (formValues) => {
jwt: response.data.token, jwt: response.data.token,
uuid: expandedUser.sub, uuid: expandedUser.sub,
exp: expandedUser.exp, exp: expandedUser.exp,
username: expandedUser.username,
} }
// Set in local storage
localStorage.setItem('user', JSON.stringify(user));
// Set in context
// setUser(user)
toast.success('Successfully logged in.'); toast.success('Successfully logged in.');
// setLoading(false)
return user; return user;
} else { } else {
toast.error(response.data.error ? response.data.error: 'An Unknown Error has occurred'); toast.error(response.data.error ? response.data.error: 'An Unknown Error has occurred');
// setLoading(false)
return null return null
} }
}) })
.catch(() => {
return Promise.resolve();
});
}; };
export const PostRegister = (formValues) => { export const PostRegister = (formValues) => {
axios.post(process.env.REACT_APP_API_URL + "register", formValues) return axios.post(process.env.REACT_APP_API_URL + "register", formValues)
.then((response) => { .then((response) => {
if (response.data.token) { if (response.data.message) {
toast.success('Successfully registered. Please sign in'); toast.success(response.data.message);
return Promise.resolve(); return Promise.resolve();
} else { } else {
@ -56,16 +52,8 @@ export const PostRegister = (formValues) => {
return Promise.reject(); return Promise.reject();
} }
}) })
.error((error) => { .catch(() => {
const message = return Promise.resolve();
(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();
}); });
}; };

View File

@ -1,10 +1,10 @@
import { React, Component } from 'react'; import { React, useState, useContext } from 'react';
import { Navbar, NavbarBrand, Collapse, Nav, NavbarToggler, NavItem } from 'reactstrap'; import { Navbar, NavbarBrand, Collapse, Nav, NavbarToggler, NavItem } from 'reactstrap';
import { Link } from 'react-router-dom'; import { Link, useLocation } from 'react-router-dom';
import logo from '../logo.png'; import logo from '../logo.png';
import './Navigation.css'; import './Navigation.css';
import logout from '../Contexts/AuthContextProvider'; import AuthContext from '../Contexts/AuthContext';
const menuItems = [ const menuItems = [
'Home', 'Home',
@ -20,68 +20,42 @@ const isMobile = () => {
return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
}; };
class Navigation extends Component { const Navigation = () => {
constructor(props) { const location = useLocation();
super(props);
this.toggleNavbar = this.toggleNavbar.bind(this);
this.handleLogout = this.handleLogout.bind(this);
// Yeah I know you might not hit home.. but I can't get the // Lovely hack to highlight the current page (:
// path based finder thing working on initial load :sweatsmile: let active = "Home"
this.state = { active: "Home", collapsed: true }; if (location && location.pathname && location.pathname.length > 1) {
active = location.pathname.replace(/\//, "");
} }
componentDidMount() { let activeStyle = { color: '#FFFFFF' };
const { isLoggedIn } = this.props; let { user, Logout } = useContext(AuthContext);
if (isLoggedIn) { let [collapsed, setCollapsed] = useState(true);
this.setState({
isLoggedIn: true,
});
}
}
_handleClick(menuItem) {
this.setState({ active: menuItem, collapsed: !this.state.collapsed });
}
handleLogout() {
this.dispatch(logout());
}
toggleNavbar() {
this.setState({ collapsed: !this.state.collapsed });
}
// This is a real mess. TO CLEAN UP.
render() {
const activeStyle = { color: '#FFFFFF' };
const renderMobileNav = () => { const renderMobileNav = () => {
return <Navbar color="dark" dark fixed="top"> return <Navbar color="dark" dark fixed="top">
<NavbarBrand className="mr-auto"><img src={logo} className="nav-logo" alt="logo" /> GoScrobble</NavbarBrand> <NavbarBrand className="mr-auto"><img src={logo} className="nav-logo" alt="logo" /> GoScrobble</NavbarBrand>
<NavbarToggler onClick={this.toggleNavbar} className="mr-2" /> <NavbarToggler onClick={setCollapsed(!collapsed)} className="mr-2" />
<Collapse isOpen={!this.state.collapsed} navbar> <Collapse isOpen={!collapsed} navbar>
{this.state.isLoggedIn ? {user ?
<Nav className="navLinkLoginMobile" navbar> <Nav className="navLinkLoginMobile" navbar>
{loggedInMenuItems.map(menuItem => {loggedInMenuItems.map(menuItem =>
<NavItem> <NavItem>
<Link <Link
key={menuItem} key={menuItem}
className="navLinkMobile" className="navLinkMobile"
style={this.state.active === menuItem ? activeStyle : {}} style={active === menuItem ? activeStyle : {}}
onClick={this._handleClick.bind(this, menuItem)}
to={menuItem} to={menuItem}
>{menuItem}</Link> >{menuItem}</Link>
</NavItem> </NavItem>
)} )}
<Link <Link
to="/profile" to="/profile"
style={this.state.active === "profile" ? activeStyle : {}} style={active === "profile" ? activeStyle : {}}
onClick={this._handleClick.bind(this, "profile")}
className="navLinkMobile" className="navLinkMobile"
>Profile</Link> >Profile</Link>
<Link to="/" className="navLink" onClick={this.handleLogout}>Logout</Link> <Link to="/" className="navLink" onClick={Logout}>Logout</Link>
</Nav> </Nav>
: <Nav className="navLinkLoginMobile" navbar> : <Nav className="navLinkLoginMobile" navbar>
{menuItems.map(menuItem => {menuItems.map(menuItem =>
@ -89,8 +63,7 @@ class Navigation extends Component {
<Link <Link
key={menuItem} key={menuItem}
className="navLinkMobile" className="navLinkMobile"
style={this.state.active === menuItem ? activeStyle : {}} style={active === menuItem ? activeStyle : {}}
onClick={this._handleClick.bind(this, menuItem)}
to={menuItem === "Home" ? "/" : menuItem} to={menuItem === "Home" ? "/" : menuItem}
> >
{menuItem} {menuItem}
@ -99,19 +72,16 @@ class Navigation extends Component {
)} )}
<NavItem> <NavItem>
<Link <Link
to="/login" to="/Login"
style={this.state.active === "login" ? activeStyle : {}} style={active === "Login" ? activeStyle : {}}
onClick={this._handleClick.bind(this, "login")}
className="navLinkMobile" className="navLinkMobile"
>Login</Link> >Login</Link>
</NavItem> </NavItem>
<NavItem> <NavItem>
<Link <Link
to="/register" to="/Register"
className="navLinkMobile" className="navLinkMobile"
style={this.state.active === "register" ? activeStyle : {}} style={active === "Register" ? activeStyle : {}}
onClick={this._handleClick.bind(this, "register")}
history={this.props.history}
>Register</Link> >Register</Link>
</NavItem> </NavItem>
</Nav> </Nav>
@ -123,14 +93,13 @@ class Navigation extends Component {
const renderDesktopNav = () => { const renderDesktopNav = () => {
return <Navbar color="dark" dark fixed="top"> return <Navbar color="dark" dark fixed="top">
<NavbarBrand className="mr-auto"><img src={logo} className="nav-logo" alt="logo" /> GoScrobble</NavbarBrand> <NavbarBrand className="mr-auto"><img src={logo} className="nav-logo" alt="logo" /> GoScrobble</NavbarBrand>
{this.state.isLoggedIn ? {user ?
<div> <div>
{loggedInMenuItems.map(menuItem => {loggedInMenuItems.map(menuItem =>
<Link <Link
key={menuItem} key={menuItem}
className="navLink" className="navLink"
style={this.state.active === menuItem ? activeStyle : {}} style={active === menuItem ? activeStyle : {}}
onClick={this._handleClick.bind(this, menuItem)}
to={menuItem} to={menuItem}
> >
{menuItem} {menuItem}
@ -142,8 +111,7 @@ class Navigation extends Component {
<Link <Link
key={menuItem} key={menuItem}
className="navLink" className="navLink"
style={this.state.active === menuItem ? activeStyle : {}} style={active === menuItem ? activeStyle : {}}
onClick={this._handleClick.bind(this, menuItem)}
to={menuItem === "Home" ? "/" : menuItem} to={menuItem === "Home" ? "/" : menuItem}
> >
{menuItem} {menuItem}
@ -151,30 +119,26 @@ class Navigation extends Component {
)} )}
</div> </div>
} }
{this.state.isLoggedIn ? {user ?
<div className="navLinkLogin"> <div className="navLinkLogin">
<Link <Link
to="/profile" to="/profile"
style={this.state.active === "profile" ? activeStyle : {}} style={active === "profile" ? activeStyle : {}}
onClick={this._handleClick.bind(this, "profile")}
className="navLink" className="navLink"
>Profile</Link> >{user.username}</Link>
<Link to="/" className="navLink" onClick={this.handleLogout}>Logout</Link> <Link to="/" className="navLink" onClick={Logout}>Logout</Link>
</div> </div>
: :
<div className="navLinkLogin"> <div className="navLinkLogin">
<Link <Link
to="/login" to="/login"
style={this.state.active === "login" ? activeStyle : {}} style={active === "login" ? activeStyle : {}}
onClick={this._handleClick.bind(this, "login")}
className="navLink" className="navLink"
>Login</Link> >Login</Link>
<Link <Link
to="/register" to="/register"
className="navLink" className="navLink"
style={this.state.active === "register" ? activeStyle : {}} style={active === "register" ? activeStyle : {}}
onClick={this._handleClick.bind(this, "register")}
history={this.props.history}
>Register</Link> >Register</Link>
</div> </div>
@ -192,6 +156,5 @@ class Navigation extends Component {
</div> </div>
); );
} }
}
export default Navigation; export default Navigation;

View File

@ -1,15 +1,6 @@
import React from "react"; import React from "react";
class ScrobbleTable extends React.Component { const ScrobbleTable = (props) => {
constructor(props) {
super(props);
this.state = {
data: this.props.data,
};
}
render() {
return ( return (
<div> <div>
<table border={1} cellPadding={5}> <table border={1} cellPadding={5}>
@ -23,8 +14,8 @@ class ScrobbleTable extends React.Component {
</thead> </thead>
<tbody> <tbody>
{ {
this.state.data && this.state.data.items && props.data && props.data.items &&
this.state.data.items.map(function (element) { props.data.items.map(function (element) {
return <tr> return <tr>
<td>{element.time}</td> <td>{element.time}</td>
<td>{element.track}</td> <td>{element.track}</td>
@ -38,6 +29,5 @@ class ScrobbleTable extends React.Component {
</div> </div>
); );
} }
}
export default ScrobbleTable; export default ScrobbleTable;

View File

@ -1,7 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import AuthContext from './AuthContext'; import AuthContext from './AuthContext';
import { PostLogin, PostRegister } from '../Api/index'; import { PostLogin, PostRegister } from '../Api/index';
const AuthContextProvider = ({ children }) => { const AuthContextProvider = ({ children }) => {
@ -22,21 +21,16 @@ const AuthContextProvider = ({ children }) => {
PostLogin(formValues).then(user => { PostLogin(formValues).then(user => {
if (user) { if (user) {
setUser(user); setUser(user);
const { history } = this.props; localStorage.setItem('user', JSON.stringify(user));
history.push("/dashboard");
} }
setLoading(false); setLoading(false);
}) })
} }
const Register = (formValues) => { const Register = (formValues) => {
const { history } = this.props;
setLoading(true); setLoading(true);
return PostRegister(formValues).then(response => { return PostRegister(formValues).then(response => {
if (response) { // Do stuff here?
history.push("/login");
}
setLoading(false); setLoading(false);
}); });
}; };

View File

@ -12,7 +12,7 @@ const About = () => {
Used to track your listening history and build a profile to discover new music. Used to track your listening history and build a profile to discover new music.
</p> </p>
<a <a
className="aboutBodyw" className="aboutBody"
href="https://gitlab.com/idanoo/go-scrobble" href="https://gitlab.com/idanoo/go-scrobble"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"

View File

@ -1,56 +1,44 @@
import React from 'react'; import React, { useState, useEffect, useContext } from 'react';
import '../App.css'; import '../App.css';
import './Dashboard.css'; import './Dashboard.css';
import { useHistory } from "react-router";
import { getRecentScrobbles } from '../Api/index'; import { getRecentScrobbles } from '../Api/index';
import ScaleLoader from 'react-spinners/ScaleLoader'; import ScaleLoader from 'react-spinners/ScaleLoader';
import ScrobbleTable from "../Components/ScrobbleTable"; import ScrobbleTable from "../Components/ScrobbleTable";
import AuthContext from '../Contexts/AuthContext';
class Dashboard extends React.Component { const Dashboard = () => {
constructor(props) { const history = useHistory();
super(props); let { user } = useContext(AuthContext);
this.state = { let [isLoading, setIsLoading] = useState(true);
isLoading: true, let [dashboardData, setDashboardData] = useState({});
scrobbleData: [],
uuid: null, if (!user) {
}; history.push("/login");
} }
componentDidMount() { useEffect(() => {
const { history, uuid } = this.props; if (!user) {
const isLoggedIn = this.props.isLoggedIn; return
if (!isLoggedIn) {
history.push("/login")
} }
getRecentScrobbles(user.uuid)
getRecentScrobbles(uuid) .then(data => {
.then((data) => { setDashboardData(data);
this.setState({ setIsLoading(false);
isLoading: false,
data: data
});
}) })
.catch(() => { }, [user])
this.setState({
isLoading: false
});
});
}
render() {
return ( return (
<div className="pageWrapper"> <div className="pageWrapper">
<h1> <h1>
Dashboard! Dashboard!
</h1> </h1>
{this.state.isLoading {isLoading
? <ScaleLoader color="#FFF" size={60} /> ? <ScaleLoader color="#FFF" size={60} />
: <ScrobbleTable data={this.state.data} /> : <ScrobbleTable data={dashboardData} />
} }
</div> </div>
); );
} }
}
export default Dashboard; export default Dashboard;

View File

@ -4,8 +4,7 @@ import './Home.css';
import HomeBanner from '../Components/HomeBanner'; import HomeBanner from '../Components/HomeBanner';
import React from 'react'; import React from 'react';
class Home extends React.Component { const Home = () => {
render() {
return ( return (
<div className="pageWrapper"> <div className="pageWrapper">
<img src={logo} className="App-logo" alt="logo" /> <img src={logo} className="App-logo" alt="logo" />
@ -14,6 +13,5 @@ class Home extends React.Component {
</div> </div>
); );
} }
}
export default Home; export default Home;

View File

@ -5,10 +5,16 @@ import { Button } from 'reactstrap';
import { Formik, Form, Field } from 'formik'; import { Formik, Form, Field } from 'formik';
import ScaleLoader from 'react-spinners/ScaleLoader'; import ScaleLoader from 'react-spinners/ScaleLoader';
import AuthContext from '../Contexts/AuthContext'; import AuthContext from '../Contexts/AuthContext';
import { useHistory } from "react-router";
const Login = () => { const Login = () => {
const history = useHistory();
let boolTrue = true; let boolTrue = true;
let { Login, loading } = useContext(AuthContext); let { Login, loading, user } = useContext(AuthContext);
if (user) {
history.push("/dashboard");
}
return ( return (
<div className="pageWrapper"> <div className="pageWrapper">

View File

@ -1,25 +1,25 @@
import React from 'react'; import React, { useContext } from 'react';
import '../App.css'; import '../App.css';
import './Dashboard.css'; import './Dashboard.css';
import { useHistory } from "react-router";
import AuthContext from '../Contexts/AuthContext';
class Profile extends React.Component { const Profile = () => {
componentDidMount() { const history = useHistory();
const { history, isLoggedIn } = this.props; const { user } = useContext(AuthContext);
if (!isLoggedIn) { if (!user) {
history.push("/login") history.push("/login");
}
} }
render() {
return ( return (
<div className="pageWrapper"> <div className="pageWrapper">
<h1> <h1>
Hai User Welcome {user.username}!
</h1> </h1>
</div> </div>
); );
}
} }
export default Profile; export default Profile;

View File

@ -1,51 +1,25 @@
import React from 'react'; import React, { useContext } from 'react';
import '../App.css'; import '../App.css';
import './Register.css'; import './Register.css';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import ScaleLoader from "react-spinners/ScaleLoader"; import ScaleLoader from "react-spinners/ScaleLoader";
import register from '../Contexts/AuthContextProvider'; import AuthContext from '../Contexts/AuthContext';
import { Formik, Field, Form } from 'formik'; import { Formik, Field, Form } from 'formik';
import { useHistory } from "react-router";
class Register extends React.Component { const Register = () => {
constructor(props) { const history = useHistory();
super(props); let boolTrue = true;
this.state = {username: '', email: '', password: '', passwordconfirm: '', loading: false}; let { Register, user, loading } = useContext(AuthContext);
if (user) {
history.push("/dashboard");
} }
componentDidMount() {
const { history, isLoggedIn } = this.props;
if (isLoggedIn) {
history.push("/dashboard")
}
}
handleRegister(values) {
console.log(values)
this.setState({loading: true});
const { dispatch, history } = this.props;
dispatch(register(values.username, values.email, values.password))
.then(() => {
this.setState({
loading: false,
});
history.push("/login");
})
.catch(() => {
this.setState({
loading: false
});
});
}
render() {
let trueBool = true;
return ( return (
<div className="pageWrapper"> <div className="pageWrapper">
{ {
// TODO: Move to DB:config REGISTRATION_DISABLED=1|0 // TODO: Move to DB:config REGISTRATION_DISABLED=1|0 :upsidedownsmile:
process.env.REACT_APP_REGISTRATION_DISABLED === "true" ? process.env.REACT_APP_REGISTRATION_DISABLED === "true" ?
<p>Registration is temporarily disabled. Please try again soon!</p> <p>Registration is temporarily disabled. Please try again soon!</p>
: :
@ -56,7 +30,7 @@ class Register extends React.Component {
<div className="registerBody"> <div className="registerBody">
<Formik <Formik
initialValues={{ username: '', email: '', password: '', passwordconfirm: '' }} initialValues={{ username: '', email: '', password: '', passwordconfirm: '' }}
onSubmit={async values => this.handleRegister(values)} onSubmit={async values => Register(values)}
> >
<Form> <Form>
<label> <label>
@ -64,7 +38,7 @@ class Register extends React.Component {
<Field <Field
name="username" name="username"
type="text" type="text"
required={trueBool} required={boolTrue}
className="registerFields" className="registerFields"
/> />
</label> </label>
@ -83,7 +57,7 @@ class Register extends React.Component {
<Field <Field
name="password" name="password"
type="password" type="password"
required={trueBool} required={boolTrue}
className="registerFields" className="registerFields"
/> />
</label> </label>
@ -93,7 +67,7 @@ class Register extends React.Component {
<Field <Field
name="passwordconfirm" name="passwordconfirm"
type="password" type="password"
required={trueBool} required={boolTrue}
className="registerFields" className="registerFields"
/> />
</label> </label>
@ -102,8 +76,8 @@ class Register extends React.Component {
color="primary" color="primary"
type="submit" type="submit"
className="registerButton" className="registerButton"
disabled={this.state.loading} disabled={loading}
>{this.state.loading ? <ScaleLoader color="#FFF" size={35} /> : "Register"}</Button> >{loading ? <ScaleLoader color="#FFF" size={35} /> : "Register"}</Button>
</Form> </Form>
</Formik> </Formik>
</div> </div>
@ -112,6 +86,5 @@ class Register extends React.Component {
</div> </div>
); );
} }
}
export default Register; export default Register;

View File

@ -2,13 +2,7 @@ import React from 'react';
import '../App.css'; import '../App.css';
import './Settings.css'; import './Settings.css';
class Settings extends React.Component { const Settings = () => {
constructor(props) {
super(props);
this.state = {username: '', password: '', loading: false};
}
render() {
return ( return (
<div className="pageWrapper"> <div className="pageWrapper">
<h1> <h1>
@ -22,6 +16,5 @@ class Settings extends React.Component {
</div> </div>
); );
} }
}
export default Settings; export default Settings;