Skip to content

Commit

Permalink
Merge pull request #128 from COS301-SE-2024/fix/vaDashboard
Browse files Browse the repository at this point in the history
fixed the date and time format of last report
  • Loading branch information
Alec-Watson authored Sep 26, 2024
2 parents ad1c37f + 1f52fd5 commit b594ba5
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 48 deletions.
97 changes: 62 additions & 35 deletions CoVAR-app/src/app/(pages)/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import SeverityDistribution from './components/severityDistribution';
import VulnerabilityLineChart from './components/lineChart';
import ReportsList from './components/reportsList';
import TopVulnerabilities from './components/topVulnerabilities';
import { fetchLastReportDates, getAllReports, getUserRole, fetchAssignedClients } from '@/functions/requests';
import { fetchLastReportDates, getAllReports, getUserRole, fetchClientsAssigned, fetchOrganisationsAssigned } from '@/functions/requests';
import { useRouter } from 'next/navigation';
import axios from 'axios';
import { evaluateLaunchStyles } from '../../../styles/evaluateStyle';
Expand Down Expand Up @@ -118,14 +118,19 @@ const Dashboard: React.FC = () => {
const fetchAssignedUsersAndOrgs = async () => {
try {
const token = localStorage.getItem('accessToken');
const [usersResponse, orgsResponse, reportDates] = await Promise.all([
axios.get('/api/users/assigned_clients', { headers: { Authorization: `Bearer ${token}` } }),
axios.get('/api/users/assigned_organizations', { headers: { Authorization: `Bearer ${token}` } }),
const userId = userID;
console.log(userId);
const [clients, orgs, reportDates] = await Promise.all([
fetchClientsAssigned(token as string),
fetchOrganisationsAssigned(token as string),
fetchLastReportDates(token as string)
]);

setUsers(usersResponse.data);
setOrganizations(orgsResponse.data);
console.log(clients);
console.log(orgs);
console.log('Report Dates:', reportDates);

setUsers(clients);
setOrganizations(orgs);
setLastReportDatesClients(reportDates.clients);
setLastReportDatesOrgs(reportDates.organizations);
setLoading(false);
Expand All @@ -134,6 +139,8 @@ const Dashboard: React.FC = () => {
setLoading(false);
}
};



const calculateSeverityDistribution = (reports: VulnerabilityReport[]) => {
const distribution: { [key: string]: number } = {
Expand Down Expand Up @@ -181,6 +188,26 @@ const Dashboard: React.FC = () => {
router.push(`/evaluate/organization/${organization.name}`);
};

const formatDate = (dateString: string) => {
if (!dateString) return 'No report';
const date = new Date(dateString);

const formattedDate = date.toLocaleDateString('en-GB', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
});

const formattedTime = date.toLocaleTimeString('en-GB', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});

return `${formattedDate} ${formattedTime}`;
};


const getReportsPerClient = async () => {
try {
const data: ClientReport[] = await fetchReportsPerClient();
Expand Down Expand Up @@ -277,34 +304,34 @@ const Dashboard: React.FC = () => {
{users.length === 0 && organizations.length === 0 ? (
<Typography>No assigned clients or organisations found.</Typography>
) : (
<List>
{users.map((user) => (
<ListItem key={user.user_id} sx={{ marginBottom: 1, padding: 1, borderRadius: 1, boxShadow: 1 }}>
<ListItemText
primary={`User: ${user.username}`}
secondary={`Last Report: ${lastReportDatesClients.find(c => c.client_name === user.username)?.last_report_date || 'No report'}`}
/>
<ListItemSecondaryAction>
<Button variant="contained" onClick={() => handleUserButtonClick(user)}>
Evaluate
</Button>
</ListItemSecondaryAction>
</ListItem>
))}
{organizations.map((org) => (
<ListItem key={org.organization_id} sx={{ marginBottom: 1, padding: 1, borderRadius: 1, boxShadow: 1 }}>
<ListItemText
primary={`Organisation: ${org.name}`}
secondary={`Last Report: ${lastReportDatesOrgs.find(o => o.organization_name === org.name)?.last_report_date || 'No report'}`}
/>
<ListItemSecondaryAction>
<Button variant="contained" onClick={() => handleOrganizationButtonClick(org)}>
Evaluate
</Button>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
<List>
{users.map((user) => (
<ListItem key={user.user_id} sx={{ marginBottom: 1, padding: 1, borderRadius: 1, boxShadow: 1 }}>
<ListItemText
primary={`User: ${user.username}`}
secondary={`Last Report: ${formatDate(lastReportDatesClients.find(c => c.client_name === user.username)?.last_report_date as string) || 'No report'}`}
/>
<ListItemSecondaryAction>
<Button variant="contained" onClick={() => handleUserButtonClick(user)}>
Evaluate
</Button>
</ListItemSecondaryAction>
</ListItem>
))}
{organizations.map((org) => (
<ListItem key={org.organization_id} sx={{ marginBottom: 1, padding: 1, borderRadius: 1, boxShadow: 1 }}>
<ListItemText
primary={`Organisation: ${org.name}`}
secondary={`Last Report: ${formatDate(lastReportDatesOrgs.find(o => o.organization_name === org.name)?.last_report_date as string) || 'No report' }`}
/>
<ListItemSecondaryAction>
<Button variant="contained" onClick={() => handleOrganizationButtonClick(org)}>
Evaluate
</Button>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
)}
</Paper>
</Box>
Expand Down
37 changes: 26 additions & 11 deletions CoVAR-app/src/functions/requests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ export const fetchAssignedClients = async (userId: string, accessToken: string)
return await handleRequest(request);
};



export const fetchAssignedOrganisations = async (userId: string, accessToken: string) => {
const request = {
method: 'get',
Expand All @@ -177,17 +179,30 @@ export const fetchAssignedOrganisations = async (userId: string, accessToken: st
};

export const fetchLastReportDates = async (token: string) => {
try {
const response = await axios.get('/api/reports/last_report_dates', {
headers: {
Authorization: `Bearer ${token}`,
},
});
return response.data;
} catch (error) {
console.error('Error fetching last report dates:', error);
throw error;
}
const request = {
method: 'get',
url: '/api/reports/last_report_dates',
headers: { Authorization: `Bearer ${token}` },
};
return await handleRequest(request);
};

export const fetchClientsAssigned = async (token: string) => {
const request = {
method: 'get',
url: '/api/users/assigned_clients',
headers: { Authorization: `Bearer ${token}` },
};
return await handleRequest(request);
};

export const fetchOrganisationsAssigned = async (token: string) => {
const request = {
method: 'get',
url: '/api/users/assigned_organizations',
headers: { Authorization: `Bearer ${token}` },
};
return await handleRequest(request);
};

export const assignClient = async (userId: string, clientUsername: string, accessToken: string) => {
Expand Down
7 changes: 5 additions & 2 deletions server/routes/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,14 @@ router.get('/reports/all', authenticateToken, async (req, res) => {

// Route to get the last report date for each client or organization
router.get('/reports/last_report_dates', authenticateToken, async (req, res) => {

try {
// Query to get last report date for assigned clients
const clientReports = await pgClient.query(
`SELECT u.username AS client_name, MAX(r.created_at) AS last_report_date
FROM users u
JOIN user_reports ur ON u.user_id = ur.user_id
JOIN reports r ON ur.report_id = r.report_id
WHERE u.role = 'client'
WHERE u.role = 'client' OR u.role = 'admin'
GROUP BY u.username`
);

Expand All @@ -46,6 +45,10 @@ router.get('/reports/last_report_dates', authenticateToken, async (req, res) =>
organizations: organizationReports.rows
};

console.log('Client Reports:', clientReports.rows);
console.log('Organization Reports:', organizationReports.rows);


res.send(result);
} catch (err) {
console.error('Error fetching last report dates:', err);
Expand Down
20 changes: 20 additions & 0 deletions server/routes/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,26 @@ router.get('/users/assigned_clients', authenticateToken, async (req, res) => {
}
});

// Get all organizations assigned to the logged-in VA
router.get('/users/assigned_organizations', authenticateToken, async (req, res) => {
const token = req.headers['authorization'].split(' ')[1];
const decodedToken = verifyToken(token);
const id = decodedToken.user_id;

try {
const organizations = await pgClient.query(
`SELECT * FROM organizations
WHERE organization_id IN (SELECT organization FROM assignment WHERE va = $1)`,
[id]
);
res.send(organizations.rows);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});


// Check if email exists in the database
router.post('/users/checkEmailExists', async (req, res) => {
const { email } = req.body;
Expand Down

0 comments on commit b594ba5

Please sign in to comment.