fffiloni commited on
Commit
6479c2d
·
verified ·
1 Parent(s): 06f6c6e

feat(ui): show full name with username in activity header

Browse files
Files changed (1) hide show
  1. app.py +96 -173
app.py CHANGED
@@ -572,67 +572,21 @@ def fetch_all_community_activity(username: str, selected_year: int):
572
 
573
 
574
  # ============================================================
575
- # Contribution grid helpers
576
  # ============================================================
577
- PALETTES = {
578
- "green": ["#0e4429", "#006d32", "#26a641", "#39d353"],
579
- "blue": ["#0a3069", "#0969da", "#54aeff", "#79c0ff"],
580
- "pink": ["#6e1f4d", "#bf3989", "#db61a2", "#f778ba"],
581
- "orange": ["#5f370e", "#a14d00", "#d97706", "#f59e0b"],
582
- "purple": ["#4c1d95", "#6d28d9", "#8b5cf6", "#c4b5fd"],
583
- "teal": ["#0f766e", "#0d9488", "#14b8a6", "#5eead4"],
584
- }
585
-
586
- TOOLTIP_SAFE_COLUMNS = 2
587
-
588
-
589
- def level_from_count(count: int) -> int:
590
- if count <= 0:
591
- return 0
592
- if count == 1:
593
- return 1
594
- if count <= 3:
595
- return 2
596
- if count <= 7:
597
- return 3
598
- return 4
599
-
600
-
601
- def level_color(palette_name: str, level: int) -> str:
602
- if level <= 0:
603
- return "var(--gh-empty-cell)"
604
- palette = PALETTES[palette_name]
605
- return palette[min(level - 1, len(palette) - 1)]
606
-
607
-
608
- def build_daily_count_map(df: pd.DataFrame):
609
- if df.empty:
610
- return {}
611
-
612
- counts = (
613
- df.copy()
614
- .assign(date=pd.to_datetime(df["date"]).dt.date, count=1)
615
- .groupby("date", as_index=False)["count"]
616
- .sum()
617
- )
618
- return {row["date"]: int(row["count"]) for _, row in counts.iterrows()}
619
-
620
-
621
- def get_calendar_bounds(year: int):
622
- start = pd.Timestamp(f"{year}-01-01")
623
- end = pd.Timestamp(f"{year}-12-31")
624
-
625
- grid_start = start - pd.Timedelta(days=start.dayofweek)
626
- grid_end = end + pd.Timedelta(days=(6 - end.dayofweek))
627
-
628
- all_days = pd.date_range(grid_start, grid_end, freq="D")
629
- num_weeks = len(all_days) // 7
630
- return start, end, grid_start, grid_end, all_days, num_weeks
631
 
 
 
 
 
 
 
632
 
