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`);