Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display project & member stats in plugin #34

Merged
merged 19 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions generated/landscape_stats.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@
}
}
},
"cncfProjectMaturitySummary": {
"sandbox": 117,
"incubating": 38,
"graduated": 27,
"archived": 8
},
"cncfSpecialSummary": {
"count": 289,
"commonKeys": [
Expand Down
1 change: 1 addition & 0 deletions packages/cncf-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export type {
StatsCategoryBreakdown,
StatsSubcategoryBreakdown,
CncfProject,
StatsProjectMaturityBreakdown,
} from './types';
4 changes: 4 additions & 0 deletions packages/cncf-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,7 @@ export interface CategoryStats {
categoryBreakdown: StatsCategoryBreakdown;
subcategoryBreakdown: StatsSubcategoryBreakdown;
}

export interface StatsProjectMaturityBreakdown {
[key:string]: number;
}
1 change: 1 addition & 0 deletions plugins/cncf-stats/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.61",
"@mui/x-charts": "^6.19.3",
"cncf-common": "*",
"react-use": "^17.2.4"
},
Expand Down
21 changes: 17 additions & 4 deletions plugins/cncf-stats/src/components/Members/Members.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import React from 'react';
import { CategoryStats } from 'cncf-common';
import { Grid, Card } from '@material-ui/core';
import { StyledPieChart } from '../Utils/charts';


const Chart = ({stats}: {
stats: CategoryStats,
}) => {
return (
<Card>
<StyledPieChart stats={stats.subcategoryBreakdown["CNCF Members"]} count={stats.count} />
</Card>
);
}

export const Members = ({stats}: {
stats: CategoryStats,
}) => {
return (
<>
Members count: {stats.count}
</>
<Grid container>
<Grid item> <Chart stats={stats}/> </Grid>
</Grid>
)
}
};
95 changes: 88 additions & 7 deletions plugins/cncf-stats/src/components/Projects/Projects.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,93 @@
import React from 'react';
import { CategoryStats } from 'cncf-common';
import {
Accordion,
AccordionSummary,
AccordionDetails,
Table,
TableBody,
TableCell,
TableRow,
Grid,
TableContainer,
Paper,
Typography,
Card,
CardHeader,
CardContent,
} from '@material-ui/core';
import ExpandMore from '@material-ui/icons/ExpandMore';
import { CategoryStats, StatsProjectMaturityBreakdown } from 'cncf-common';
import { StyledPieChart } from '../Utils/charts';