633
- def month_positions_for_year(year: int, grid_start: pd.Timestamp):
634
- month_starts = pd.date_range(f"{year}-01-01", f"{year}-12-31", freq="MS")
635
- return [(d.strftime("%b"), int((d - grid_start).days // 7)) for d in month_starts]
636
 
637
 
638
  # ============================================================
@@ -764,37 +718,38 @@ def render_fetching_context_banner(
764
  return render_status_badge(" · ".join(parts))
765
 
766
 
767
- def render_idle_community_banner(
768
- username: str,
769
- selected_year: int,
770
  profile: gr.OAuthProfile | None,
771
  ):
772
  username = (username or "").strip()
773
  selected_year = int(selected_year)
774
  viewer = getattr(profile, "username", None) if profile else None
775
 
 
 
 
 
 
 
776
  if not username:
777
- if viewer:
778
- return render_status_badge(
779
- f"Community activity not fetched yet · Logged in as <b>{html.escape(viewer)}</b> · Fetch your activity or enter another username"
780
- )
781
- return render_status_badge(
782
- "Community activity not fetched yet · Enter a username to get started"
783
- )
784
 
785
  if viewer and username.lower() == viewer.lower():
786
- return render_status_badge(
787
- f"Community activity not fetched yet · Ready to fetch <b>your activity</b> · {selected_year}"
788
- )
 
 
789
 
790
- return render_status_badge(
791
- f"Community activity not fetched yet · Ready to fetch <b>{html.escape(username)}</b> · {selected_year}"
792
- )
793
 
794
 
795
- def render_fetching_community_banner(
796
- username: str,
797
- selected_year: int,
798
  profile: gr.OAuthProfile | None,
799
  ):
800
  username = (username or "").strip()
@@ -802,46 +757,48 @@ def render_fetching_community_banner(
802
  viewer = getattr(profile, "username", None) if profile else None
803
 
804
  if not username:
805
- return render_idle_community_banner(username, selected_year, profile)
 
 
 
 
 
 
806
 
807
  if viewer and username.lower() == viewer.lower():
808
- return render_status_badge(
809
- f"Fetching community activity for <b>your activity</b> · {selected_year}"
810
- )
811
 
812
- return render_status_badge(
813
- f"Fetching community activity for <b>{html.escape(username)}</b> · {selected_year}"
814
- )
815
 
816
 
817
- def render_final_community_banner(
818
  community_state: dict | None,
819
  profile: gr.OAuthProfile | None,
820
  ):
821
- if not community_state or not community_state.get("fetched"):
822
- selected_year = int(community_state.get("selected_year", datetime.now().year)) if community_state else datetime.now().year
823
- username = (community_state.get("username", "") if community_state else "")
824
- return render_idle_community_banner(username, selected_year, profile)
825
 
826
- username = (community_state.get("username") or "").strip()
827
- selected_year = int(community_state.get("selected_year") or datetime.now().year)
828
  viewer = getattr(profile, "username", None) if profile else None
829
 
830
- pr_opened_count = int(community_state["pr_opened"]["count"])
831
- pr_activity_count = int(community_state["pr_activity"]["count"])
832
- thread_opened_count = int(community_state["thread_opened"]["count"])
833
- discussion_activity_count = int(community_state["discussion_activity"]["count"])
834
-
835
- total_events = pr_opened_count + pr_activity_count + thread_opened_count + discussion_activity_count
836
 
837
  if viewer and username.lower() == viewer.lower():
838
- subject = "<b>your activity</b>"
839
  else:
840
- subject = f"<b>{html.escape(username)}</b>"
841
 
842
- return render_status_badge(
843
- f"Viewing community activity for {subject} · {selected_year} · {total_events} total events"
844
- )
845
 
846
 
847
  def render_empty_chart(title: str):
@@ -1154,6 +1111,7 @@ def render_app_state(
1154
  space_df = pd.DataFrame(kind_views["space"]["activity_dates"], columns=["date"])
1155
 
1156
  context_html = render_context_banner(app_state, profile)
 
1157
 
1158
  metrics_html = render_metric_cards(
1159
  total_activity=total_activity,
@@ -1173,7 +1131,7 @@ def render_app_state(
1173
  all_chart_html = render_contrib_chart(
1174
  all_df,
1175
  selected_year,
1176
- f"{username}'s activity",
1177
  palette_name="green",
1178
  subtitle=f"Repo creations + repo contributions in {selected_year}",
1179
  )
@@ -1214,7 +1172,7 @@ def render_app_state(
1214
  logs_text = "\n".join(warnings) if warnings else "Done."
1215
 
1216
  return (
1217
- f"## {username}'s activity in {selected_year}",
1218
  context_html,
1219
  metrics_html,
1220
  all_chart_html,
@@ -1232,48 +1190,29 @@ def prepare_repo_fetch_ui(
1232
  username,
1233
  selected_year,
1234
  current_visibility_mode,
1235
- current_app_state,
1236
  profile: gr.OAuthProfile | None,
1237
  ):
1238
  username = (username or "").strip()
1239
  _ = int(selected_year)
1240
  viewer = getattr(profile, "username", None) if profile else None
1241
 
1242
- context_html = render_fetching_context_banner(username, selected_year, profile)
1243
-
1244
- if not username:
1245
- return (
1246
- render_idle_context_banner("", profile),
1247
- gr.update(visible="hidden", interactive=False),
1248
- )
1249
-
1250
- if not viewer or username.lower() != viewer.lower():
1251
- return (
1252
- context_html,
1253
- gr.update(visible="hidden", interactive=False),
1254
  )
1255
-
1256
- same_existing_user = bool(
1257
- current_app_state
1258
- and current_app_state.get("username")
1259
- and current_app_state["username"].lower() == username.lower()
1260
- and current_app_state.get("can_toggle_visibility")
1261
- )
1262
-
1263
- if same_existing_user:
1264
- return (
1265
- context_html,
1266
- gr.update(
1267
- value=current_visibility_mode or "all",
1268
- visible=True,
1269
- interactive=True,
1270
- ),
1271
  )
1272
 
1273
- return (
1274
- context_html,
1275
- gr.update(),
1276
- )
1277
 
1278
 
1279
  def fetch_and_render_repo_only(
@@ -1287,17 +1226,19 @@ def fetch_and_render_repo_only(
1287
  selected_year = int(selected_year)
1288
 
1289
  app_state = build_app_state(username, selected_year, profile, oauth_token)
1290
- default_visibility = app_state["default_visibility"]
 
 
1291
 
1292
  title_md, context_box, metrics_box, all_chart, model_chart, dataset_chart, space_chart, logs_box = render_app_state(
1293
  app_state,
1294
- default_visibility,
1295
  profile,
1296
  )
1297
 
1298
  visibility_update = gr.update(
1299
  choices=[("All repos", "all"), ("Public only", "public")],
1300
- value=default_visibility,
1301
  visible=True if app_state["can_toggle_visibility"] else "hidden",
1302
  interactive=bool(app_state["can_toggle_visibility"]),
1303
  )
@@ -1337,7 +1278,7 @@ def maybe_reset_community_section(
1337
  state = empty_community_state(selected_year)
1338
  return (
1339
  state,
1340
- render_idle_community_banner(username, selected_year, profile),
1341
  gr.update(value="both", visible="hidden"),
1342
  render_empty_chart("Pull Requests"),
1343
  gr.update(value="both", visible="hidden"),
@@ -1366,7 +1307,7 @@ def maybe_reset_community_section(
1366
  )
1367
  return (
1368
  current_community_state,
1369
- render_final_community_banner(current_community_state, profile),
1370
  gr.update(value=pr_mode, visible=True),
1371
  pr_chart,
1372
  gr.update(value=discussion_mode, visible=True),
@@ -1377,7 +1318,7 @@ def maybe_reset_community_section(
1377
  state = empty_community_state(selected_year)
1378
  return (
1379
  state,
1380
- render_idle_community_banner(username, selected_year, profile),
1381
  gr.update(value="both", visible="hidden"),
1382
  render_empty_chart("Pull Requests"),
1383
  gr.update(value="both", visible="hidden"),
@@ -1386,23 +1327,8 @@ def maybe_reset_community_section(
1386
  )
1387
 
1388
 
1389
- def prepare_community_fetch_ui(
1390
- username,
1391
- selected_year,
1392
- pr_mode,
1393
- discussion_mode,
1394
- profile: gr.OAuthProfile | None,
1395
- ):
1396
- username = (username or "").strip()
1397
- selected_year = int(selected_year)
1398
- pr_mode = pr_mode or "both"
1399
- discussion_mode = discussion_mode or "both"
1400
-
1401
- return (
1402
- render_fetching_community_banner(username, selected_year, profile),
1403
- gr.update(value=pr_mode, visible="hidden"),
1404
- gr.update(value=discussion_mode, visible="hidden"),
1405
- )
1406
 
1407
 
1408
  def fetch_and_render_community(
@@ -1436,7 +1362,7 @@ def fetch_and_render_community(
1436
 
1437
  return (
1438
  state,
1439
- render_final_community_banner(state, profile),
1440
  pr_chart,
1441
  discussion_chart,
1442
  state["logs"],
@@ -1467,7 +1393,7 @@ def rerender_discussions_from_state(community_state, discussion_mode):
1467
  )
1468
 
1469
 
1470
- def hydrate_banners_on_load(
1471
  current_username,
1472
  selected_year,
1473
  profile: gr.OAuthProfile | None,
@@ -1483,11 +1409,9 @@ def hydrate_banners_on_load(
1483
  username_update = gr.update(value=profile_username)
1484
  effective_username = profile_username
1485
 
1486
- return (
1487
- username_update,
1488
- render_idle_context_banner(effective_username, profile),
1489
- render_idle_community_banner(effective_username, selected_year, profile),
1490
- )
1491
 
1492
 
1493
  # ============================================================
@@ -2086,9 +2010,8 @@ with gr.Blocks(title="HF Contributions") as demo:
2086
  gr.Markdown("## Community activity")
2087
 
2088
  fetch_community_button = gr.Button("Fetch community activity", variant="secondary")
2089
-
2090
  community_context_box = gr.HTML(
2091
- render_status_badge("Community activity not fetched yet · Enter a username to get started")
2092
  )
2093
 
2094
  with gr.Column(elem_classes="toggles-container"):
@@ -2175,7 +2098,7 @@ with gr.Blocks(title="HF Contributions") as demo:
2175
  ]
2176
 
2177
  demo.load(
2178
- fn=hydrate_banners_on_load,
2179
  inputs=[username, selected_year],
2180
  outputs=[username, context_box, community_context_box],
2181
  show_progress="hidden",
@@ -2183,7 +2106,7 @@ with gr.Blocks(title="HF Contributions") as demo:
2183
 
2184
  run_button.click(
2185
  fn=prepare_repo_fetch_ui,
2186
- inputs=[username, selected_year, visibility_mode, app_state],
2187
  outputs=[context_box, visibility_mode],
2188
  show_progress="hidden",
2189
  ).then(
@@ -2215,8 +2138,8 @@ with gr.Blocks(title="HF Contributions") as demo:
2215
 
2216
  fetch_community_button.click(
2217
  fn=prepare_community_fetch_ui,
2218
- inputs=[username, selected_year, pr_view_mode, discussion_view_mode],
2219
- outputs=[community_context_box, pr_view_mode, discussion_view_mode],
2220
  show_progress="hidden",
2221
  ).then(
2222
  fn=fetch_and_render_community,
 
572
 
573
 
574
  # ============================================================
575
+ # Name helpers
576
  # ============================================================
577
+ def resolve_display_name(username: str, profile: gr.OAuthProfile | None):
578
+ username = (username or "").strip()
579
+ if not username:
580
+ return ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
 
582
+ if profile is not None:
583
+ profile_username = getattr(profile, "username", None)
584
+ if profile_username and profile_username.lower() == username.lower():
585
+ full_name = getattr(profile, "name", None) or getattr(profile, "full_name", None)
586
+ if isinstance(full_name, str) and full_name.strip():
587
+ return f"{full_name.strip()} (@{username})"
588
 
589
+ return f"@{username}"
 
 
590
 
591
 
592
  # ============================================================
 
718
  return render_status_badge(" · ".join(parts))
719
 
720
 
721
+ def render_community_idle_banner(
722
+ username,
723
+ selected_year,
724
  profile: gr.OAuthProfile | None,
725
  ):
726
  username = (username or "").strip()
727
  selected_year = int(selected_year)
728
  viewer = getattr(profile, "username", None) if profile else None
729
 
730
+ parts = []
731
+ if viewer:
732
+ parts.append(f"Logged in as <b>{html.escape(viewer)}</b>")
733
+ else:
734
+ parts.append("Not logged in")
735
+
736
  if not username:
737
+ parts.append("Enter a username to fetch community activity")
738
+ return render_status_badge(" · ".join(parts))
 
 
 
 
 
739
 
740
  if viewer and username.lower() == viewer.lower():
741
+ parts.append("Fetch your community activity or enter another username")
742
+ parts.append(str(selected_year))
743
+ else:
744
+ parts.append(f"Ready to fetch community activity for <b>{html.escape(username)}</b>")
745
+ parts.append(str(selected_year))
746
 
747
+ return render_status_badge(" · ".join(parts))
 
 
748
 
749
 
750
+ def render_community_fetching_banner(
751
+ username,
752
+ selected_year,
753
  profile: gr.OAuthProfile | None,
754
  ):
755
  username = (username or "").strip()
 
757
  viewer = getattr(profile, "username", None) if profile else None
758
 
759
  if not username:
760
+ return render_community_idle_banner("", selected_year, profile)
761
+
762
+ parts = []
763
+ if viewer:
764
+ parts.append(f"Logged in as <b>{html.escape(viewer)}</b>")
765
+ else:
766
+ parts.append("Not logged in")
767
 
768
  if viewer and username.lower() == viewer.lower():
769
+ parts.append("Fetching <b>your community activity</b>")
770
+ else:
771
+ parts.append(f"Fetching community activity for <b>{html.escape(username)}</b>")
772
 
773
+ parts.append(str(selected_year))
774
+ return render_status_badge(" · ".join(parts))
 
775
 
776
 
777
+ def render_community_loaded_banner(
778
  community_state: dict | None,
779
  profile: gr.OAuthProfile | None,
780
  ):
781
+ if not community_state or not community_state.get("username"):
782
+ year = community_state.get("selected_year", datetime.now().year) if community_state else datetime.now().year
783
+ return render_community_idle_banner("", year, profile)
 
784
 
785
+ username = community_state["username"]
786
+ selected_year = int(community_state["selected_year"])
787
  viewer = getattr(profile, "username", None) if profile else None
788
 
789
+ parts = []
790
+ if viewer:
791
+ parts.append(f"Logged in as <b>{html.escape(viewer)}</b>")
792
+ else:
793
+ parts.append("Not logged in")
 
794
 
795
  if viewer and username.lower() == viewer.lower():
796
+ parts.append("Viewing <b>your community activity</b>")
797
  else:
798
+ parts.append(f"Viewing community activity for <b>{html.escape(username)}</b>")
799
 
800
+ parts.append(str(selected_year))
801
+ return render_status_badge(" · ".join(parts))
 
802
 
803
 
804
  def render_empty_chart(title: str):
 
1111
  space_df = pd.DataFrame(kind_views["space"]["activity_dates"], columns=["date"])
1112
 
1113
  context_html = render_context_banner(app_state, profile)
1114
+ display_name = resolve_display_name(username, profile)
1115
 
1116
  metrics_html = render_metric_cards(
1117
  total_activity=total_activity,
 
1131
  all_chart_html = render_contrib_chart(
1132
  all_df,
1133
  selected_year,
1134
+ f"{display_name}'s activity",
1135
  palette_name="green",
1136
  subtitle=f"Repo creations + repo contributions in {selected_year}",
1137
  )
 
1172
  logs_text = "\n".join(warnings) if warnings else "Done."
1173
 
1174
  return (
1175
+ f"## {display_name}'s activity in {selected_year}",
1176
  context_html,
1177
  metrics_html,
1178
  all_chart_html,
 
1190
  username,
1191
  selected_year,
1192
  current_visibility_mode,
 
1193
  profile: gr.OAuthProfile | None,
1194
  ):
1195
  username = (username or "").strip()
1196
  _ = int(selected_year)
1197
  viewer = getattr(profile, "username", None) if profile else None
1198
 
1199
+ if viewer and username and username.lower() == viewer.lower():
1200
+ value = current_visibility_mode if current_visibility_mode in {"all", "public"} else "all"
1201
+ visibility_update = gr.update(
1202
+ choices=[("All repos", "all"), ("Public only", "public")],
1203
+ value=value,
1204
+ visible=True,
1205
+ interactive=True,
 
 
 
 
 
1206
  )
1207
+ else:
1208
+ visibility_update = gr.update(
1209
+ choices=[("All repos", "all"), ("Public only", "public")],
1210
+ value="public",
1211
+ visible="hidden",
1212
+ interactive=False,
 
 
 
 
 
 
 
 
 
 
1213
  )
1214
 
1215
+ return render_fetching_context_banner(username, selected_year, profile), visibility_update
 
 
 
1216
 
1217
 
1218
  def fetch_and_render_repo_only(
 
1226
  selected_year = int(selected_year)
1227
 
1228
  app_state = build_app_state(username, selected_year, profile, oauth_token)
1229
+
1230
+ requested_visibility = current_visibility_mode if current_visibility_mode in {"all", "public"} else app_state["default_visibility"]
1231
+ final_visibility = requested_visibility if app_state["can_toggle_visibility"] else "public"
1232
 
1233
  title_md, context_box, metrics_box, all_chart, model_chart, dataset_chart, space_chart, logs_box = render_app_state(
1234
  app_state,
1235
+ final_visibility,
1236
  profile,
1237
  )
1238
 
1239
  visibility_update = gr.update(
1240
  choices=[("All repos", "all"), ("Public only", "public")],
1241
+ value=final_visibility,
1242
  visible=True if app_state["can_toggle_visibility"] else "hidden",
1243
  interactive=bool(app_state["can_toggle_visibility"]),
1244
  )
 
1278
  state = empty_community_state(selected_year)
1279
  return (
1280
  state,
1281
+ render_community_idle_banner(username, selected_year, profile),
1282
  gr.update(value="both", visible="hidden"),
1283
  render_empty_chart("Pull Requests"),
1284
  gr.update(value="both", visible="hidden"),
 
1307
  )
1308
  return (
1309
  current_community_state,
1310
+ render_community_loaded_banner(current_community_state, profile),
1311
  gr.update(value=pr_mode, visible=True),
1312
  pr_chart,
1313
  gr.update(value=discussion_mode, visible=True),
 
1318
  state = empty_community_state(selected_year)
1319
  return (
1320
  state,
1321
+ render_community_idle_banner(username, selected_year, profile),
1322
  gr.update(value="both", visible="hidden"),
1323
  render_empty_chart("Pull Requests"),
1324
  gr.update(value="both", visible="hidden"),
 
1327
  )
1328
 
1329
 
1330
+ def prepare_community_fetch_ui(username, selected_year, profile: gr.OAuthProfile | None):
1331
+ return render_community_fetching_banner(username, selected_year, profile)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1332
 
1333
 
1334
  def fetch_and_render_community(
 
1362
 
1363
  return (
1364
  state,
1365
+ render_community_loaded_banner(state, profile),
1366
  pr_chart,
1367
  discussion_chart,
1368
  state["logs"],
 
1393
  )
1394
 
1395
 
1396
+ def hydrate_header_on_load(
1397
  current_username,
1398
  selected_year,
1399
  profile: gr.OAuthProfile | None,
 
1409
  username_update = gr.update(value=profile_username)
1410
  effective_username = profile_username
1411
 
1412
+ repo_context_html = render_idle_context_banner(effective_username, profile)
1413
+ community_context_html = render_community_idle_banner(effective_username, selected_year, profile)
1414
+ return username_update, repo_context_html, community_context_html
 
 
1415
 
1416
 
1417
  # ============================================================
 
2010
  gr.Markdown("## Community activity")
2011
 
2012
  fetch_community_button = gr.Button("Fetch community activity", variant="secondary")
 
2013
  community_context_box = gr.HTML(
2014
+ render_status_badge("Not logged in · Enter a username to fetch community activity")
2015
  )
2016
 
2017
  with gr.Column(elem_classes="toggles-container"):
 
2098
  ]
2099
 
2100
  demo.load(
2101
+ fn=hydrate_header_on_load,
2102
  inputs=[username, selected_year],
2103
  outputs=[username, context_box, community_context_box],
2104
  show_progress="hidden",
 
2106
 
2107
  run_button.click(
2108
  fn=prepare_repo_fetch_ui,
2109
+ inputs=[username, selected_year, visibility_mode],
2110
  outputs=[context_box, visibility_mode],
2111
  show_progress="hidden",
2112
  ).then(
 
2138
 
2139
  fetch_community_button.click(
2140
  fn=prepare_community_fetch_ui,
2141
+ inputs=[username, selected_year],
2142
+ outputs=community_context_box,
2143
  show_progress="hidden",
2144
  ).then(
2145
  fn=fetch_and_render_community,