Skip to content

Commit 3445607

Browse files
Admin features
Admin authorization, admin dashboard, admin crud events
1 parent 65637a5 commit 3445607

File tree

9 files changed

+1599
-496
lines changed

9 files changed

+1599
-496
lines changed

package-lock.json

+958-251
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@material-ui/core": "^4.11.3",
6+
"@material-ui/core": "^4.12.4",
7+
"@material-ui/icons": "^4.11.3",
8+
"@material-ui/lab": "^4.0.0-alpha.61",
79
"@testing-library/jest-dom": "^5.11.10",
810
"@testing-library/react": "^11.2.6",
911
"@testing-library/user-event": "^12.8.3",
1012
"axios": "^0.21.1",
1113
"bootstrap": "^5.0.1",
14+
"material-table": "^1.69.3",
1215
"moment": "^2.29.4",
1316
"node-sass": "^6.0.0",
1417
"react": "^17.0.2",

src/components/admin-head.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class Header extends Component {
4444
</li>
4545
</ul>
4646
<a className="nav-link" href="signout">Log Out</a>
47-
<a href="dashboard"><button className="btn btn-outline my-2 my-sm-0">Lola</button></a>
47+
<a href="/dashboard"><button className="btn btn-outline my-2 my-sm-0">{user?.username}</button></a>
4848
</div>
4949
</nav>
5050
</React.Fragment>

src/services/admin_api.js

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import Axios from "axios"
2+
export default new (class Http {
3+
API_URL = "https://wosca-backend.herokuapp.com/api/v1"
4+
5+
6+
AxiosSetup = () => {
7+
const token = localStorage.getItem("ad_token")
8+
const axiosInstance = Axios.create({
9+
baseURL: this.API_URL,
10+
})
11+
axiosInstance.defaults.headers.common.Authorization = "Bearer " + token;
12+
axiosInstance.interceptors.response.use(
13+
(response) => {
14+
return response
15+
},
16+
(error) => {
17+
return Promise.reject(error)
18+
}
19+
)
20+
return axiosInstance
21+
}
22+
23+
post = async (urlpath, data, config) => {
24+
try {
25+
const response = await this.AxiosSetup().post(urlpath, data, config)
26+
if (
27+
response.data.errorMsg !== null
28+
) {
29+
localStorage.removeItem("jwt_token")
30+
// window.location.reload()
31+
}
32+
return response
33+
} catch (err) {
34+
return err
35+
}
36+
}
37+
38+
put = async (urlpath, data, config) => {
39+
try {
40+
const response = await this.AxiosSetup().put(urlpath, data, config)
41+
if (
42+
response.data.errorMsg !== null
43+
) {
44+
localStorage.removeItem("jwt_token")
45+
// window.location.reload()
46+
}
47+
return response
48+
} catch (err) {
49+
return err
50+
}
51+
}
52+
53+
get = async (urlpath) => {
54+
const url = `${urlpath}`
55+
try {
56+
const response = await this.AxiosSetup().get(url)
57+
if (
58+
response.data.errorMsg !== null
59+
) {
60+
localStorage.removeItem("jwt_token")
61+
// window.location.reload()
62+
}
63+
return response
64+
} catch (err) {
65+
return err
66+
}
67+
}
68+
69+
delete = async (urlpath, data) => {
70+
try {
71+
const response = await this.AxiosSetup().delete(urlpath, data)
72+
if (
73+
response.data.errorMsg !== null
74+
) {
75+
localStorage.removeItem("jwt_token")
76+
// window.location.reload()
77+
}
78+
return response
79+
} catch (err) {
80+
return err
81+
}
82+
}
83+
})()

src/styles/views/admin-page.css

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
.MuiTableCell-body {
2+
color: #FFFFFF !important;
3+
}
4+
5+
.MuiTableCell-root {
6+
border-bottom: 0px !important;
7+
}
8+
9+
.MuiPaper-elevation2 {
10+
width: 100%;
11+
overflow-x: auto;
12+
}
13+
14+
.MTableToolbar-root-12 {
15+
padding-right: 8px;
16+
color: #B70569;
17+
}
18+
19+
.MuiSvgIcon-root {
20+
color: #B70569;
21+
}
22+
23+
.MuiInputBase-input {
24+
color: #FFFFFF !important;
25+
/* color: #B70569 !important; */
26+
}
27+
28+
.MuiTypography-caption {
29+
color: #FFFFFF !important;
30+
}
31+
32+
.MuiTypography-h6 {
33+
font-family: 'Axiforma' !important;
34+
padding-left: 15px !important;
35+
color: #B70569;
36+
}
37+
38+
.MuiTypography-body1, .MuiTypography-body2, .MuiPickersYear-root {
39+
color: #B70569 !important;
40+
}
41+
42+
.MuiPickersYear-yearSelected {
43+
color: #FFFFFF !important;
44+
}

src/views/admin/adminService.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import http from "../../services/admin_api"
2+
3+
// PRS
4+
export const prs = () => {
5+
return http.get('/pulls/');
6+
}
7+
8+
export const _all_events = () => {
9+
return http.get('/events/');
10+
}
11+
12+
export const _add_event = e => {
13+
return http.post(`/events/`, e);
14+
}
15+
16+
export const _update_event = (s, e) => {
17+
return http.put(`/events/${s}`, e);
18+
}
19+
20+
export const _delete_event = (e) => {
21+
return http.delete(`/events/${e}`);
22+
}

src/views/admin/custom.js

+51-15
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,55 @@
1-
import React from 'react';
2-
import { AiOutlineLink } from 'react-icons/ai'
3-
import { BsCheckAll } from 'react-icons/bs'
1+
import React, { Component } from 'react';
2+
import { AiOutlineLink } from 'react-icons/ai';
3+
import { BsCheckAll } from 'react-icons/bs';
44
import { Card } from "../../components/Card";
5+
import { UserContext } from "../../context/AuthContext";
6+
import { prs } from "./adminService";
57

6-
function Dashboard() {
7-
return (
8-
<React.Fragment>
9-
<div className="admin-greeting"> <p>Welcome Here, Lola</p></div>
10-
<div className="contribution-cards admin-cards">
11-
<Card title="Total Contributions" value="345" icon={<AiOutlineLink color={'#fff'} />} />
12-
<Card title="Total Submitted PRs" value="345" icon={<AiOutlineLink color={'#fff'} />} />
13-
<Card title="Accepted Contributions" value="345" icon={<BsCheckAll color={'#fff'} />} />
14-
</div>
15-
</React.Fragment >
16-
);
17-
}
8+
class Dashboard extends Component {
9+
constructor(props) {
10+
super(props);
11+
this.state = {
12+
pr: 1,
13+
total_users: 2,
14+
total_events: 3,
15+
};
16+
}
17+
18+
render() {
19+
const { token, user } = this.context
20+
return (
21+
<React.Fragment>
22+
<div className="admin-greeting"> <p>Welcome Here, {user?.username}</p></div>
23+
<div className="contribution-cards admin-cards">
24+
<Card title="Total Users" value={this.state.total_users} icon={<AiOutlineLink color={'#fff'} />} />
25+
<Card title="Total Submitted PRs" value={this.state.pr} icon={<AiOutlineLink color={'#fff'} />} />
26+
<Card title="Accepted Contributions" value={this.state.total_events} icon={<BsCheckAll color={'#fff'} />} />
27+
</div>
28+
</React.Fragment >
29+
);
30+
}
1831

32+
async componentDidMount() {
33+
var au = this.context.user;
34+
if (!au) {
35+
window.location.replace('/signin')
36+
} else if (au.role !== 'admin') {
37+
window.location.replace('/dashboard')
38+
} else {
39+
// find totalcontributions
40+
// find PRS
41+
await prs()
42+
.then((response) => {
43+
var count = response.data.data.pullRequests.length
44+
this.setState({ pr: count })
45+
})
46+
.catch((error) => {
47+
console.log(error)
48+
// alert.error(error)
49+
})
50+
// find acceptedcontributions
51+
}
52+
}
53+
}
54+
Dashboard.contextType = UserContext
1955
export default Dashboard;

0 commit comments

Comments
 (0)