cleanup
Browse files- app.py +66 -225
- assets/styles.css +198 -5
- graphs/leaderboard.py +7 -4
app.py
CHANGED
|
@@ -6,7 +6,7 @@ import time
|
|
| 6 |
from graphs.leaderboard import (
|
| 7 |
button_style,
|
| 8 |
get_top_n_leaderboard,
|
| 9 |
-
render_table_content
|
| 10 |
)
|
| 11 |
from dash_iconify import DashIconify
|
| 12 |
|
|
@@ -58,9 +58,9 @@ def load_parquet_to_duckdb(con, parquet_url, view_name):
|
|
| 58 |
con = duckdb.connect(database=":memory:", read_only=False)
|
| 59 |
|
| 60 |
# Load parquet files from Hugging Face using DuckDB
|
| 61 |
-
HF_DATASET_ID = "
|
| 62 |
-
hf_parquet_url_1 = "https://huggingface.co/datasets/
|
| 63 |
-
hf_parquet_url_2 = "https://huggingface.co/datasets/
|
| 64 |
|
| 65 |
print(f"Attempting to connect to dataset from Hugging Face Hub: {HF_DATASET_ID}")
|
| 66 |
try:
|
|
@@ -196,71 +196,32 @@ app.layout = dmc.MantineProvider(
|
|
| 196 |
},
|
| 197 |
children=[
|
| 198 |
dcc.Store(id="selected-view", data="all_downloads"),
|
| 199 |
-
dcc.Store(
|
| 200 |
-
id="model-attribution-type", data="uploader"
|
| 201 |
-
),
|
| 202 |
html.Div(
|
| 203 |
[
|
| 204 |
# Header
|
| 205 |
html.Div(
|
| 206 |
[
|
| 207 |
-
# --- Replace title/subtitle with LIVE button and last updated ---
|
| 208 |
html.Div(
|
| 209 |
[
|
| 210 |
html.Span(
|
| 211 |
[
|
| 212 |
html.Span(
|
| 213 |
-
|
| 214 |
-
"display": "inline-block",
|
| 215 |
-
"width": "14px",
|
| 216 |
-
"height": "14px",
|
| 217 |
-
"borderRadius": "50%",
|
| 218 |
-
"backgroundColor": "#AC482A",
|
| 219 |
-
"marginRight": "8px",
|
| 220 |
-
"verticalAlign": "middle",
|
| 221 |
-
"boxShadow": "0 0 6px #AC482A",
|
| 222 |
-
},
|
| 223 |
),
|
| 224 |
html.Span(
|
| 225 |
"LIVE",
|
| 226 |
-
|
| 227 |
-
"backgroundColor": "transparent",
|
| 228 |
-
"color": "#fff",
|
| 229 |
-
"fontWeight": "700",
|
| 230 |
-
"fontSize": "18px",
|
| 231 |
-
"letterSpacing": "1px",
|
| 232 |
-
"verticalAlign": "middle",
|
| 233 |
-
"display": "inline-block",
|
| 234 |
-
},
|
| 235 |
),
|
| 236 |
],
|
| 237 |
-
|
| 238 |
-
"display": "inline-flex",
|
| 239 |
-
"alignItems": "center",
|
| 240 |
-
"marginRight": "16px",
|
| 241 |
-
},
|
| 242 |
),
|
| 243 |
html.Span(
|
| 244 |
f"Last updated: {get_last_updated()}",
|
| 245 |
-
|
| 246 |
-
"backgroundColor": "#1B344D",
|
| 247 |
-
"color": "#FFFFFF",
|
| 248 |
-
"fontWeight": "500",
|
| 249 |
-
"fontSize": "15px",
|
| 250 |
-
"verticalAlign": "middle",
|
| 251 |
-
"display": "inline-block",
|
| 252 |
-
"borderRadius": "8px",
|
| 253 |
-
"padding": "4px 14px",
|
| 254 |
-
"boxShadow": "0 1px 4px rgba(8,32,48,0.10)",
|
| 255 |
-
"marginLeft": "0px",
|
| 256 |
-
},
|
| 257 |
),
|
| 258 |
],
|
| 259 |
-
|
| 260 |
-
"display": "flex",
|
| 261 |
-
"alignItems": "center",
|
| 262 |
-
"gap": "12px",
|
| 263 |
-
},
|
| 264 |
),
|
| 265 |
html.Div(
|
| 266 |
[
|
|
@@ -268,36 +229,19 @@ app.layout = dmc.MantineProvider(
|
|
| 268 |
children=[
|
| 269 |
html.Img(
|
| 270 |
src="assets/images/dpi.svg",
|
| 271 |
-
|
| 272 |
-
"height": "28px",
|
| 273 |
-
"verticalAlign": "middle",
|
| 274 |
-
"paddingRight": "8px",
|
| 275 |
-
},
|
| 276 |
),
|
| 277 |
"Data Provenance Initiative",
|
| 278 |
],
|
| 279 |
href="https://www.dataprovenance.org/",
|
| 280 |
target="_blank",
|
| 281 |
className="no-bg-link header-link",
|
| 282 |
-
style={
|
| 283 |
-
"display": "inline-block",
|
| 284 |
-
"padding": "6px 14px",
|
| 285 |
-
"fontSize": 13,
|
| 286 |
-
"color": "#FFFFFF", # white on dark header
|
| 287 |
-
"borderRadius": "18px",
|
| 288 |
-
"fontWeight": "700",
|
| 289 |
-
"textDecoration": "none",
|
| 290 |
-
"marginRight": "12px",
|
| 291 |
-
},
|
| 292 |
),
|
| 293 |
html.A(
|
| 294 |
children=[
|
| 295 |
html.Img(
|
| 296 |
src="assets/images/hf.svg",
|
| 297 |
-
|
| 298 |
-
"height": "30px",
|
| 299 |
-
"verticalAlign": "middle",
|
| 300 |
-
},
|
| 301 |
),
|
| 302 |
html.Span(
|
| 303 |
"Hugging Face",
|
|
@@ -307,15 +251,6 @@ app.layout = dmc.MantineProvider(
|
|
| 307 |
href="https://huggingface.co/",
|
| 308 |
target="_blank",
|
| 309 |
className="no-bg-link header-link",
|
| 310 |
-
style={
|
| 311 |
-
"display": "inline-flex",
|
| 312 |
-
"padding": "6px 14px",
|
| 313 |
-
"alignItems": "center",
|
| 314 |
-
"color": "#FFFFFF",
|
| 315 |
-
"borderRadius": "18px",
|
| 316 |
-
"textDecoration": "none",
|
| 317 |
-
"marginRight": "12px",
|
| 318 |
-
},
|
| 319 |
),
|
| 320 |
html.A(
|
| 321 |
children=[
|
|
@@ -327,21 +262,9 @@ app.layout = dmc.MantineProvider(
|
|
| 327 |
href="https://www.google.com/",
|
| 328 |
target="_blank",
|
| 329 |
className="no-bg-link header-link paper-link",
|
| 330 |
-
style={
|
| 331 |
-
"display": "inline-flex",
|
| 332 |
-
"alignItems": "center",
|
| 333 |
-
"padding": "6px 12px",
|
| 334 |
-
"fontSize": 14,
|
| 335 |
-
"margin": "0 auto",
|
| 336 |
-
"backgroundColor": "#AC482A",
|
| 337 |
-
"color": "#FFFFFF",
|
| 338 |
-
"borderRadius": "5px",
|
| 339 |
-
"textDecoration": "none",
|
| 340 |
-
"fontWeight": "700",
|
| 341 |
-
},
|
| 342 |
),
|
| 343 |
],
|
| 344 |
-
|
| 345 |
),
|
| 346 |
],
|
| 347 |
style={
|
|
@@ -354,7 +277,6 @@ app.layout = dmc.MantineProvider(
|
|
| 354 |
},
|
| 355 |
className="responsive-header", # <-- add class
|
| 356 |
),
|
| 357 |
-
# Title row with "live" button
|
| 358 |
html.Div(
|
| 359 |
[
|
| 360 |
html.Span(
|
|
@@ -378,13 +300,12 @@ app.layout = dmc.MantineProvider(
|
|
| 378 |
},
|
| 379 |
className="responsive-title-row", # <-- add class
|
| 380 |
),
|
| 381 |
-
# Intro / description below header (kept but styled to match layout)
|
| 382 |
html.Div(
|
| 383 |
children=[
|
| 384 |
"This leaderboard assesses concentrations of power in the open model ecosystem through ranking user downloads across three groups: countries, developers, and models. Explore how user downloads of models are distributed among these groups and identify key players shaping the open model ecosystem on Hugging Face. This dashboard accompanies the paper titled ",
|
| 385 |
html.A(
|
| 386 |
"Economies of Open Intelligence: Tracing Power & Participation in the Model Ecosystem.",
|
| 387 |
-
href="https://www.google.com/",
|
| 388 |
target="_blank",
|
| 389 |
style={
|
| 390 |
"color": "#AC482A",
|
|
@@ -403,7 +324,6 @@ app.layout = dmc.MantineProvider(
|
|
| 403 |
},
|
| 404 |
className="responsive-intro", # <-- add class
|
| 405 |
),
|
| 406 |
-
# Main content (filters + tabs)
|
| 407 |
html.Div(
|
| 408 |
children=[
|
| 409 |
html.Div(
|
|
@@ -442,18 +362,9 @@ app.layout = dmc.MantineProvider(
|
|
| 442 |
],
|
| 443 |
),
|
| 444 |
],
|
| 445 |
-
|
| 446 |
-
"display": "inline-flex",
|
| 447 |
-
"alignItems": "center",
|
| 448 |
-
},
|
| 449 |
),
|
| 450 |
-
|
| 451 |
-
"fontWeight": "700",
|
| 452 |
-
"marginBottom": 8,
|
| 453 |
-
"fontSize": 14,
|
| 454 |
-
"display": "flex",
|
| 455 |
-
"alignItems": "center",
|
| 456 |
-
},
|
| 457 |
),
|
| 458 |
html.Div(
|
| 459 |
[
|
|
@@ -463,42 +374,23 @@ app.layout = dmc.MantineProvider(
|
|
| 463 |
color="#AC482A",
|
| 464 |
transitionDuration=200,
|
| 465 |
data=[
|
| 466 |
-
{
|
| 467 |
-
|
| 468 |
-
"label": "All Downloads",
|
| 469 |
-
},
|
| 470 |
-
{
|
| 471 |
-
"value": "filtered-downloads",
|
| 472 |
-
"label": html.Span(
|
| 473 |
-
[
|
| 474 |
-
"Filtered Downloads",
|
| 475 |
-
]
|
| 476 |
-
),
|
| 477 |
-
},
|
| 478 |
],
|
| 479 |
mb=10,
|
| 480 |
),
|
| 481 |
],
|
| 482 |
-
|
| 483 |
),
|
| 484 |
html.Div(
|
| 485 |
"Choose whether to count all downloads, or only downloads up to one year from model creation.",
|
| 486 |
-
|
| 487 |
-
"fontSize": 13,
|
| 488 |
-
"color": "#555",
|
| 489 |
-
"marginBottom": "12px",
|
| 490 |
-
},
|
| 491 |
),
|
| 492 |
-
# New segmented control below the first one
|
| 493 |
html.Div(
|
| 494 |
[
|
| 495 |
html.Div(
|
| 496 |
"Model Attribution",
|
| 497 |
-
|
| 498 |
-
"fontWeight": "700",
|
| 499 |
-
"marginBottom": 8,
|
| 500 |
-
"fontSize": 14,
|
| 501 |
-
},
|
| 502 |
),
|
| 503 |
dmc.SegmentedControl(
|
| 504 |
id="model-attribution-segmented",
|
|
@@ -506,59 +398,36 @@ app.layout = dmc.MantineProvider(
|
|
| 506 |
color="#AC482A",
|
| 507 |
transitionDuration=200,
|
| 508 |
data=[
|
| 509 |
-
{
|
| 510 |
-
|
| 511 |
-
"label": "Model Uploader",
|
| 512 |
-
},
|
| 513 |
-
{
|
| 514 |
-
"value": "original_creator",
|
| 515 |
-
"label": "Original Model Creator",
|
| 516 |
-
},
|
| 517 |
],
|
| 518 |
mb=10,
|
| 519 |
),
|
| 520 |
html.Div(
|
| 521 |
"Toggle between having downloads attributed to the account that uploaded the model, or the account that uploaded the model that this was originally derived from.",
|
| 522 |
-
|
| 523 |
-
"fontSize": 13,
|
| 524 |
-
"color": "#555",
|
| 525 |
-
"marginBottom": "12px",
|
| 526 |
-
},
|
| 527 |
),
|
| 528 |
],
|
| 529 |
style={"marginTop": "10px"},
|
| 530 |
),
|
| 531 |
html.Span(
|
| 532 |
id="global-toggle-status",
|
| 533 |
-
|
| 534 |
-
"marginLeft": "8px",
|
| 535 |
-
"display": "inline-block",
|
| 536 |
-
"marginTop": 6,
|
| 537 |
-
},
|
| 538 |
),
|
| 539 |
],
|
| 540 |
-
|
| 541 |
),
|
| 542 |
html.Div(
|
| 543 |
[
|
| 544 |
html.Div(
|
| 545 |
"Download Date Range",
|
| 546 |
-
|
| 547 |
-
"fontWeight": "700",
|
| 548 |
-
"marginBottom": 8,
|
| 549 |
-
"fontSize": 14,
|
| 550 |
-
},
|
| 551 |
),
|
| 552 |
time_slider,
|
| 553 |
html.Div(
|
| 554 |
"Adjust the time range to filter leaderboard results by when models were downloaded by users.",
|
| 555 |
-
|
| 556 |
-
"fontSize": 13,
|
| 557 |
-
"color": "#555",
|
| 558 |
-
"marginTop": "32px", # increased from 24px
|
| 559 |
-
},
|
| 560 |
),
|
| 561 |
-
# Tip section
|
| 562 |
html.Div(
|
| 563 |
[
|
| 564 |
html.Div(
|
|
@@ -574,77 +443,40 @@ app.layout = dmc.MantineProvider(
|
|
| 574 |
),
|
| 575 |
html.Span("Tip"),
|
| 576 |
],
|
| 577 |
-
|
| 578 |
-
"fontWeight": "700",
|
| 579 |
-
"fontSize": 15,
|
| 580 |
-
"marginBottom": "6px",
|
| 581 |
-
"color": "#082030",
|
| 582 |
-
"display": "flex",
|
| 583 |
-
"alignItems": "center",
|
| 584 |
-
},
|
| 585 |
),
|
| 586 |
html.Div(
|
| 587 |
[
|
| 588 |
"Try switching between ",
|
| 589 |
html.Span(
|
| 590 |
"All Downloads",
|
| 591 |
-
|
| 592 |
-
"fontWeight": "600",
|
| 593 |
-
"color": "#AC482A",
|
| 594 |
-
},
|
| 595 |
),
|
| 596 |
" and ",
|
| 597 |
html.Span(
|
| 598 |
"Filtered Downloads",
|
| 599 |
-
|
| 600 |
-
"fontWeight": "600",
|
| 601 |
-
"color": "#AC482A",
|
| 602 |
-
},
|
| 603 |
),
|
| 604 |
" to compare net popularity (but many duplicate, unused downloads) versus more immediate interest as models are released. ",
|
| 605 |
"You can also toggle between ",
|
| 606 |
html.Span(
|
| 607 |
"Model Uploader",
|
| 608 |
-
|
| 609 |
-
"fontWeight": "600",
|
| 610 |
-
"color": "#AC482A",
|
| 611 |
-
},
|
| 612 |
),
|
| 613 |
" and ",
|
| 614 |
html.Span(
|
| 615 |
"Original Model Creator",
|
| 616 |
-
|
| 617 |
-
"fontWeight": "600",
|
| 618 |
-
"color": "#AC482A",
|
| 619 |
-
},
|
| 620 |
),
|
| 621 |
" to see how attribution affects perceived popularity.",
|
| 622 |
],
|
| 623 |
-
|
| 624 |
-
"fontSize": 13,
|
| 625 |
-
"color": "#082030",
|
| 626 |
-
"lineHeight": "1.6",
|
| 627 |
-
},
|
| 628 |
),
|
| 629 |
],
|
| 630 |
-
|
| 631 |
-
"backgroundColor": "#F5ECE6",
|
| 632 |
-
"borderRadius": "14px",
|
| 633 |
-
"padding": "18px 20px",
|
| 634 |
-
"marginTop": "28px",
|
| 635 |
-
"boxShadow": "0 1px 4px rgba(8,32,48,0.04)",
|
| 636 |
-
"border": "1px solid #f0e3d6",
|
| 637 |
-
},
|
| 638 |
),
|
| 639 |
],
|
| 640 |
-
|
| 641 |
-
"flex": 2,
|
| 642 |
-
"minWidth": "320px",
|
| 643 |
-
"display": "flex",
|
| 644 |
-
"flexDirection": "column",
|
| 645 |
-
"justifyContent": "center",
|
| 646 |
-
"height": "100%",
|
| 647 |
-
},
|
| 648 |
),
|
| 649 |
],
|
| 650 |
style={
|
|
@@ -684,13 +516,14 @@ app.layout = dmc.MantineProvider(
|
|
| 684 |
},
|
| 685 |
children=[
|
| 686 |
html.Div(
|
| 687 |
-
children=
|
| 688 |
-
|
| 689 |
-
"
|
| 690 |
-
"
|
| 691 |
-
"
|
| 692 |
-
"
|
| 693 |
-
|
|
|
|
| 694 |
),
|
| 695 |
html.Div(
|
| 696 |
dcc.Loading(
|
|
@@ -728,13 +561,16 @@ app.layout = dmc.MantineProvider(
|
|
| 728 |
},
|
| 729 |
children=[
|
| 730 |
html.Div(
|
| 731 |
-
children=
|
| 732 |
-
|
| 733 |
-
"
|
| 734 |
-
"
|
| 735 |
-
"
|
| 736 |
-
"
|
| 737 |
-
|
|
|
|
|
|
|
|
|
|
| 738 |
),
|
| 739 |
html.Div(
|
| 740 |
dcc.Loading(
|
|
@@ -774,13 +610,18 @@ app.layout = dmc.MantineProvider(
|
|
| 774 |
},
|
| 775 |
children=[
|
| 776 |
html.Div(
|
| 777 |
-
children=
|
| 778 |
-
|
| 779 |
-
"
|
| 780 |
-
"
|
| 781 |
-
"
|
| 782 |
-
"
|
| 783 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 784 |
),
|
| 785 |
html.Div(
|
| 786 |
dcc.Loading(
|
|
|
|
| 6 |
from graphs.leaderboard import (
|
| 7 |
button_style,
|
| 8 |
get_top_n_leaderboard,
|
| 9 |
+
render_table_content
|
| 10 |
)
|
| 11 |
from dash_iconify import DashIconify
|
| 12 |
|
|
|
|
| 58 |
con = duckdb.connect(database=":memory:", read_only=False)
|
| 59 |
|
| 60 |
# Load parquet files from Hugging Face using DuckDB
|
| 61 |
+
HF_DATASET_ID = "mmpr/open_model_evolution_data"
|
| 62 |
+
hf_parquet_url_1 = "https://huggingface.co/datasets/mmpr/open_model_evolution_data/resolve/main/all_downloads_with_annotations.parquet"
|
| 63 |
+
hf_parquet_url_2 = "https://huggingface.co/datasets/mmpr/open_model_evolution_data/resolve/main/one_year_rolling.parquet"
|
| 64 |
|
| 65 |
print(f"Attempting to connect to dataset from Hugging Face Hub: {HF_DATASET_ID}")
|
| 66 |
try:
|
|
|
|
| 196 |
},
|
| 197 |
children=[
|
| 198 |
dcc.Store(id="selected-view", data="all_downloads"),
|
| 199 |
+
dcc.Store(id="model-attribution-type", data="uploader"),
|
|
|
|
|
|
|
| 200 |
html.Div(
|
| 201 |
[
|
| 202 |
# Header
|
| 203 |
html.Div(
|
| 204 |
[
|
|
|
|
| 205 |
html.Div(
|
| 206 |
[
|
| 207 |
html.Span(
|
| 208 |
[
|
| 209 |
html.Span(
|
| 210 |
+
className="live-dot",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
),
|
| 212 |
html.Span(
|
| 213 |
"LIVE",
|
| 214 |
+
className="live-label",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
),
|
| 216 |
],
|
| 217 |
+
className="live-row",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
),
|
| 219 |
html.Span(
|
| 220 |
f"Last updated: {get_last_updated()}",
|
| 221 |
+
className="last-updated",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
),
|
| 223 |
],
|
| 224 |
+
className="header-status-row",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
),
|
| 226 |
html.Div(
|
| 227 |
[
|
|
|
|
| 229 |
children=[
|
| 230 |
html.Img(
|
| 231 |
src="assets/images/dpi.svg",
|
| 232 |
+
className="header-logo-img",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
),
|
| 234 |
"Data Provenance Initiative",
|
| 235 |
],
|
| 236 |
href="https://www.dataprovenance.org/",
|
| 237 |
target="_blank",
|
| 238 |
className="no-bg-link header-link",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
),
|
| 240 |
html.A(
|
| 241 |
children=[
|
| 242 |
html.Img(
|
| 243 |
src="assets/images/hf.svg",
|
| 244 |
+
className="header-logo-img",
|
|
|
|
|
|
|
|
|
|
| 245 |
),
|
| 246 |
html.Span(
|
| 247 |
"Hugging Face",
|
|
|
|
| 251 |
href="https://huggingface.co/",
|
| 252 |
target="_blank",
|
| 253 |
className="no-bg-link header-link",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
),
|
| 255 |
html.A(
|
| 256 |
children=[
|
|
|
|
| 262 |
href="https://www.google.com/",
|
| 263 |
target="_blank",
|
| 264 |
className="no-bg-link header-link paper-link",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 265 |
),
|
| 266 |
],
|
| 267 |
+
className="header-links-row",
|
| 268 |
),
|
| 269 |
],
|
| 270 |
style={
|
|
|
|
| 277 |
},
|
| 278 |
className="responsive-header", # <-- add class
|
| 279 |
),
|
|
|
|
| 280 |
html.Div(
|
| 281 |
[
|
| 282 |
html.Span(
|
|
|
|
| 300 |
},
|
| 301 |
className="responsive-title-row", # <-- add class
|
| 302 |
),
|
|
|
|
| 303 |
html.Div(
|
| 304 |
children=[
|
| 305 |
"This leaderboard assesses concentrations of power in the open model ecosystem through ranking user downloads across three groups: countries, developers, and models. Explore how user downloads of models are distributed among these groups and identify key players shaping the open model ecosystem on Hugging Face. This dashboard accompanies the paper titled ",
|
| 306 |
html.A(
|
| 307 |
"Economies of Open Intelligence: Tracing Power & Participation in the Model Ecosystem.",
|
| 308 |
+
href="https://www.google.com/",
|
| 309 |
target="_blank",
|
| 310 |
style={
|
| 311 |
"color": "#AC482A",
|
|
|
|
| 324 |
},
|
| 325 |
className="responsive-intro", # <-- add class
|
| 326 |
),
|
|
|
|
| 327 |
html.Div(
|
| 328 |
children=[
|
| 329 |
html.Div(
|
|
|
|
| 362 |
],
|
| 363 |
),
|
| 364 |
],
|
| 365 |
+
className="filter-label-row",
|
|
|
|
|
|
|
|
|
|
| 366 |
),
|
| 367 |
+
className="filter-label-container",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
),
|
| 369 |
html.Div(
|
| 370 |
[
|
|
|
|
| 374 |
color="#AC482A",
|
| 375 |
transitionDuration=200,
|
| 376 |
data=[
|
| 377 |
+
{"value": "all-downloads", "label": "All Downloads"},
|
| 378 |
+
{"value": "filtered-downloads", "label": html.Span(["Filtered Downloads"])},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 379 |
],
|
| 380 |
mb=10,
|
| 381 |
),
|
| 382 |
],
|
| 383 |
+
className="filter-segmented-row",
|
| 384 |
),
|
| 385 |
html.Div(
|
| 386 |
"Choose whether to count all downloads, or only downloads up to one year from model creation.",
|
| 387 |
+
className="filter-description",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 388 |
),
|
|
|
|
| 389 |
html.Div(
|
| 390 |
[
|
| 391 |
html.Div(
|
| 392 |
"Model Attribution",
|
| 393 |
+
className="filter-label",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 394 |
),
|
| 395 |
dmc.SegmentedControl(
|
| 396 |
id="model-attribution-segmented",
|
|
|
|
| 398 |
color="#AC482A",
|
| 399 |
transitionDuration=200,
|
| 400 |
data=[
|
| 401 |
+
{"value": "uploader", "label": "Model Uploader"},
|
| 402 |
+
{"value": "original_creator", "label": "Original Model Creator"},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 403 |
],
|
| 404 |
mb=10,
|
| 405 |
),
|
| 406 |
html.Div(
|
| 407 |
"Toggle between having downloads attributed to the account that uploaded the model, or the account that uploaded the model that this was originally derived from.",
|
| 408 |
+
className="filter-description",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
),
|
| 410 |
],
|
| 411 |
style={"marginTop": "10px"},
|
| 412 |
),
|
| 413 |
html.Span(
|
| 414 |
id="global-toggle-status",
|
| 415 |
+
className="global-toggle-status",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
),
|
| 417 |
],
|
| 418 |
+
className="main-content-left",
|
| 419 |
),
|
| 420 |
html.Div(
|
| 421 |
[
|
| 422 |
html.Div(
|
| 423 |
"Download Date Range",
|
| 424 |
+
className="filter-label",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 425 |
),
|
| 426 |
time_slider,
|
| 427 |
html.Div(
|
| 428 |
"Adjust the time range to filter leaderboard results by when models were downloaded by users.",
|
| 429 |
+
className="filter-description filter-description-margin",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
),
|
|
|
|
| 431 |
html.Div(
|
| 432 |
[
|
| 433 |
html.Div(
|
|
|
|
| 443 |
),
|
| 444 |
html.Span("Tip"),
|
| 445 |
],
|
| 446 |
+
className="tip-title",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
),
|
| 448 |
html.Div(
|
| 449 |
[
|
| 450 |
"Try switching between ",
|
| 451 |
html.Span(
|
| 452 |
"All Downloads",
|
| 453 |
+
className="tip-highlight",
|
|
|
|
|
|
|
|
|
|
| 454 |
),
|
| 455 |
" and ",
|
| 456 |
html.Span(
|
| 457 |
"Filtered Downloads",
|
| 458 |
+
className="tip-highlight",
|
|
|
|
|
|
|
|
|
|
| 459 |
),
|
| 460 |
" to compare net popularity (but many duplicate, unused downloads) versus more immediate interest as models are released. ",
|
| 461 |
"You can also toggle between ",
|
| 462 |
html.Span(
|
| 463 |
"Model Uploader",
|
| 464 |
+
className="tip-highlight",
|
|
|
|
|
|
|
|
|
|
| 465 |
),
|
| 466 |
" and ",
|
| 467 |
html.Span(
|
| 468 |
"Original Model Creator",
|
| 469 |
+
className="tip-highlight",
|
|
|
|
|
|
|
|
|
|
| 470 |
),
|
| 471 |
" to see how attribution affects perceived popularity.",
|
| 472 |
],
|
| 473 |
+
className="tip-description",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 474 |
),
|
| 475 |
],
|
| 476 |
+
className="tip-section",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 477 |
),
|
| 478 |
],
|
| 479 |
+
className="main-content-right",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
),
|
| 481 |
],
|
| 482 |
style={
|
|
|
|
| 516 |
},
|
| 517 |
children=[
|
| 518 |
html.Div(
|
| 519 |
+
children=[
|
| 520 |
+
"The country leaderboard shows how downloads are distributed across different nations, highlighting which countries are leading in model usage and adoption. The metadata includes the ",
|
| 521 |
+
html.Span("country", className="meta-var"),
|
| 522 |
+
" and ",
|
| 523 |
+
html.Span("number of user downloads", className="meta-var"),
|
| 524 |
+
".",
|
| 525 |
+
],
|
| 526 |
+
className="tab-description",
|
| 527 |
),
|
| 528 |
html.Div(
|
| 529 |
dcc.Loading(
|
|
|
|
| 561 |
},
|
| 562 |
children=[
|
| 563 |
html.Div(
|
| 564 |
+
children=[
|
| 565 |
+
"The developer leaderboard highlights the most influential model creators on Hugging Face, showcasing which developers have garnered the highest download counts for their models. The metadata includes the ",
|
| 566 |
+
html.Span("developer name", className="meta-var"),
|
| 567 |
+
", ",
|
| 568 |
+
html.Span("number of user downloads", className="meta-var"),
|
| 569 |
+
", and the ",
|
| 570 |
+
html.Span("country", className="meta-var"),
|
| 571 |
+
".",
|
| 572 |
+
],
|
| 573 |
+
className="tab-description",
|
| 574 |
),
|
| 575 |
html.Div(
|
| 576 |
dcc.Loading(
|
|
|
|
| 610 |
},
|
| 611 |
children=[
|
| 612 |
html.Div(
|
| 613 |
+
children=[
|
| 614 |
+
"The model leaderboard ranks individual models based on their download counts, revealing which models are most popular among users on Hugging Face. The metadata includes the ",
|
| 615 |
+
html.Span("model name", className="meta-var"),
|
| 616 |
+
", ",
|
| 617 |
+
html.Span("number of user downloads", className="meta-var"),
|
| 618 |
+
", the ",
|
| 619 |
+
html.Span("developer", className="meta-var"),
|
| 620 |
+
", and ",
|
| 621 |
+
html.Span("modality", className="meta-var"),
|
| 622 |
+
" (the input and output types of the model).",
|
| 623 |
+
],
|
| 624 |
+
className="tab-description",
|
| 625 |
),
|
| 626 |
html.Div(
|
| 627 |
dcc.Loading(
|
assets/styles.css
CHANGED
|
@@ -51,15 +51,21 @@
|
|
| 51 |
.paper-link {
|
| 52 |
position: relative; /* needed for positioning the arrow */
|
| 53 |
overflow: visible;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
background-color: #AC482A !important; /* restore previous button color */
|
| 55 |
color: #FFFFFF !important;
|
| 56 |
-
|
| 57 |
-
border-radius: 5px;
|
| 58 |
-
font-weight: 700;
|
| 59 |
-
display: inline-flex;
|
| 60 |
-
align-items: center;
|
| 61 |
text-decoration: none !important;
|
|
|
|
| 62 |
transition: transform var(--default-transition-duration, .15s) var(--default-transition-timing-function, cubic-bezier(.4,0,.2,1)), background-color var(--default-transition-duration, .15s);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
}
|
| 64 |
|
| 65 |
/* Small arrow placed inline to the right of the text */
|
|
@@ -124,6 +130,169 @@ button[id^="download-"]:focus {
|
|
| 124 |
outline: none;
|
| 125 |
}
|
| 126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
@media (max-width: 1150px) {
|
| 128 |
.responsive-main-content {
|
| 129 |
flex-direction: column !important;
|
|
@@ -140,6 +309,30 @@ button[id^="download-"]:focus {
|
|
| 140 |
flex-direction: column !important;
|
| 141 |
gap: 12px !important;
|
| 142 |
padding: 12px !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
}
|
| 144 |
.responsive-title-row {
|
| 145 |
margin-left: 0 !important;
|
|
|
|
| 51 |
.paper-link {
|
| 52 |
position: relative; /* needed for positioning the arrow */
|
| 53 |
overflow: visible;
|
| 54 |
+
display: inline-flex !important;
|
| 55 |
+
align-items: center !important;
|
| 56 |
+
padding: 6px 12px !important;
|
| 57 |
+
font-size: 14px !important;
|
| 58 |
+
margin: 0 auto !important;
|
| 59 |
background-color: #AC482A !important; /* restore previous button color */
|
| 60 |
color: #FFFFFF !important;
|
| 61 |
+
border-radius: 5px !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
text-decoration: none !important;
|
| 63 |
+
font-weight: 700 !important;
|
| 64 |
transition: transform var(--default-transition-duration, .15s) var(--default-transition-timing-function, cubic-bezier(.4,0,.2,1)), background-color var(--default-transition-duration, .15s);
|
| 65 |
+
max-width: 220px;
|
| 66 |
+
white-space: nowrap;
|
| 67 |
+
overflow: hidden;
|
| 68 |
+
text-overflow: ellipsis;
|
| 69 |
}
|
| 70 |
|
| 71 |
/* Small arrow placed inline to the right of the text */
|
|
|
|
| 130 |
outline: none;
|
| 131 |
}
|
| 132 |
|
| 133 |
+
.chip-hover-darken {
|
| 134 |
+
transition: background-color 0.15s;
|
| 135 |
+
}
|
| 136 |
+
.chip-hover-darken:hover,
|
| 137 |
+
.chip-hover-darken:focus {
|
| 138 |
+
background-color: #e1f2fd !important; /* slightly darker than #F0F0F0 */
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/* Header status row */
|
| 142 |
+
.header-status-row {
|
| 143 |
+
display: flex;
|
| 144 |
+
align-items: center;
|
| 145 |
+
gap: 12px;
|
| 146 |
+
}
|
| 147 |
+
.live-row {
|
| 148 |
+
display: inline-flex;
|
| 149 |
+
align-items: center;
|
| 150 |
+
margin-right: 16px;
|
| 151 |
+
}
|
| 152 |
+
.live-dot {
|
| 153 |
+
display: inline-block;
|
| 154 |
+
width: 14px;
|
| 155 |
+
height: 14px;
|
| 156 |
+
border-radius: 50%;
|
| 157 |
+
background-color: #AC482A;
|
| 158 |
+
margin-right: 8px;
|
| 159 |
+
vertical-align: middle;
|
| 160 |
+
box-shadow: 0 0 6px #AC482A;
|
| 161 |
+
}
|
| 162 |
+
.live-label {
|
| 163 |
+
background-color: transparent;
|
| 164 |
+
color: #fff;
|
| 165 |
+
font-weight: 700;
|
| 166 |
+
font-size: 18px;
|
| 167 |
+
letter-spacing: 1px;
|
| 168 |
+
vertical-align: middle;
|
| 169 |
+
display: inline-block;
|
| 170 |
+
}
|
| 171 |
+
.last-updated {
|
| 172 |
+
background-color: #1B344D;
|
| 173 |
+
color: #FFFFFF;
|
| 174 |
+
font-weight: 500;
|
| 175 |
+
font-size: 15px;
|
| 176 |
+
vertical-align: middle;
|
| 177 |
+
display: inline-block;
|
| 178 |
+
border-radius: 8px;
|
| 179 |
+
padding: 4px 14px;
|
| 180 |
+
box-shadow: 0 1px 4px rgba(8,32,48,0.10);
|
| 181 |
+
margin-left: 0px;
|
| 182 |
+
}
|
| 183 |
+
.header-links-row {
|
| 184 |
+
display: flex;
|
| 185 |
+
align-items: center;
|
| 186 |
+
}
|
| 187 |
+
.header-link {
|
| 188 |
+
display: inline-flex !important;
|
| 189 |
+
padding: 6px 14px !important;
|
| 190 |
+
font-size: 13px !important;
|
| 191 |
+
color: #FFFFFF !important;
|
| 192 |
+
border-radius: 18px !important;
|
| 193 |
+
font-weight: 700 !important;
|
| 194 |
+
text-decoration: none !important;
|
| 195 |
+
margin-right: 12px !important;
|
| 196 |
+
align-items: center !important;
|
| 197 |
+
}
|
| 198 |
+
.header-logo-img {
|
| 199 |
+
height: 28px;
|
| 200 |
+
vertical-align: middle;
|
| 201 |
+
padding-right: 8px;
|
| 202 |
+
}
|
| 203 |
+
.main-title {
|
| 204 |
+
font-size: 40px;
|
| 205 |
+
font-weight: 700;
|
| 206 |
+
text-align: center;
|
| 207 |
+
margin-top: 20px;
|
| 208 |
+
margin-bottom: 20px;
|
| 209 |
+
}
|
| 210 |
+
.intro-paper-link {
|
| 211 |
+
color: #AC482A;
|
| 212 |
+
font-weight: 700;
|
| 213 |
+
text-decoration: underline;
|
| 214 |
+
}
|
| 215 |
+
.filter-label-row {
|
| 216 |
+
display: inline-flex;
|
| 217 |
+
align-items: center;
|
| 218 |
+
}
|
| 219 |
+
.filter-label-container {
|
| 220 |
+
font-weight: 700;
|
| 221 |
+
margin-bottom: 8px;
|
| 222 |
+
font-size: 14px;
|
| 223 |
+
display: flex;
|
| 224 |
+
align-items: center;
|
| 225 |
+
}
|
| 226 |
+
.filter-segmented-row {
|
| 227 |
+
display: flex;
|
| 228 |
+
align-items: center;
|
| 229 |
+
}
|
| 230 |
+
.filter-label {
|
| 231 |
+
font-weight: 700;
|
| 232 |
+
margin-bottom: 8px;
|
| 233 |
+
font-size: 14px;
|
| 234 |
+
}
|
| 235 |
+
.filter-description {
|
| 236 |
+
font-size: 13px;
|
| 237 |
+
color: #555;
|
| 238 |
+
margin-bottom: 12px;
|
| 239 |
+
}
|
| 240 |
+
.filter-description-margin {
|
| 241 |
+
margin-top: 32px !important;
|
| 242 |
+
}
|
| 243 |
+
.global-toggle-status {
|
| 244 |
+
margin-left: 8px;
|
| 245 |
+
display: inline-block;
|
| 246 |
+
margin-top: 6px;
|
| 247 |
+
}
|
| 248 |
+
.main-content-left {
|
| 249 |
+
flex: 1;
|
| 250 |
+
min-width: 220px;
|
| 251 |
+
}
|
| 252 |
+
.main-content-right {
|
| 253 |
+
flex: 2;
|
| 254 |
+
min-width: 320px;
|
| 255 |
+
display: flex;
|
| 256 |
+
flex-direction: column;
|
| 257 |
+
justify-content: center;
|
| 258 |
+
height: 100%;
|
| 259 |
+
}
|
| 260 |
+
.tip-section {
|
| 261 |
+
background-color: #F5ECE6;
|
| 262 |
+
border-radius: 14px;
|
| 263 |
+
padding: 18px 20px;
|
| 264 |
+
margin-top: 28px;
|
| 265 |
+
box-shadow: 0 1px 4px rgba(8,32,48,0.04);
|
| 266 |
+
border: 1px solid #f0e3d6;
|
| 267 |
+
}
|
| 268 |
+
.tip-title {
|
| 269 |
+
font-weight: 700;
|
| 270 |
+
font-size: 15px;
|
| 271 |
+
margin-bottom: 6px;
|
| 272 |
+
color: #082030;
|
| 273 |
+
display: flex;
|
| 274 |
+
align-items: center;
|
| 275 |
+
}
|
| 276 |
+
.tip-highlight {
|
| 277 |
+
font-weight: 600;
|
| 278 |
+
color: #AC482A;
|
| 279 |
+
}
|
| 280 |
+
.tip-description {
|
| 281 |
+
font-size: 13px;
|
| 282 |
+
color: #082030;
|
| 283 |
+
line-height: 1.6;
|
| 284 |
+
}
|
| 285 |
+
.tab-description {
|
| 286 |
+
font-size: 14px;
|
| 287 |
+
margin-top: 18px;
|
| 288 |
+
margin-bottom: 12px;
|
| 289 |
+
text-align: left;
|
| 290 |
+
}
|
| 291 |
+
.meta-var {
|
| 292 |
+
font-weight: bold;
|
| 293 |
+
color: #082030;
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
@media (max-width: 1150px) {
|
| 297 |
.responsive-main-content {
|
| 298 |
flex-direction: column !important;
|
|
|
|
| 309 |
flex-direction: column !important;
|
| 310 |
gap: 12px !important;
|
| 311 |
padding: 12px !important;
|
| 312 |
+
width: 100vw !important;
|
| 313 |
+
box-sizing: border-box !important;
|
| 314 |
+
}
|
| 315 |
+
/* Fix header link squishing: stack links vertically and center them */
|
| 316 |
+
.responsive-header .header-link {
|
| 317 |
+
display: flex !important;
|
| 318 |
+
flex-direction: row !important;
|
| 319 |
+
align-items: center !important;
|
| 320 |
+
justify-content: center !important;
|
| 321 |
+
margin-bottom: 8px !important;
|
| 322 |
+
width: 100% !important;
|
| 323 |
+
min-width: 0 !important;
|
| 324 |
+
font-size: 15px !important;
|
| 325 |
+
flex-wrap: wrap !important;
|
| 326 |
+
}
|
| 327 |
+
.responsive-header > div:last-child {
|
| 328 |
+
flex-direction: column !important;
|
| 329 |
+
align-items: center !important;
|
| 330 |
+
gap: 8px !important;
|
| 331 |
+
width: 100% !important;
|
| 332 |
+
}
|
| 333 |
+
.responsive-header .header-link img {
|
| 334 |
+
margin-bottom: 0 !important;
|
| 335 |
+
margin-right: 8px !important;
|
| 336 |
}
|
| 337 |
.responsive-title-row {
|
| 338 |
margin-left: 0 !important;
|
graphs/leaderboard.py
CHANGED
|
@@ -154,7 +154,7 @@ def get_metadata_popover_content(icon, name, meta_type):
|
|
| 154 |
def chip_with_hovercard(text, bg_color="#F0F0F0", meta_type=None, icon=None):
|
| 155 |
hovercard_content = get_metadata_popover_content(icon, text, meta_type)
|
| 156 |
return dmc.HoverCard(
|
| 157 |
-
width=
|
| 158 |
shadow="md",
|
| 159 |
position="top",
|
| 160 |
children=[
|
|
@@ -170,7 +170,10 @@ def chip_with_hovercard(text, bg_color="#F0F0F0", meta_type=None, icon=None):
|
|
| 170 |
"alignItems": "center",
|
| 171 |
"fontSize": "14px",
|
| 172 |
"cursor": "pointer",
|
|
|
|
| 173 |
},
|
|
|
|
|
|
|
| 174 |
)
|
| 175 |
),
|
| 176 |
dmc.HoverCardDropdown(dmc.Text(hovercard_content, size="sm")),
|
|
@@ -330,9 +333,6 @@ def get_top_n_leaderboard(filtered_df, group_col, top_n=10, derived_author_toggl
|
|
| 330 |
download_top["Total Value"] = download_top["Total Value"].astype(int)
|
| 331 |
download_top["% of total"] = download_top["% of total"].round(2)
|
| 332 |
|
| 333 |
-
# Replace "User" in names
|
| 334 |
-
top["Name"] = top["Name"].replace("User", "user")
|
| 335 |
-
|
| 336 |
# All relevant metadata columns
|
| 337 |
meta_cols = meta_cols_map.get(group_col, [])
|
| 338 |
|
|
@@ -413,6 +413,9 @@ def get_top_n_leaderboard(filtered_df, group_col, top_n=10, derived_author_toggl
|
|
| 413 |
# Apply metadata builder to top dataframe
|
| 414 |
top["Metadata"] = top["Name"].astype(object).apply(build_metadata)
|
| 415 |
|
|
|
|
|
|
|
|
|
|
| 416 |
# Build download dataframe with metadata
|
| 417 |
download_info_list = [build_download_metadata(nm) for nm in download_top["Name"]]
|
| 418 |
download_info_df = pd.DataFrame(download_info_list)
|
|
|
|
| 154 |
def chip_with_hovercard(text, bg_color="#F0F0F0", meta_type=None, icon=None):
|
| 155 |
hovercard_content = get_metadata_popover_content(icon, text, meta_type)
|
| 156 |
return dmc.HoverCard(
|
| 157 |
+
width="auto",
|
| 158 |
shadow="md",
|
| 159 |
position="top",
|
| 160 |
children=[
|
|
|
|
| 170 |
"alignItems": "center",
|
| 171 |
"fontSize": "14px",
|
| 172 |
"cursor": "pointer",
|
| 173 |
+
"transition": "background-color 0.15s",
|
| 174 |
},
|
| 175 |
+
# Add a class for hover effect
|
| 176 |
+
className="chip-hover-darken"
|
| 177 |
)
|
| 178 |
),
|
| 179 |
dmc.HoverCardDropdown(dmc.Text(hovercard_content, size="sm")),
|
|
|
|
| 333 |
download_top["Total Value"] = download_top["Total Value"].astype(int)
|
| 334 |
download_top["% of total"] = download_top["% of total"].round(2)
|
| 335 |
|
|
|
|
|
|
|
|
|
|
| 336 |
# All relevant metadata columns
|
| 337 |
meta_cols = meta_cols_map.get(group_col, [])
|
| 338 |
|
|
|
|
| 413 |
# Apply metadata builder to top dataframe
|
| 414 |
top["Metadata"] = top["Name"].astype(object).apply(build_metadata)
|
| 415 |
|
| 416 |
+
# Capitalize "user" back to "User" for display
|
| 417 |
+
top["Name"] = top["Name"].replace("user", "User")
|
| 418 |
+
|
| 419 |
# Build download dataframe with metadata
|
| 420 |
download_info_list = [build_download_metadata(nm) for nm in download_top["Name"]]
|
| 421 |
download_info_df = pd.DataFrame(download_info_list)
|