Skip to content

Commit

Permalink
created dashboard stats and included authentication and authorization…
Browse files Browse the repository at this point in the history
… rules
  • Loading branch information
jamiebones committed Mar 25, 2021
1 parent 57fcc76 commit f550484
Show file tree
Hide file tree
Showing 22 changed files with 807 additions and 456 deletions.
95 changes: 94 additions & 1 deletion client/src/components/adminDashboard.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
import React from "react";
import React, { useState, useEffect } from "react";
import "react-tabs/style/react-tabs.css";
import { GetAdminDashboardStats } from "../graphql/queries";
import { useQuery } from "@apollo/client";
import styled from "styled-components";
import Loading from "./common/loading";

const AdminDashboardStyles = styled.div`
.account {
background-color: #30375a;
}
.hostel {
background-color: #090f1f;
}
.vacant {
background-color: #462e02;
}
.occupied {
background-color: #104008;
}
.lock {
background-color: #a52b2b;
}
.stats {
display: inline-block;
width: 400px;
height: 150px;
margin: 20px;
padding: 10px;
position: relative;
}
.label {
font-size: 26px;
color: #c0c0c0;
}
.value {
font-size: 30px;
color: white;
position: absolute;
bottom: 2px;
right: 5px;
}
@media print {
.react-tabs__tab {
display: none;
Expand All @@ -14,11 +57,61 @@ const AdminDashboardStyles = styled.div`
`;

const AdminDashboard = () => {
const [stats, setStats] = useState(null);
const { error, data, loading } = useQuery(GetAdminDashboardStats);
const [errors, setErrors] = useState(null);

useEffect(() => {
if (error) {
setErrors(error);
}

if (data) {
setStats(data.getAdminDashBoardStats);
console.log(data.getAdminDashBoardStats);
}
}, [data, error]);

return (
<AdminDashboardStyles>
<div className="row">
<div className="col-md-12">
<div className="text-center">
{errors && <p className="lead text-danger">{errors.message}</p>}
{loading && <Loading />}
</div>
<p className="lead">Welcome Admin</p>
{stats && (
<React.Fragment>
<div className="stats account">
<p className="label">Student Account</p>

<p className="value">{stats.studentAccounts}</p>
</div>
<div className="stats hostel">
<p className="label">Hostels</p>

<p className="value">{stats.hostelNumber}</p>
</div>
<div className="stats vacant">
<p className="label">Vacant Beds</p>

<p className="value">{stats.vacantBeds}</p>
</div>

<div className="stats lock">
<p className="label">Locked Beds</p>

<p className="value">{stats.lockedBeds}</p>
</div>

<div className="stats occupied">
<p className="label">Occupied Beds</p>

<p className="value">{stats.occupiedBeds}</p>
</div>
</React.Fragment>
)}
</div>
</div>
</AdminDashboardStyles>
Expand Down
13 changes: 13 additions & 0 deletions client/src/graphql/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,20 @@ const GetSuccessFullTransactions = gql`
}
`;

const GetAdminDashboardStats = gql`
query getAdminDashBoardStats {
getAdminDashBoardStats {
studentAccounts
hostelNumber
vacantBeds
lockedBeds
occupiedBeds
}
}
`;

export {
GetAdminDashboardStats,
GetSMSCreditAvailable,
GetHostelById,
CheckphoneIfThePersonHasTriedsMoreThanThreeTimes,
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ services:
CheapGlobalSmsGateway: http://cheapglobalsms.com/api_v1
CheapGlobalSmsSubAccount: 9540_uniuyo
CheapGlobalSmsSubAccountPassword: blazing147
DeveloperBugsEmailSupport: bugsreport2021@gmail.com
DeveloperBugsEmailPassword: blazing147



Expand Down
27 changes: 27 additions & 0 deletions server/logs/app.log

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"morgan": "^1.10.0",
"node-cron": "^2.0.3",
"node-fetch": "^2.6.1",
"nodemailer": "^6.5.0",
"react-icons": "^3.11.0",
"redis": "^3.0.2",
"util": "^0.12.3",
Expand Down
9 changes: 9 additions & 0 deletions server/src/config/checkAccessRight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// const CheckAccessRight = (rightsArray, user) => {
// if (!user) return false;
// const accessLevel = user.accessLevel;
// const accessIndex = rightsArray.indexOf(accessLevel.toLowerCase());
// if (accessIndex != -1) return true;
// return false;
// };

// export default CheckAccessRight;
2 changes: 2 additions & 0 deletions server/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import logger from "./winston";
import redis from "./redis-client";
import isAuth from "./isAuth";
import createCollection from "./createCollection";
import checkAccessRight from "./checkAccessRight";

export default {
...key,
winston: logger,
redisClient: redis,
isAuth,
createCollection,
checkAccessRight,
};
2 changes: 2 additions & 0 deletions server/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ async function StartUp() {
return new Error("Internal server error");
}
console.log("this is an error", err);
//send the email here about the error to the developer

return err;
//return new Error("There was an error");
},
Expand Down
1 change: 1 addition & 0 deletions server/src/methods/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import confirmPhoneMethod from "./confirmPhoneTable";
import userMethod from "./users";
import messageMethod from "./message"


export default {
studentBioMethod,
transactionMethod,
Expand Down
2 changes: 2 additions & 0 deletions server/src/methods/message/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import JusibeModule from "./jusibeModule";
import EBulkSms from "./ebulkSms";
import CheapGlobalSMS from "./cheapGlobalSMS";
import SendErrorEmail from "./sendErrorEmail";

export default {
//JusibeModule,
//EBulkSms,
CheapGlobalSMS,
SendErrorEmail,
};
24 changes: 24 additions & 0 deletions server/src/methods/message/sendErrorEmail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const nodemailer = require("nodemailer");
const { DeveloperBugsEmailSupport, DeveloperBugsEmailPassword } = process.env;

const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: DeveloperBugsEmailSupport,
pass: DeveloperBugsEmailPassword,
},
});

export const sendErrorMailToDeveloper = async (message) => {
var mailOptions = {
from: DeveloperBugsEmailSupport,
to: DeveloperBugsEmailSupport,
subject: "Bugs Report from UUHOSTEL",
text: message,
};
try {
transporter.sendMail(mailOptions);
} catch (error) {
console.log("error send email to developer");
}
};
23 changes: 16 additions & 7 deletions server/src/resolvers/adminRoomAllocation.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { combineResolvers } from "graphql-resolvers";
import { isAuthenticated, isAdmin } from "./authorization";

export default {
Query: {
adminAllocationBySession: async (parent, { session }, { fastConn, slowConn }) => {
const roomDashedByAdmin = await fastConn.models.AdminRoomAllocation.find({
session: session,
});
return roomDashedByAdmin;
},
adminAllocationBySession: combineResolvers(
isAuthenticated,
isAdmin,
async (parent, { session }, { fastConn }) => {
const roomDashedByAdmin = await fastConn.models.AdminRoomAllocation.find(
{
session: session,
}
);
return roomDashedByAdmin;
}
),
},

AdminRoomAllocation: {
student: async (parent, {}, { fastConn, slowConn }) => {
student: async (parent, {}, { fastConn }) => {
const student = await fastConn.models.StudentBio.findOne({
regNumber: parent.regNumber.toLowerCase(),
});
Expand Down
37 changes: 32 additions & 5 deletions server/src/resolvers/authorization.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
import { ForbiddenError } from 'apollo-server';
import { skip } from 'graphql-resolvers';

export const isAuthenticated = (parent, args, { me }) =>
me ? skip : new ForbiddenError('Not authenticated as user.');
import { ForbiddenError } from "apollo-server";
import { skip } from "graphql-resolvers";

export const isAuthenticated = (parent, args, ctx) => {
return ctx && ctx.user
? skip
: new ForbiddenError("Not authenticated as user.");
};

export const isAdmin = (parent, args, { user }) => {
if (user) {
return user.accessLevel === "super-admin" || user.accessLevel === "admin"
? skip
: new ForbiddenError("only an administrator can perform this task");
} else {
return new ForbiddenError("You must be authenticated to continue");
}
};

export const isSuperAdmin = (parent, args, { user }) => {
return user && user.accessLevel === "super-admin"
? skip
: new ForbiddenError(
"you must be login as a super administrator to continue."`1`
);
};

export const isStudent = (parent, args, { user }) => {
return user && user.userType === "student"
? skip
: new ForbiddenError("only a student can perform this task.");
};
45 changes: 45 additions & 0 deletions server/src/resolvers/bedAllocatedStat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { combineResolvers } from "graphql-resolvers";
import { isAuthenticated, isAdmin } from "./authorization";

export default {
Query: {
getAdminDashBoardStats: combineResolvers(
isAuthenticated,
isAdmin,
async (_, {}, { fastConn }) => {
const [
studentAccounts,
hostelNumber,
vacantBeds,
lockedBeds,
occupiedBeds,
] = await Promise.all([
fastConn.models.StudentBio.countDocuments(),
fastConn.models.Hostel.countDocuments(),
fastConn.models.BedSpace.find({
bedStatus: "vacant",
}).countDocuments(),
fastConn.models.BedSpace.find({
bedStatus: "locked",
}).countDocuments(),

fastConn.models.BedSpace.find({
bedStatus: "occupied",
}).countDocuments(),
]);

return {
studentAccounts: +studentAccounts,
hostelNumber: +hostelNumber,
vacantBeds: +vacantBeds,
lockedBeds: +lockedBeds,
occupiedBeds: +occupiedBeds,
};
}
),
getBedAlloctedStats: async (_, {}, {}) => {},
},
Mutation: {
updateBedAlloctedStats: async (parent, {}, {}) => {},
},
};
Loading

0 comments on commit f550484

Please sign in to comment.