Skip to content

Commit

Permalink
feat: Refactor code and improve UI for statistics (#1400)
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinWitt authored Dec 25, 2023
1 parent aa6bd8e commit 337128d
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 140 deletions.
53 changes: 52 additions & 1 deletion frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,13 @@ const themeOptions: ThemeOptions = {
},
},
spacing: 8,

typography: {
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
fontSize: 14,
fontWeightLight: 300,
fontWeightRegular: 400,
fontWeightMedium: 500,
},
components: {
MuiCard: {
styleOverrides: {
Expand All @@ -93,6 +99,51 @@ const themeOptions: ThemeOptions = {
},
},
},
MuiTable: {
styleOverrides: {
root: {
'& .MuiTableRow-root:hover': {
backgroundColor: '#eceff1', // on hover background color for TableRow
'& .MuiTableCell-root': {
color: '#000000', // on hover text color for TableCell
},
}
}
}
},
MuiTableCell: {
styleOverrides: {
root: {
paddingTop: '12px',
paddingBottom: '12px',
},
head: {
fontSize: 16, // Increased the font size from 14 to 16
color: '#000000', // Change font color to black
}
}
},
MuiTypography: {
styleOverrides: {
h4: {
fontSize: '1.6rem',
fontWeight: 500,
},
h5: {
fontSize: '1.4rem',
fontWeight: 500,
}
}
},
MuiTableHead: {
styleOverrides: {
root: {
backgroundColor: '#b3e5fc', // light blue color for table header background
textColor: '#000000', // on hover text color for TableCell
}
}
},

},
};
const theme = createTheme(themeOptions);
Expand Down
23 changes: 3 additions & 20 deletions frontend/src/pages/PageLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,9 @@
import React from 'react';
import {
Grid,
AppBar,
Toolbar,
List,
ListItem,
ListItemText,
Box,
Divider,
} from '@mui/material';
import { LoginButton } from '../component/LoginButton';
import { useNavigate } from 'react-router';
import Sidebar, { LinkType } from '../component/Sidebar';

interface NameProps {
name: string;
}

interface Link {
name: string;
href: string;
}
interface PageLayoutProps {
children: React.ReactNode;
}
Expand All @@ -35,15 +18,15 @@ export default function PageLayout({ children }: PageLayoutProps) {
<Grid
container
spacing={2}
justifyContent="flex-start" // added this
style={{ height: 'calc(100%) ', flexWrap: 'nowrap' }}
>
<Grid item sx={{ width: '200px' }}>
<Grid item xs={2.5}>
<Sidebar links={navigationItems} />
</Grid>
<Grid item xs={9} sx={{}}>
<Grid item xs={9} style={{ overflow: 'auto' }}>
{children}
</Grid>
<Grid item xs={1}></Grid>
</Grid>
</div>
);
Expand Down
200 changes: 102 additions & 98 deletions frontend/src/pages/StatisticsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,109 +1,98 @@
import { useQuery } from '@apollo/client';
import PageLayout from './PageLayout';
import {
Box,
Card,
CardContent,
CardHeader,
Divider,
LinearProgress,
Box, Breadcrumbs, Grid,
LinearProgress, Link,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
} from '@mui/material';
import Avatar from 'react-avatar';
import { FancyText } from '../styled/FancyText';
import { GetProjectsQuery, Project } from '../gql/graphql';
import { Error } from '@mui/icons-material';
import { graphql } from '../gql';
import { useGetProjectsQuery } from '../gql/graphql-types';
import { useGetProjectsQuery, GetProjectsQuery } from '../gql/graphql-types';

