Fixed broken API endpoints
This commit is contained in:
parent
175e6fe902
commit
d000283453
26 changed files with 28831 additions and 24585 deletions
52365
client/package-lock.json
generated
52365
client/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -20,7 +20,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "cp ${ENV:-'../.env'} .env && react-scripts build",
|
||||
"build": "cp ${ENV:-'../.env'} .env && rm -rf build && react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||
|
||||
import Navbar from './components/Navbar';
|
||||
|
|
@ -17,14 +17,22 @@ import OrgDashboard from './components/orgs/OrgDashboard';
|
|||
import UpdateOrganization from './components/forms/UpdateOrganization';
|
||||
|
||||
function App() {
|
||||
const [token, setToken] = useState(false);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route path='' element={<Navbar />}>
|
||||
<Route
|
||||
path=''
|
||||
element={<Navbar tokenState={{ token, setToken }} />}
|
||||
>
|
||||
<Route index element={<MainPage />} />
|
||||
|
||||
<Route path='login' element={<Login />} />
|
||||
<Route
|
||||
path='login'
|
||||
element={<Login setToken={setToken} />}
|
||||
/>
|
||||
<Route path='register' element={<Register />} />
|
||||
<Route path='update' element={<EditUser />} />
|
||||
<Route path='recover' element={<Form />}>
|
||||
|
|
@ -32,10 +40,10 @@ function App() {
|
|||
<Route path=':id' element={<Reset />} />
|
||||
</Route>
|
||||
|
||||
<Route path='org' element={<OwnedOrgs />} />
|
||||
<Route path='joined'>
|
||||
<Route index element={<MemberOrgs />} />
|
||||
<Route path=':id'>
|
||||
<Route path='org'>
|
||||
<Route index element={<OwnedOrgs />} />
|
||||
<Route path='joined' element={<MemberOrgs />} />
|
||||
<Route path=':orgID'>
|
||||
<Route index element={<OrgDashboard />} />
|
||||
<Route
|
||||
path='update'
|
||||
|
|
|
|||
|
|
@ -35,55 +35,11 @@ function MainPage() {
|
|||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
async function getOwnedOrgs() {
|
||||
await axios
|
||||
.get(
|
||||
`${
|
||||
process.env.REACT_APP_DOMAIN_ROOT
|
||||
}/auth?token=${Cookies.get('token')}`
|
||||
)
|
||||
.then((response) => {
|
||||
setOwnedOrgs(() =>
|
||||
response.data.map((org) => {
|
||||
return {
|
||||
orgID: org.orgID,
|
||||
orgName: org.orgName,
|
||||
memberCount: org.memberCount,
|
||||
createdAt: org.createdAt,
|
||||
};
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
getOwnedOrgs();
|
||||
}, []);
|
||||
useEffect(() => {}, []);
|
||||
|
||||
useEffect(() => {
|
||||
async function getOrgs() {
|
||||
await axios
|
||||
.get(
|
||||
`${
|
||||
process.env.REACT_APP_DOMAIN_ROOT
|
||||
}/auth/orgs?token=${Cookies.get('token')}`
|
||||
)
|
||||
.then((response) => {
|
||||
setOrgs(() =>
|
||||
response.data.map((org) => {
|
||||
return {
|
||||
orgID: org.orgID,
|
||||
orgName: org.orgName,
|
||||
memberCount: org.memberCount,
|
||||
createdAt: org.createdAt,
|
||||
};
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
getOrgs();
|
||||
getMemberOrgs();
|
||||
getOwnedOrgs();
|
||||
}, []);
|
||||
|
||||
function handleChange(e) {
|
||||
|
|
@ -95,24 +51,76 @@ function MainPage() {
|
|||
});
|
||||
}
|
||||
|
||||
async function joinOrg(e) {
|
||||
e.preventDefault();
|
||||
async function getOwnedOrgs() {
|
||||
await axios
|
||||
.get(
|
||||
`${process.env.REACT_APP_DOMAIN_ROOT}/auth?token=${Cookies.get(
|
||||
'token'
|
||||
)}`
|
||||
)
|
||||
.then((response) => {
|
||||
setOwnedOrgs(() =>
|
||||
response.data.map((org) => {
|
||||
return {
|
||||
orgID: org.orgID,
|
||||
orgName: org.orgName,
|
||||
memberCount: org.memberCount,
|
||||
createdAt: org.createdAt,
|
||||
};
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
|
||||
await axios.post(`${process.env.REACT_APP_DOMAIN_ROOT}/org/create`, {
|
||||
token: Cookies.get('token'),
|
||||
orgName: form.name,
|
||||
});
|
||||
async function getMemberOrgs() {
|
||||
await axios
|
||||
.get(
|
||||
`${
|
||||
process.env.REACT_APP_DOMAIN_ROOT
|
||||
}/auth/orgs?token=${Cookies.get('token')}`
|
||||
)
|
||||
.then((response) => {
|
||||
setOrgs(() =>
|
||||
response.data.map((org) => {
|
||||
return {
|
||||
orgID: org.orgID,
|
||||
orgName: org.orgName,
|
||||
memberCount: org.memberCount,
|
||||
createdAt: org.createdAt,
|
||||
};
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function createOrg(e) {
|
||||
e.preventDefault();
|
||||
console.log('create');
|
||||
|
||||
await axios.post(
|
||||
`${process.env.REACT_APP_DOMAIN_ROOT}/org/${form.id}`,
|
||||
{
|
||||
await axios
|
||||
.post(`${process.env.REACT_APP_DOMAIN_ROOT}/org/create`, {
|
||||
token: Cookies.get('token'),
|
||||
}
|
||||
);
|
||||
orgName: form.name,
|
||||
})
|
||||
.then(() => {
|
||||
navigate('');
|
||||
getOwnedOrgs();
|
||||
});
|
||||
}
|
||||
|
||||
async function joinOrg(e) {
|
||||
e.preventDefault();
|
||||
|
||||
await axios
|
||||
.post(`${process.env.REACT_APP_DOMAIN_ROOT}/org/${form.id}/add`, {
|
||||
token: Cookies.get('token'),
|
||||
})
|
||||
.then(() => {
|
||||
getMemberOrgs();
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -131,7 +139,6 @@ function MainPage() {
|
|||
<form onSubmit={joinOrg}>
|
||||
<FormGroup row>
|
||||
<TextField
|
||||
id='standard-name'
|
||||
label='Organization ID'
|
||||
name='id'
|
||||
value={form.id}
|
||||
|
|
@ -154,10 +161,9 @@ function MainPage() {
|
|||
<form onSubmit={createOrg}>
|
||||
<FormGroup row>
|
||||
<TextField
|
||||
id='standard-name'
|
||||
label='Organization Name'
|
||||
name='orgName'
|
||||
value={form.orgName}
|
||||
name='name'
|
||||
value={form.name}
|
||||
onChange={handleChange}
|
||||
sx={{ width: '70%' }}
|
||||
/>
|
||||
|
|
@ -191,7 +197,7 @@ function MainPage() {
|
|||
</StackItem>
|
||||
<StackItem>
|
||||
<Typography variant='h6'>
|
||||
<Link to='joined' style={linkStyle}>
|
||||
<Link to='org/joined' style={linkStyle}>
|
||||
Joined Organizations
|
||||
</Link>
|
||||
</Typography>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Link, Outlet } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
import { Link, Outlet, useNavigate } from 'react-router-dom';
|
||||
|
||||
import axios from 'axios';
|
||||
import Cookies from 'js-cookie';
|
||||
|
|
@ -15,8 +15,10 @@ import {
|
|||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
|
||||
function Navbar() {
|
||||
const [token, setToken] = useState('');
|
||||
function Navbar({ tokenState }) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { token, setToken } = tokenState;
|
||||
|
||||
const linkStyle = { textDecoration: 'none', color: 'inherit' };
|
||||
const darkTheme = createTheme({
|
||||
|
|
@ -25,17 +27,48 @@ function Navbar() {
|
|||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setToken(() => Cookies.get('token'));
|
||||
}, []);
|
||||
function ButtonGroup({ token }) {
|
||||
if (token) {
|
||||
return (
|
||||
<Button onClick={handleLogout} color='inherit'>
|
||||
<Link to='/login' style={linkStyle}>
|
||||
Logout
|
||||
</Link>
|
||||
</Button>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button color='inherit'>
|
||||
<Link to='/login' style={linkStyle}>
|
||||
Login
|
||||
</Link>
|
||||
</Button>
|
||||
<Button color='inherit'>
|
||||
<Link to='/register' style={linkStyle}>
|
||||
Register
|
||||
</Link>
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleLogout() {
|
||||
await axios.post(`${process.env.REACT_APP_DOMAIN_ROOT}/auth/logout`, {
|
||||
token: Cookies.get('token'),
|
||||
});
|
||||
await axios
|
||||
.post(`${process.env.REACT_APP_DOMAIN_ROOT}/auth/logout`, {
|
||||
token: Cookies.get('token'),
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
|
||||
Cookies.remove('token');
|
||||
Cookies.remove('userID');
|
||||
setToken(() => '');
|
||||
|
||||
setToken(() => false);
|
||||
|
||||
navigate('login');
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -63,27 +96,7 @@ function Navbar() {
|
|||
KnowItAll
|
||||
</Typography>
|
||||
|
||||
{token && (
|
||||
<Button onClick={handleLogout} color='inherit'>
|
||||
<Link to='/login' style={linkStyle}>
|
||||
Logout
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
{!token && (
|
||||
<React.Fragment>
|
||||
<Button color='inherit'>
|
||||
<Link to='/login' style={linkStyle}>
|
||||
Login
|
||||
</Link>
|
||||
</Button>
|
||||
<Button color='inherit'>
|
||||
<Link to='/register' style={linkStyle}>
|
||||
Register
|
||||
</Link>
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
<ButtonGroup token={token} />
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Outlet />
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ function EditUser() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='First Name'
|
||||
name='firstName'
|
||||
variant='outlined'
|
||||
|
|
@ -89,7 +88,6 @@ function EditUser() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Last Name'
|
||||
name='lastName'
|
||||
variant='outlined'
|
||||
|
|
@ -100,7 +98,6 @@ function EditUser() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Email'
|
||||
name='email'
|
||||
variant='outlined'
|
||||
|
|
@ -110,7 +107,6 @@ function EditUser() {
|
|||
/>
|
||||
<TextField
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Pronouns'
|
||||
name='pronouns'
|
||||
variant='outlined'
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
|
||||
import Form from '../utils/Form';
|
||||
|
||||
function Login() {
|
||||
function Login({ setToken }) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [form, setForm] = useState({
|
||||
|
|
@ -26,19 +26,22 @@ function Login() {
|
|||
const [error, setError] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (Cookies.get('token')) {
|
||||
async function logout() {
|
||||
await axios
|
||||
.post(`${process.env.REACT_APP_DOMAIN_ROOT}/auth/logout`, {
|
||||
token: Cookies.get('token'),
|
||||
})
|
||||
.catch((e) => console.log(e));
|
||||
}
|
||||
logout();
|
||||
async function logout() {
|
||||
await axios
|
||||
.post(`${process.env.REACT_APP_DOMAIN_ROOT}/auth/logout`, {
|
||||
token: Cookies.get('token'),
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
|
||||
Cookies.remove('token');
|
||||
Cookies.remove('userID');
|
||||
|
||||
setToken(() => false);
|
||||
}
|
||||
}, []);
|
||||
logout();
|
||||
}, [setToken]);
|
||||
|
||||
function handleChange(e) {
|
||||
const name = e.target.name;
|
||||
|
|
@ -69,6 +72,7 @@ function Login() {
|
|||
Cookies.set('userID', response.data.userID, {
|
||||
expires: form.remember ? 3650 : 1,
|
||||
});
|
||||
setToken(true);
|
||||
navigate('/');
|
||||
})
|
||||
.catch((e) => setError(() => e.response.data));
|
||||
|
|
@ -83,7 +87,6 @@ function Login() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Email'
|
||||
name='email'
|
||||
variant='outlined'
|
||||
|
|
@ -94,7 +97,6 @@ function Login() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outlined-password-input'
|
||||
label='Password'
|
||||
name='password'
|
||||
type='password'
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ import axios from 'axios';
|
|||
|
||||
import { Box, Typography, TextField, Button } from '@mui/material';
|
||||
|
||||
import Form from '../utils/Form';
|
||||
|
||||
function Recover() {
|
||||
const [form, setForm] = useState({
|
||||
email: '',
|
||||
|
|
@ -34,47 +32,44 @@ function Recover() {
|
|||
}
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Typography variant='h4' sx={{ marginTop: '1vh 0vh' }}>
|
||||
Recover my Password
|
||||
</Typography>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Email'
|
||||
name='email'
|
||||
variant='outlined'
|
||||
onChange={handleChange}
|
||||
value={form.email}
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
/>
|
||||
{error && (
|
||||
<Box textAlign='right'>
|
||||
<Typography variant='body2' color='error'>
|
||||
{error}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{success && (
|
||||
<Box textAlign='right'>
|
||||
<Typography variant='body2' color='primary'>
|
||||
{success}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
type='submit'
|
||||
fullWidth
|
||||
>
|
||||
Recover my password
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Typography variant='h4' sx={{ marginTop: '1vh 0vh' }}>
|
||||
Recover my Password
|
||||
</Typography>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
label='Email'
|
||||
name='email'
|
||||
variant='outlined'
|
||||
onChange={handleChange}
|
||||
value={form.email}
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
/>
|
||||
{error && (
|
||||
<Box textAlign='right'>
|
||||
<Typography variant='body2' color='error'>
|
||||
{error}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{success && (
|
||||
<Box textAlign='right'>
|
||||
<Typography variant='body2' color='primary'>
|
||||
{success}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
type='submit'
|
||||
fullWidth
|
||||
>
|
||||
Recover my password
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ function Register() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='First Name'
|
||||
name='firstName'
|
||||
variant='outlined'
|
||||
|
|
@ -64,7 +63,6 @@ function Register() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Last Name'
|
||||
name='lastName'
|
||||
variant='outlined'
|
||||
|
|
@ -75,7 +73,6 @@ function Register() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Email'
|
||||
name='email'
|
||||
variant='outlined'
|
||||
|
|
@ -85,7 +82,6 @@ function Register() {
|
|||
/>
|
||||
<TextField
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Pronouns'
|
||||
name='pronouns'
|
||||
variant='outlined'
|
||||
|
|
@ -96,7 +92,6 @@ function Register() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outlined-password-input'
|
||||
label='Password'
|
||||
name='password'
|
||||
type='password'
|
||||
|
|
@ -108,7 +103,6 @@ function Register() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outlined-password-input'
|
||||
label='Confirm Password'
|
||||
name='confirmPassword'
|
||||
type='password'
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import axios from 'axios';
|
|||
|
||||
import { Box, Typography, TextField, Button } from '@mui/material';
|
||||
|
||||
import Form from '../utils/Form';
|
||||
|
||||
function Reset() {
|
||||
const navigate = useNavigate();
|
||||
const { id } = useParams();
|
||||
|
|
@ -42,54 +40,50 @@ function Reset() {
|
|||
}
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Typography variant='h4' sx={{ marginTop: '1vh 0vh' }}>
|
||||
Reset my Password
|
||||
</Typography>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Password'
|
||||
name='password'
|
||||
variant='outlined'
|
||||
type='password'
|
||||
onChange={handleChange}
|
||||
value={form.password}
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
/>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='Confirm Password'
|
||||
name='confirmPassword'
|
||||
variant='outlined'
|
||||
type='password'
|
||||
onChange={handleChange}
|
||||
value={form.confirmPassword}
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
/>
|
||||
{error && (
|
||||
<Box textAlign='right'>
|
||||
<Typography variant='body2' color='error'>
|
||||
{error}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
type='submit'
|
||||
fullWidth
|
||||
disabled={form.password !== form.confirmPassword}
|
||||
>
|
||||
Reset my Password
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Typography variant='h4' sx={{ marginTop: '1vh 0vh' }}>
|
||||
Reset my Password
|
||||
</Typography>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
label='Password'
|
||||
name='password'
|
||||
variant='outlined'
|
||||
type='password'
|
||||
onChange={handleChange}
|
||||
value={form.password}
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
/>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
label='Confirm Password'
|
||||
name='confirmPassword'
|
||||
variant='outlined'
|
||||
type='password'
|
||||
onChange={handleChange}
|
||||
value={form.confirmPassword}
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
/>
|
||||
{error && (
|
||||
<Box textAlign='right'>
|
||||
<Typography variant='body2' color='error'>
|
||||
{error}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
sx={{ margin: '1vh 0vh' }}
|
||||
type='submit'
|
||||
fullWidth
|
||||
disabled={form.password !== form.confirmPassword}
|
||||
>
|
||||
Reset my Password
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import React, { useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
|
||||
import axios from 'axios';
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
import { Typography, TextField, Button } from '@mui/material';
|
||||
|
||||
|
|
@ -9,6 +10,7 @@ import Form from '../utils/Form';
|
|||
|
||||
function UpdateOrganization() {
|
||||
const { orgID } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [name, setName] = useState('');
|
||||
|
||||
|
|
@ -20,10 +22,15 @@ function UpdateOrganization() {
|
|||
|
||||
async function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
await axios.patch(`${process.env.REACT_APP_DOMAIN_ROOT}/org/update`, {
|
||||
orgName: name,
|
||||
orgID,
|
||||
});
|
||||
await axios
|
||||
.patch(`${process.env.REACT_APP_DOMAIN_ROOT}/org/update`, {
|
||||
token: Cookies.get('token'),
|
||||
orgName: name,
|
||||
orgID,
|
||||
})
|
||||
.then(() => {
|
||||
navigate(`/org/${orgID}`);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -35,8 +42,7 @@ function UpdateOrganization() {
|
|||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id='outline-required'
|
||||
label='name'
|
||||
label='Name'
|
||||
name='name'
|
||||
variant='outlined'
|
||||
onChange={handleChange}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,18 @@ function OrgDashboard() {
|
|||
const { orgID } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [org, setOrg] = useState({});
|
||||
const [org, setOrg] = useState({
|
||||
orgID: '',
|
||||
orgName: '',
|
||||
orgOwner: {
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
email: '',
|
||||
},
|
||||
orgMembers: [],
|
||||
createdAt: '',
|
||||
memberCount: 0,
|
||||
});
|
||||
const [rows, setRows] = useState([]);
|
||||
const [status, setStatus] = useState('');
|
||||
const [selection, setSelection] = useState();
|
||||
|
|
@ -36,37 +47,41 @@ function OrgDashboard() {
|
|||
)
|
||||
.then((response) => {
|
||||
const res = response.data;
|
||||
|
||||
setOrg(() => {
|
||||
return {
|
||||
orgID: res.orgID,
|
||||
orgName: res.orgName,
|
||||
orgID: res.org.orgID,
|
||||
orgName: res.org.orgName,
|
||||
orgOwner: {
|
||||
firstName: res.orgOwner.firstName,
|
||||
lastName: res.orgOwner.lastName,
|
||||
email: res.orgOwner.email,
|
||||
firstName: res.org.orgOwner.firstName,
|
||||
lastName: res.org.orgOwner.lastName,
|
||||
email: res.org.orgOwner.email,
|
||||
},
|
||||
orgMembers: res.orgMembers,
|
||||
createdAt: res.createdAt,
|
||||
orgMembers: res.org.orgMembers,
|
||||
createdAt: res.org.createdAt,
|
||||
memberCount: res.memberCount,
|
||||
};
|
||||
});
|
||||
|
||||
const orgMembers = res.orgMembers.map((member, index) => {
|
||||
const orgMembers = res.org.orgMembers.map((member) => {
|
||||
return {
|
||||
id: member.userID,
|
||||
...member,
|
||||
};
|
||||
});
|
||||
|
||||
setRows(() => orgMembers);
|
||||
|
||||
setStatus(() => res.status);
|
||||
})
|
||||
.catch(() => {
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
navigate('/');
|
||||
});
|
||||
}
|
||||
|
||||
getData();
|
||||
});
|
||||
}, [navigate, orgID]);
|
||||
|
||||
async function handleDelete() {
|
||||
await axios
|
||||
|
|
@ -76,7 +91,7 @@ function OrgDashboard() {
|
|||
orgID,
|
||||
},
|
||||
})
|
||||
.then(navigate(''));
|
||||
.then(navigate('/'));
|
||||
}
|
||||
|
||||
function copyID() {
|
||||
|
|
@ -117,7 +132,7 @@ function OrgDashboard() {
|
|||
Organization ID: {org.orgID}
|
||||
</Typography>
|
||||
<Typography variant='body1'>
|
||||
Members: {org.orgMembers.length}
|
||||
Members: {org.memberCount}
|
||||
</Typography>
|
||||
<Typography variant='body1'>
|
||||
Created On: {org.createdAt}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ function OrgUnit({ org }) {
|
|||
return (
|
||||
<React.Fragment>
|
||||
<Typography variant='h6'>
|
||||
<Link to={orgID}>Name: {orgName}</Link>
|
||||
<Link to={`org/${orgID}`}>Name: {orgName}</Link>
|
||||
</Typography>
|
||||
<Box>
|
||||
<Stack spacing={2} direction={{ xs: 'column', md: 'row' }}>
|
||||
|
|
|
|||
756
package-lock.json
generated
756
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -23,13 +23,29 @@ app.set('port', port);
|
|||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
async function connectDatabase() {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log(
|
||||
`[INFO]: Database connection to ${process.env.NODE_ENV} has been established successfully.`
|
||||
);
|
||||
if (process.env.NODE_ENV == 'development') {
|
||||
await sequelize.sync({ force: 'true' });
|
||||
console.log('[INFO]: Wiping all tables on database');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('[ERROR]: Unable to connect to the database;', error);
|
||||
}
|
||||
}
|
||||
connectDatabase().then(() => {
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
});
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
|
|
@ -82,19 +98,6 @@ function onError(error) {
|
|||
*/
|
||||
|
||||
async function onListening() {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log(
|
||||
`[INFO]: Database connection to ${process.env.NODE_ENV} has been established successfully.`
|
||||
);
|
||||
if (process.env.NODE_ENV == 'development') {
|
||||
await sequelize.sync({ force: 'true' });
|
||||
console.log('[INFO]: Wiping all tables on database');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Unable to connect to the database:', error);
|
||||
}
|
||||
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
const { User, Organization } = require('../models/index');
|
||||
const { Organization } = require('../models/index');
|
||||
|
||||
async function GetOrg(req, res, next) {
|
||||
const user = req.user;
|
||||
const orgID = req.params.orgID || req.query.orgID || req.body.orgID;
|
||||
|
||||
const verify = await Organization.findOne({
|
||||
where: { orgID: orgID },
|
||||
const result = await Organization.findByPk(orgID, {
|
||||
include: [
|
||||
{
|
||||
association: 'orgOwner',
|
||||
|
|
@ -20,11 +19,11 @@ async function GetOrg(req, res, next) {
|
|||
],
|
||||
});
|
||||
|
||||
if (!verify) {
|
||||
if (!result) {
|
||||
return res.status(500).send('There is no organization with this id.');
|
||||
}
|
||||
|
||||
if (!verify.orgOwner && verify.orgMembers.length == 0) {
|
||||
if (!result.orgOwner && result.orgMembers.length == 0) {
|
||||
return res
|
||||
.status(500)
|
||||
.send('You do not know any organizations with this id.');
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module.exports = (sequelize, DataTypes) => {
|
|||
onDelete: 'CASCADE',
|
||||
});
|
||||
Organization.belongsToMany(models.User, {
|
||||
as: 'orgMembers',
|
||||
as: 'orgMember',
|
||||
through: 'OrgMembers',
|
||||
uniqueKey: 'orgID',
|
||||
onDelete: 'CASCADE',
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ async function CreateUser(req, res, next) {
|
|||
const body = req.body;
|
||||
|
||||
if (!body.firstName || !body.lastName || !body.email || !body.password) {
|
||||
console.log(body);
|
||||
return res.status(400).send('The request is missing required fields.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ async function GetMemberOrgs(req, res, next) {
|
|||
attributes: { exclude: ['updatedAt'] },
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
return res.status(200).send(result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
async function Logout(req, res, next) {
|
||||
const user = req.user;
|
||||
const token = await user.getToken();
|
||||
await token.destroy();
|
||||
|
||||
if (token) {
|
||||
await token.destroy();
|
||||
}
|
||||
|
||||
return res.send('User logged out');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ async function AddOrgMember(req, res, next) {
|
|||
const user = req.user;
|
||||
const orgID = req.params.orgID;
|
||||
|
||||
const result = await Organization.findOne({ where: { orgID: orgID } });
|
||||
const result = await Organization.findByPk(orgID);
|
||||
|
||||
if (!result) {
|
||||
return res.status(500).send('No organization exists with that id.');
|
||||
}
|
||||
|
||||
await result.addOrgMember(user);
|
||||
await result.addOrgMember(user.userID);
|
||||
|
||||
return res.send('User added to organization.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ async function CreateOrg(req, res, next) {
|
|||
return res.status(400).send('Form missing necessary fields');
|
||||
}
|
||||
|
||||
console.log(user);
|
||||
const existing = await user.countOwnedOrg({
|
||||
where: { orgName: orgName },
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
const { Organization } = require('../../models/index');
|
||||
|
||||
async function DeleteOrg(req, res, next) {
|
||||
const user = req.user;
|
||||
const orgID = req.query.orgID;
|
||||
|
||||
await user.removeOwnedOrg({ where: { orgID: orgID } });
|
||||
await Organization.destroy({ where: { orgID: orgID } });
|
||||
|
||||
return res.send('Organization deleted');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@ async function GetOrg(req, res, next) {
|
|||
],
|
||||
});
|
||||
|
||||
const status = org.orgOwner.userID == user.userID;
|
||||
const status = org.ownerID == user.userID;
|
||||
|
||||
return res.send({
|
||||
org: { ...org, memberCount: org.orgMembers.length },
|
||||
org,
|
||||
memberCount: org.orgMembers.length,
|
||||
status,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,10 @@ async function RemoveOrgMember(req, res, next) {
|
|||
}
|
||||
|
||||
if (!doomedUserIDs) {
|
||||
await result.removeOrgMember({ where: { userID: user.userID } });
|
||||
await result.removeOrgMember(user.userID);
|
||||
} else {
|
||||
if (user.userID == result.orgOwner.userID) {
|
||||
await result.removeOrgMembers({
|
||||
where: { userID: { [Op.in]: doomedUserIDs } },
|
||||
});
|
||||
await result.removeOrgMembers(doomedUserIDs);
|
||||
} else {
|
||||
res.status(403).send('You do not have permission to do that.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,16 @@ async function UpdateOrgDetails(req, res, next) {
|
|||
const orgName = req.body.orgName;
|
||||
const orgID = req.body.orgID;
|
||||
|
||||
if (!orgName) {
|
||||
if (!orgName || !orgID) {
|
||||
return res.status(400).send('Form missing required information.');
|
||||
}
|
||||
|
||||
const result = await user.getOwnedOrgs({ where: { orgID: orgID } });
|
||||
const result = await user.getOwnedOrg({ where: { orgID: orgID } });
|
||||
|
||||
if (result.length < 1) {
|
||||
return res.status(400).send('No organzation with that ID exists.');
|
||||
}
|
||||
|
||||
result[0].update({ orgName: orgName });
|
||||
|
||||
return res.send(result);
|
||||
|
|
|
|||
Reference in a new issue