diff --git a/tools-public/toolpad/pages/OverviewPage/page.yml b/tools-public/toolpad/pages/OverviewPage/page.yml index c7362db..cbb7a2e 100644 --- a/tools-public/toolpad/pages/OverviewPage/page.yml +++ b/tools-public/toolpad/pages/OverviewPage/page.yml @@ -405,6 +405,10 @@ spec: name: text32 props: value: Joy UI NPM KPIs + - component: Text + name: text34 + props: + value: Team's issues activity - component: PageColumn name: pageColumn9 layout: @@ -446,6 +450,19 @@ spec: parameters: {} content: View page variant: text + - component: Button + name: button28 + props: + content: View page + variant: text + onClick: + $$navigationAction: + page: muiTeamIssues + parameters: + repoId: mui/material-ui + benchmarkId: '' + layout: + horizontalAlign: end layout: columnSize: 1 layout: diff --git a/tools-public/toolpad/pages/muiTeamIssues/page.yml b/tools-public/toolpad/pages/muiTeamIssues/page.yml new file mode 100644 index 0000000..b18c602 --- /dev/null +++ b/tools-public/toolpad/pages/muiTeamIssues/page.yml @@ -0,0 +1,79 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/mui/mui-toolpad/v0.6.0/docs/schemas/v1/definitions.json#properties/Page + +apiVersion: v1 +kind: page +spec: + title: muiTeamIssues + display: shell + authorization: + allowAll: true + queries: + - name: getRepoDataQuery + mode: query + query: + function: functions.ts#getTeamIssues + kind: local + parameters: + - name: repo + value: + $$jsExpression: page.parameters.repoId + - name: getBenchmarkDataQuery + mode: query + query: + function: functions.ts#getTeamIssues + kind: local + parameters: + - name: repo + value: + $$jsExpression: page.parameters.benchmarkId + parameters: + - name: repoId + value: mui/material-ui + - name: benchmarkId + value: '' + content: + - component: Text + name: text2 + props: + value: TEAM ISSUES ACITVITY + variant: h3 + - component: Text + name: text + props: + mode: markdown + value: + $$jsExpression: '`This charts shows the team''s issues acitivity stats, in + comparison with a benchmark repository (if provided). Use the + repoId & benchmarkId query params by + specifying the OSS + Insight id. For the most commons used repositories, like + mui/material-ui, mui/base-ui, mui/pigment-css, vercel/next.js you + can directly use the repository name.`' + - component: Text + name: text1 + props: + mode: markdown + value: + $$jsExpression: |- + `MUI repo: ${page.parameters.repoId ?? + 'mui/material-ui'}, Benchmark repo: + ${page.parameters.benchmarkId !== '' ? + page.parameters.benchmarkId : '(not specified)'}` + - component: Chart + name: chart + props: + data: + - label: MUI repo data + kind: line + data: + $$jsExpression: getRepoDataQuery.data + color: '#2E96FF' + xKey: event_month + yKey: issues_activity + - label: Benchmark repo data + kind: line + data: + $$jsExpression: getBenchmarkDataQuery.data + color: '#ff9800' + xKey: event_month + yKey: issues_activity diff --git a/tools-public/toolpad/resources/functions.ts b/tools-public/toolpad/resources/functions.ts index 0617e4a..513e486 100644 --- a/tools-public/toolpad/resources/functions.ts +++ b/tools-public/toolpad/resources/functions.ts @@ -107,6 +107,93 @@ SELECT * FROM final_table return data.data; } +export async function getTeamIssues(repo: string = 'mui/material-ui') { + if (repo === '') { + return []; + } + + const repoMap = { + 'mui/material-ui': 23083156, + 'mui/base-ui': 762289766, + 'mui/pigment-css': 715829513, + 'vercel/next.js': 70107786, + 'radix-ui/primitives': 273499522, + }; + + const repoParam = repoMap[repo] ?? repo; + + const openQuery = ` +WITH maintainers as ( + SELECT + DISTINCT ge.actor_login + FROM + github_events ge + WHERE + ge.repo_id = ${repoParam} + AND ge.type = 'PullRequestEvent' + /* maintainers are defined as the ones that are allowed to merge PRs */ + AND ge.action = 'closed' + AND ge.pr_merged = 1 + AND ge.created_at >= '2016-01-01' +), +issues AS ( + SELECT + DATE_FORMAT(created_at, '%Y-%m-01') AS event_month, + COUNT(*) AS cnt + FROM github_events ge + WHERE + type = 'IssuesEvent' + AND action = 'opened' + AND ge.repo_id = ${repoParam} + AND ge.actor_login in (SELECT actor_login FROM maintainers) + AND event_month >= '2020-01-01' + GROUP BY 1 + ORDER BY 1 +), issue_comments AS ( + SELECT + DATE_FORMAT(created_at, '%Y-%m-01') AS event_month, + COUNT(*) AS cnt + FROM github_events ge + WHERE + type = 'IssueCommentEvent' + AND action = 'created' + AND ge.repo_id = ${repoParam} + AND ge.actor_login in (SELECT actor_login FROM maintainers) + AND event_month >= '2020-01-01' + GROUP BY 1 + ORDER BY 1 +), event_months AS ( + SELECT DISTINCT event_month + FROM ( + SELECT event_month + FROM issues + UNION + SELECT event_month + FROM issue_comments + ) sub +) +SELECT + m.event_month, + IFNULL(i.cnt, 0) + IFNULL(ic.cnt, 0) AS issues_activity +FROM event_months m +LEFT JOIN issues i ON m.event_month = i.event_month +LEFT JOIN issue_comments ic ON m.event_month = ic.event_month +ORDER BY m.event_month ASC + `; + const res = await fetch('https://api.ossinsight.io/q/playground', { + headers: { + 'content-type': 'application/json', + }, + body: JSON.stringify({ sql: openQuery, type: 'repo', id: `${repoParam}` }), + method: 'POST', + }); + if (res.status !== 200) { + throw new Error(`HTTP ${res.status}: ${(await res.text()).slice(0, 500)}`); + } + const data = await res.json(); + return data.data; +} + export async function queryCommitStatuses(repository: string) { if (!process.env.GITHUB_TOKEN) { throw new Error(`Env variable GITHUB_TOKEN not configured`);