function toCard(card: CardData[]) {
const { owner, url } = card[0];
return (
<Card
key={url}
sx={{
width: 275,
height: 275,
margin: 2,
boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.2)',
}}
>
<CardHeader
sx={{ flexDirection: 'column-reverse' }}
avatar={<Avatar githubHandle={owner} />}
title={<FancyText variant="h6">{owner}</FancyText>}
/>
<CardContent>
<FancyText>{card.length} Projects</FancyText>
</CardContent>
</Card>
);
}
type CardData = {
owner: string;
type OrgStats = {
name: string;
url: string;
commitHashes: string[];
projectCount: number;
commitCount: number;
issuesCount: number;
};
type OrgData = {
[key: string]: OrgStats;
};

function Statistics({ projects }: { projects: CardData[] }) {
// group the projects by owner
const groupedProjects: { [key: string]: CardData[] } = {};
projects.forEach((project) => {
if (groupedProjects[project.owner]) {
groupedProjects[project.owner].push(project);
} else {
groupedProjects[project.owner] = [project];
export function calculateOrganizationStats(data: GetProjectsQuery): OrgData {
const organizations: OrgData = {};
data.getProjects!.forEach((project) => {
const urlParts = project!.projectUrl!.split('/');
const owner = urlParts[urlParts.length - 2];
let commitCount = project!.commits?.length || 0;
let issuesCount = 0;
project!.commits?.forEach((commit) => {
commit?.analyzerStatuses?.forEach((status) => {
issuesCount += status?.numberOfIssues || 0;
});
});
if (!organizations[owner]) {
organizations[owner] = {
name: owner,
projectCount: 0,
commitCount: 0,
issuesCount: 0,
};
}
organizations[owner].projectCount += 1;
organizations[owner].commitCount += commitCount;
organizations[owner].issuesCount += issuesCount;
});
console.log(organizations);
return organizations;
}

const numOwners = Object.keys(groupedProjects).length;
type OrgStatsTableProps = {
organizations: OrgData;
};

export const OrgStatsTable: React.FC<OrgStatsTableProps> = ({
organizations,
}) => {
return (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
marginTop: 4,
}}
>
<FancyText sx={{ fontSize: 60 }} variant="h1">
Statistics
</FancyText>
<Divider sx={{ width: '50%', margin: '2rem 0' }} />
<FancyText>{numOwners} owners</FancyText>
<FancyText>{projects.length} projects</FancyText>
<Divider sx={{ width: '50%', margin: '2rem 0' }} />
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
{Object.values(groupedProjects).map((card) => toCard(card))}
</div>
</Box>
<TableContainer component={Paper}>
<Table aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Organization</TableCell>
<TableCell align="right">Project Count</TableCell>
<TableCell align="right">Commit Count</TableCell>
<TableCell align="right">Issues Count</TableCell>
</TableRow>
</TableHead>
<TableBody>
{Object.values(organizations).map(
(org) => (
(
<TableRow key={org.name}>
<TableCell component="th" scope="row">
{org.name}
</TableCell>
<TableCell align="right">{org.projectCount}</TableCell>
<TableCell align="right">{org.commitCount}</TableCell>
<TableCell align="right">{org.issuesCount}</TableCell>
</TableRow>
)
)
)}
</TableBody>
</Table>
</TableContainer>
);
}
};

const postsQueryDocument = graphql(`
query getProjects {
getProjects {
projectName
projectUrl
commitHashes
commits {
analyzerStatuses {
analyzerName
commitHash
localDateTime
numberOfIssues
status
}
commitHash
}
}
}
`);
export function StatisticPage() {
const { loading, error, data } = useGetProjectsQuery();

if (loading) return <PageLayout children={<LinearProgress />}></PageLayout>;
if (error)
return (
Expand All @@ -114,28 +103,43 @@ export function StatisticPage() {
</Error>
</PageLayout>
);
console.log(data)
if (!data || data.getProjects?.length === 0) {
return (
<PageLayout>
<Box padding={5} display="flex" flexDirection="row" alignItems="center">
<Grid container component={Paper} style={{backgroundColor: '#3f51b5', padding: '10px', margin: '20px'}}>
<Breadcrumbs aria-label="breadcrumb">
<Link color="inherit" href="/">
Home
</Link>
<Typography color="textPrimary">Statistics</Typography>
</Breadcrumbs>
</Grid>
<Box
padding="5px"
display="flex"
flexDirection="row"
alignItems="center"
>
<Error />
<Typography variant="h5">No Data found </Typography>
</Box>
</PageLayout>
);
}
const projects: CardData[] = data.getProjects!.map((project) => {
const urlParts = project!.projectUrl!.split('/');
const owner = urlParts[urlParts.length - 2];
const name = urlParts[urlParts.length - 1];
const url = urlParts.join('/');
const commitHashes = project!.commitHashes;
return { owner, name, url, commitHashes } as CardData;
});
const organizations = calculateOrganizationStats(data);

return (
<PageLayout>
<Statistics projects={projects} />
<Grid container component={Paper} style={{backgroundColor: '#3f51b5', padding: '10px', margin: '20px'}}>
<Breadcrumbs aria-label="breadcrumb">
<Link color="inherit" href="/">
Home
</Link>
<Typography color="textPrimary">Statistics</Typography>
</Breadcrumbs>
</Grid>
<OrgStatsTable organizations={organizations} />
</PageLayout>
);
}
Loading

0 comments on commit 337128d

Please sign in to comment.