Skip to content

Commit

Permalink
feat(prs): add filtering and table
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenigneArcher committed Aug 21, 2024
1 parent 34ae300 commit 50552f5
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 32 deletions.
200 changes: 168 additions & 32 deletions notebook/dashboard.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
"from dotenv import load_dotenv\n",
"from github import Github, UnknownObjectException\n",
"import pandas as pd\n",
"from IPython.display import display\n",
"from ipywidgets import widgets, interactive\n",
"import plotly.express as px\n",
"import plotly.graph_objects as go\n",
"import plotly.io as pio\n",
Expand Down Expand Up @@ -367,46 +369,180 @@
"# Open PRs\n",
"pr_data = []\n",
"for repo in df_repos.to_dict('records'):\n",
" draft_prs = 0\n",
" non_draft_prs = 0\n",
" dependabot_prs = 0\n",
"\n",
" for pr in repo['prs']:\n",
" pr_details = repo['_repo'].get_pull(pr.number)\n",
" if pr_details.user.login == 'dependabot[bot]' or pr_details.user.login == 'renovate[bot]':\n",
" dependabot_prs += 1\n",
" elif pr_details.draft:\n",
" draft_prs += 1\n",
" else:\n",
" non_draft_prs += 1\n",
"\n",
" pr_data.append({\n",
" \"repo\": repo['repo'],\n",
" \"Draft\": draft_prs,\n",
" \"Ready for review\": non_draft_prs,\n",
" \"Dependency\": dependabot_prs,\n",
" })\n",
" pr_data.append({\n",
" \"repo\": repo['repo'],\n",
" \"number\": pr.number,\n",
" \"title\": pr_details.title,\n",
" \"author\": pr_details.user.login,\n",
" \"assignees\": [assignee.login for assignee in pr_details.assignees],\n",
" \"labels\": [label.name for label in pr_details.labels],\n",
" \"ready\": not pr_details.draft,\n",
" \"created_at\": pr_details.created_at if hasattr(pr_details, 'created_at') else None,\n",
" \"updated_at\": pr_details.updated_at if hasattr(pr_details, 'updated_at') else None,\n",
" })\n",
"\n",
"df_prs = pd.DataFrame(pr_data)\n",
"df_prs['total_prs'] = df_prs[['Draft', 'Ready for review', 'Dependency']].sum(axis=1)\n",
"\n",
"# Sort by total PRs in descending order\n",
"df_prs = df_prs.sort_values(by='total_prs', ascending=False)\n",
"\n",
"# Visualize data using a stacked bar chart\n",
"fig = px.bar(\n",
" df_prs,\n",
" x='repo',\n",
" y=['Draft', 'Ready for review', 'Dependency'],\n",
" title='Open Pull Requests',\n",
" labels={'value': 'Count', 'variable': 'PR Type'},\n",
" barmode='stack'\n",
"# Helper functions for filtering\n",
"def filter_by_column(df, column, value, exclude=False):\n",
" if value == 'All':\n",
" return df\n",
" if exclude:\n",
" return df[df[column] != value]\n",
" return df[df[column] == value]\n",
"\n",
"def filter_by_list_column(df, column, value, exclude=False):\n",
" if value == 'All':\n",
" return df\n",
" if exclude:\n",
" return df[~df[column].apply(lambda x: value in x)]\n",
" return df[df[column].apply(lambda x: value in x)]\n",
"\n",
"\n",
"# Filter and sort functions\n",
"def filter_prs(\n",
" df,\n",
" repo='All',\n",
" author='All',\n",
" assignee='All',\n",
" label='All',\n",
" ready='All',\n",
" exclude_repo=False,\n",
" exclude_author=False,\n",
" exclude_assignee=False,\n",
" exclude_label=False,\n",
"):\n",
" df = filter_by_column(df, 'repo', repo, exclude_repo)\n",
" df = filter_by_column(df, 'author', author, exclude_author)\n",
" df = filter_by_list_column(df, 'assignees', assignee, exclude_assignee)\n",
" df = filter_by_list_column(df, 'labels', label, exclude_label)\n",
" if ready != 'All':\n",
" df = df[df['ready'] == (ready == 'Ready for Review')]\n",
" return df\n",
"\n",
"# Create dropdown filters\n",
"repo_filter = widgets.Dropdown(\n",
" options=['All'] + df_prs['repo'].unique().tolist(),\n",
" value='All',\n",
" description='Repo:',\n",
")\n",
"fig.update_layout(\n",
" yaxis_title='Count of PRs',\n",
" xaxis_title='Repository',\n",
"\n",
"author_filter = widgets.Dropdown(\n",
" options=['All'] + df_prs['author'].unique().tolist(),\n",
" value='All',\n",
" description='Author:',\n",
")\n",
"fig.show()"
"\n",
"assignee_filter = widgets.Dropdown(\n",
" options=['All'] + list(set(assignee for assignees in df_prs['assignees'] for assignee in assignees)),\n",
" value='All',\n",
" description='Assignee:',\n",
")\n",
"\n",
"label_filter = widgets.Dropdown(\n",
" options=['All'] + list(set(label for labels in df_prs['labels'] for label in labels)),\n",
" value='All',\n",
" description='Label:',\n",
")\n",
"\n",
"ready_filter = widgets.Dropdown(\n",
" options=['All', 'Draft', 'Ready for Review'],\n",
" value='All',\n",
" description='Ready:',\n",
")\n",
"\n",
"# Create exclusion checkboxes\n",
"exclude_repo_checkbox = widgets.Checkbox(\n",
" value=False,\n",
" description='Exclude selected repo',\n",
")\n",
"\n",
"exclude_author_checkbox = widgets.Checkbox(\n",
" value=False,\n",
" description='Exclude selected author',\n",
")\n",
"\n",
"exclude_assignee_checkbox = widgets.Checkbox(\n",
" value=False,\n",
" description='Exclude selected assignee',\n",
")\n",
"\n",
"exclude_label_checkbox = widgets.Checkbox(\n",
" value=False,\n",
" description='Exclude selected label',\n",
")\n",
"\n",
"# Text widget to display total number of PRs\n",
"total_prs_text = widgets.HTML(value=\"\")\n",
"\n",
"def update_visualizations(\n",
" repo,\n",
" author,\n",
" assignee,\n",
" label,\n",
" ready,\n",
" exclude_repo,\n",
" exclude_author,\n",
" exclude_assignee,\n",
" exclude_label,\n",
"):\n",
" filtered_df = filter_prs(\n",
" df_prs,\n",
" repo,\n",
" author,\n",
" assignee,\n",
" label,\n",
" ready,\n",
" exclude_repo,\n",
" exclude_author,\n",
" exclude_assignee,\n",
" exclude_label,\n",
" )\n",
"\n",
" # Update Table\n",
" fig_table = go.Figure(data=[go.Table(\n",
" header=dict(values=list(filtered_df.columns),\n",
" align='left'),\n",
" cells=dict(values=[filtered_df[col] for col in filtered_df.columns],\n",
" align='left'))\n",
" ])\n",
" fig_table.update_layout(height=800, title='Filtered PRs')\n",
"\n",
" # Update Bar Chart\n",
" df_bar = filtered_df.groupby(['repo', 'ready']).size().reset_index(name='count')\n",
" fig_bar = px.bar(\n",
" df_bar,\n",
" x='repo',\n",
" y='count',\n",
" color='ready',\n",
" title='PRs by Repo and Ready Status',\n",
" labels={'count': 'Number of PRs', 'repo': 'Repository', 'ready': 'Ready Status'},\n",
" barmode='stack',\n",
" text='count'\n",
" )\n",
"\n",
" # Update total PRs text\n",
" total_prs_text.value = f\"<b>Filtered PRs: {len(filtered_df)}</b>\"\n",
"\n",
" fig_table.show()\n",
" fig_bar.show()\n",
"\n",
"interactive_visualizations = interactive(\n",
" update_visualizations,\n",
" repo=repo_filter,\n",
" author=author_filter,\n",
" assignee=assignee_filter,\n",
" label=label_filter,\n",
" ready=ready_filter,\n",
" exclude_repo=exclude_repo_checkbox,\n",
" exclude_author=exclude_author_checkbox,\n",
" exclude_assignee=exclude_assignee_checkbox,\n",
" exclude_label=exclude_label_checkbox,\n",
")\n",
"display(total_prs_text, interactive_visualizations)"
]
},
{
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ipython==8.26.0
ipywidgets==8.1.3
notebook==7.2.1
pandas==2.2.2
plotly==5.23.0
Expand Down

0 comments on commit 50552f5

Please sign in to comment.