export const Projects = ({stats}: {
stats: CategoryStats,
}) => {

const ChartByCategory = ({stats}: {stats: CategoryStats}) => {
const { subcategoryBreakdown, categoryBreakdown } = stats;
return (
<>
Projects count: {stats.count}
</>
<Card>
<CardHeader title="By Category" />
<CardContent>
{Object.keys(subcategoryBreakdown).map((category) => (
<Accordion key={category}>
<AccordionSummary
expandIcon={<ExpandMore/>}
style={{fontSize:16, fontWeight:'bold'}}
>
<Grid container justifyContent='space-between' alignItems='center'>
<Grid item>{category}</Grid>
<Grid item>{categoryBreakdown[category]}</Grid>
</Grid>
</AccordionSummary>
<AccordionDetails style={{backgroundColor:"#f0f0f0", fontSize:16, fontWeight:'bold'}}>
<TableContainer component={Paper}>
<Table>
<TableBody>
{Object.entries(subcategoryBreakdown[category]).map(
([subcategory, count]) => (
<TableRow key={subcategory}>
<TableCell style={{fontWeight: 'bold'}}>{subcategory}</TableCell>
<TableCell style={{fontWeight: 'bold'}}>{count}</TableCell>
</TableRow>
)
)}
</TableBody>
</Table>
</TableContainer>
</AccordionDetails>
</Accordion>
))}
<Grid container justifyContent='space-between' alignItems='center' style={{padding:'14px'}}>
<Typography variant="h6">Total</Typography>
<Typography variant="h6">{stats.count}</Typography>
</Grid>
</CardContent>
</Card>
)
};

const ChartByMaturity = ({stats, count}: {
stats: StatsProjectMaturityBreakdown,
count: number,
}) => {
return (
<Card>
<CardHeader title="By Maturity" />
<CardContent>
<StyledPieChart stats={stats} count={count} />
</CardContent>
</Card>
)
}

interface ProjectsProps {
projectStats: CategoryStats;
maturityStats: StatsProjectMaturityBreakdown;
}

export const Projects = ({ projectStats, maturityStats}: ProjectsProps) => {
return (
<Grid container>
<Grid item> <ChartByMaturity stats={maturityStats} count={projectStats.count}/> </Grid>
<Grid item> <ChartByCategory stats={projectStats}/> </Grid>
</Grid>
)
};
4 changes: 2 additions & 2 deletions plugins/cncf-stats/src/components/StatsPage/StatsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ export const StatsPage = () => {
return (
<StatsLayout>
<StatsLayout.Route path="projects" title="Projects">
<Projects stats={value.cncfMembersSummary} />
<Projects projectStats={value.cncfProjectsSummary} maturityStats={value.cncfProjectMaturitySummary} />
</StatsLayout.Route>
<StatsLayout.Route path="members" title="Members">
<Members stats={value.cncfProjectsSummary} />
<Members stats={value.cncfMembersSummary} />
</StatsLayout.Route>
</StatsLayout>
);
Expand Down
71 changes: 71 additions & 0 deletions plugins/cncf-stats/src/components/Utils/charts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';
import { useDrawingArea } from '@mui/x-charts/hooks';
import { PieChart } from '@mui/x-charts/PieChart';
import { blueberryTwilightPaletteLight } from '@mui/x-charts/colorPalettes';
import {
styled,
Grid,
Table,
TableRow,
TableCell,
TableBody,
} from '@material-ui/core';


const StyledText = styled('text')(({ theme }) => ({
fill: theme.palette.text.primary,
textAnchor: 'middle',
dominantBaseline: 'central',
fontSize: 20,
fontWeight: 'bold',
}));

function PieCenterLabel({ children }: { children: React.ReactNode }): React.ReactElement {
const { width, height, left, top } = useDrawingArea();
return (
<StyledText x={left + width / 2} y={top + height / 2}>
{children}
</StyledText>
);
}

function processPieChartData(data: { [key:string]: number }): { label:string; value:number}[] {
return Object.entries(data).map(([label, value]) => ({ label, value}));
}

interface PieChartProps {
stats: { [key:string]: number };
count: number;
}

export function StyledPieChart({stats, count}: PieChartProps): React.ReactElement {
const data = processPieChartData(stats);
return(
<Grid container alignItems='center' style={{padding: '16px'}}>
<Grid item>
<PieChart
series={[{ data, innerRadius: 120 }]}
width={400}
height={400}
slotProps={{legend: {hidden: true}}}
colors={blueberryTwilightPaletteLight}
>
<PieCenterLabel>Total: {count}</PieCenterLabel>
</PieChart>
</Grid>
<Grid item>
<Table>
<TableBody>
{data.map(({label, value}, index) => (
<TableRow>
minkimcello marked this conversation as resolved.
Show resolved Hide resolved
<TableCell style={{ backgroundColor: blueberryTwilightPaletteLight[index]}} />
<TableCell style={{ fontWeight: 'bold' }}> {label} </TableCell>
<TableCell style={{ fontWeight: 'bold' }}> {value} </TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Grid>
</Grid>
)
}
7 changes: 6 additions & 1 deletion scripts/landscape-yaml-parser/generateStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import {
filterWasm,
} from './filters';
import { LandscapeItem } from 'cncf-common';
import { calculateStats } from './utils/calculateStats';
import {
calculateStats,
calculateProjectMaturityStats,
} from './utils/calculateStats';

const fs = require('fs');

Expand Down Expand Up @@ -37,6 +40,7 @@ function getStats() {
summary: cncfProjectsSummary,
uniqueKeysAnalysis: cncfProjectsKeysAnalysis,
} = calculateStats(cncfProjects);
const cncfProjectMaturitySummary = calculateProjectMaturityStats(cncfProjects);
const {
summary: cncfSpecialSummary,
uniqueKeysAnalysis: cncfSpecialKeysAnalysis,
Expand All @@ -57,6 +61,7 @@ function getStats() {
return {
summary: {
cncfProjectsSummary,
cncfProjectMaturitySummary,
cncfSpecialSummary,
cncfMembersSummary,
cncfWasmSummary,
Expand Down
15 changes: 15 additions & 0 deletions scripts/landscape-yaml-parser/utils/calculateStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
LandscapeItem,
StatsCategoryBreakdown,
StatsSubcategoryBreakdown,
StatsProjectMaturityBreakdown,
} from 'cncf-common';

export const calculateStats = (items: LandscapeItem[]): {
Expand Down Expand Up @@ -48,3 +49,17 @@ export const calculateStats = (items: LandscapeItem[]): {
uniqueKeysAnalysis,
};
}

export const calculateProjectMaturityStats = (items: LandscapeItem[]): StatsProjectMaturityBreakdown => {
const projectMaturityBreakdown = items.reduce((acc, item) => {
if (item.project) {
if (acc.hasOwnProperty(item.project)) {
acc[item.project] += 1;
} else {
acc[item.project] = 1;
}
}
return acc;
}, {} as StatsProjectMaturityBreakdown);
return projectMaturityBreakdown;
}