Update app.py
Browse files
app.py
CHANGED
|
@@ -110,26 +110,27 @@ html, body {
|
|
| 110 |
}
|
| 111 |
|
| 112 |
/* ========================================
|
| 113 |
-
Cards & Groups -
|
| 114 |
======================================== */
|
| 115 |
.group {
|
| 116 |
background: var(--bg-card) !important;
|
| 117 |
border: 1px solid var(--border-color) !important;
|
| 118 |
-
border-radius:
|
| 119 |
-
padding:
|
| 120 |
margin-bottom: 24px !important;
|
| 121 |
-
box-shadow:
|
| 122 |
-
backdrop-filter:
|
| 123 |
transition: var(--transition);
|
| 124 |
}
|
| 125 |
|
| 126 |
.group:hover {
|
| 127 |
-
box-shadow:
|
|
|
|
| 128 |
}
|
| 129 |
|
| 130 |
.dark .group {
|
| 131 |
-
background: var(--bg-card) !important;
|
| 132 |
-
border: 1px solid
|
| 133 |
}
|
| 134 |
|
| 135 |
/* ========================================
|
|
@@ -198,15 +199,16 @@ button.secondary:hover {
|
|
| 198 |
Tabs - Premium Look
|
| 199 |
======================================== */
|
| 200 |
.tabs {
|
| 201 |
-
background:
|
| 202 |
border: 1px solid var(--border-color) !important;
|
| 203 |
-
border-radius:
|
| 204 |
overflow: hidden !important;
|
| 205 |
-
box-shadow:
|
| 206 |
}
|
| 207 |
|
| 208 |
.dark .tabs {
|
| 209 |
-
|
|
|
|
| 210 |
}
|
| 211 |
|
| 212 |
.tab-nav {
|
|
@@ -241,24 +243,24 @@ button.secondary:hover {
|
|
| 241 |
|
| 242 |
.tabitem {
|
| 243 |
background: var(--bg-secondary) !important;
|
| 244 |
-
padding:
|
| 245 |
}
|
| 246 |
|
| 247 |
/* ========================================
|
| 248 |
Accordion - Expandable Sections
|
| 249 |
======================================== */
|
| 250 |
.accordion {
|
| 251 |
-
background: var(--bg-
|
| 252 |
border: 1px solid var(--border-color) !important;
|
| 253 |
-
border-radius:
|
| 254 |
-
margin-top:
|
| 255 |
overflow: hidden !important;
|
| 256 |
transition: var(--transition);
|
| 257 |
}
|
| 258 |
|
| 259 |
.dark .accordion {
|
| 260 |
-
background:
|
| 261 |
-
border: 1px solid rgba(249, 115, 22, 0.
|
| 262 |
}
|
| 263 |
|
| 264 |
.accordion:hover {
|
|
@@ -382,30 +384,6 @@ button.secondary:hover {
|
|
| 382 |
padding: 0 !important;
|
| 383 |
}
|
| 384 |
|
| 385 |
-
/* Header Row - Remove any background and styling */
|
| 386 |
-
.header-row,
|
| 387 |
-
.header-row > *,
|
| 388 |
-
.header-column,
|
| 389 |
-
.header-column > * {
|
| 390 |
-
background: transparent !important;
|
| 391 |
-
background-color: transparent !important;
|
| 392 |
-
border: none !important;
|
| 393 |
-
box-shadow: none !important;
|
| 394 |
-
padding: 0 !important;
|
| 395 |
-
margin: 0 !important;
|
| 396 |
-
}
|
| 397 |
-
|
| 398 |
-
/* Remove default Gradio block backgrounds for header area */
|
| 399 |
-
.header-row .block,
|
| 400 |
-
.header-row .panel,
|
| 401 |
-
.header-column .block,
|
| 402 |
-
.header-column .panel {
|
| 403 |
-
background: transparent !important;
|
| 404 |
-
background-color: transparent !important;
|
| 405 |
-
border: none !important;
|
| 406 |
-
box-shadow: none !important;
|
| 407 |
-
}
|
| 408 |
-
|
| 409 |
/* Container max width */
|
| 410 |
.gradio-container > .main {
|
| 411 |
padding: 0 !important;
|
|
@@ -432,10 +410,100 @@ button.secondary:hover {
|
|
| 432 |
}
|
| 433 |
|
| 434 |
/* ========================================
|
| 435 |
-
|
| 436 |
======================================== */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 437 |
|
| 438 |
-
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
.command-center-card,
|
| 440 |
.pipeline-status-card,
|
| 441 |
.campaign-output-card {
|
|
@@ -445,60 +513,44 @@ button.secondary:hover {
|
|
| 445 |
padding: 32px !important;
|
| 446 |
margin-bottom: 24px !important;
|
| 447 |
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
|
| 448 |
-
transition: all 0.3s
|
| 449 |
}
|
| 450 |
|
| 451 |
.command-center-card:hover,
|
| 452 |
.pipeline-status-card:hover,
|
| 453 |
.campaign-output-card:hover {
|
| 454 |
-
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05), 0 0 40px rgba(139, 92, 246, 0.
|
| 455 |
}
|
| 456 |
|
| 457 |
-
/* Dark mode
|
| 458 |
.dark .command-center-card,
|
| 459 |
.dark .pipeline-status-card,
|
| 460 |
-
.dark .campaign-output-card
|
| 461 |
-
[data-theme="dark"] .command-center-card,
|
| 462 |
-
[data-theme="dark"] .pipeline-status-card,
|
| 463 |
-
[data-theme="dark"] .campaign-output-card {
|
| 464 |
background: var(--bg-card, #1c1c1f) !important;
|
| 465 |
-
border: 1px solid
|
| 466 |
-
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.4) !important;
|
| 467 |
-
}
|
| 468 |
-
|
| 469 |
-
/* Command Center - Purple accent in dark mode */
|
| 470 |
-
.dark .command-center-card,
|
| 471 |
-
[data-theme="dark"] .command-center-card {
|
| 472 |
-
border-color: rgba(139, 92, 246, 0.2) !important;
|
| 473 |
}
|
| 474 |
|
| 475 |
-
|
| 476 |
-
.dark .pipeline-status-card,
|
| 477 |
-
|
| 478 |
-
|
|
|
|
| 479 |
}
|
| 480 |
|
| 481 |
-
/*
|
| 482 |
-
.
|
| 483 |
-
|
| 484 |
-
border-color: rgba(6, 182, 212, 0.2) !important;
|
| 485 |
}
|
| 486 |
|
| 487 |
-
/*
|
| 488 |
-
.
|
| 489 |
-
|
| 490 |
-
.campaign-output-card.group {
|
| 491 |
-
background: var(--bg-card, #ffffff) !important;
|
| 492 |
-
border: 1px solid var(--border-color, #e4e4e7) !important;
|
| 493 |
-
border-radius: 20px !important;
|
| 494 |
-
padding: 32px !important;
|
| 495 |
-
backdrop-filter: none !important;
|
| 496 |
}
|
| 497 |
|
| 498 |
-
|
| 499 |
-
.
|
| 500 |
-
|
| 501 |
-
background: var(--bg-card, #1c1c1f) !important;
|
| 502 |
}
|
| 503 |
|
| 504 |
/* Terminal content styling */
|
|
@@ -514,49 +566,81 @@ button.secondary:hover {
|
|
| 514 |
line-height: 1.6 !important;
|
| 515 |
}
|
| 516 |
|
| 517 |
-
.dark .terminal-content
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
border-color: var(--border-color, #3f3f46) !important;
|
| 521 |
}
|
| 522 |
|
| 523 |
-
/*
|
| 524 |
.campaign-output-card .tabs {
|
| 525 |
background: transparent !important;
|
| 526 |
-
border:
|
| 527 |
-
border-radius: 16px !important;
|
| 528 |
-
overflow: hidden !important;
|
| 529 |
box-shadow: none !important;
|
|
|
|
| 530 |
}
|
| 531 |
|
| 532 |
.campaign-output-card .tab-nav {
|
| 533 |
background: var(--bg-tertiary, #f5f5f5) !important;
|
| 534 |
-
border
|
| 535 |
-
|
|
|
|
|
|
|
|
|
|
| 536 |
}
|
| 537 |
|
| 538 |
-
.dark .campaign-output-card .
|
| 539 |
-
|
| 540 |
-
border-color:
|
| 541 |
}
|
| 542 |
|
| 543 |
-
.
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
border-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 547 |
}
|
| 548 |
|
| 549 |
.campaign-output-card .tabitem {
|
| 550 |
-
background: var(--bg-
|
|
|
|
|
|
|
| 551 |
padding: 24px !important;
|
|
|
|
| 552 |
}
|
| 553 |
|
| 554 |
-
.dark .campaign-output-card .tabitem
|
| 555 |
-
|
| 556 |
-
|
| 557 |
}
|
| 558 |
|
| 559 |
-
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 560 |
.command-center-card input,
|
| 561 |
.command-center-card textarea,
|
| 562 |
.command-center-card select {
|
|
@@ -568,11 +652,11 @@ button.secondary:hover {
|
|
| 568 |
.dark .command-center-card input,
|
| 569 |
.dark .command-center-card textarea,
|
| 570 |
.dark .command-center-card select {
|
| 571 |
-
background:
|
| 572 |
-
border-color:
|
| 573 |
}
|
| 574 |
|
| 575 |
-
/* Accordion inside
|
| 576 |
.command-center-card .accordion {
|
| 577 |
background: var(--bg-tertiary, #f5f5f5) !important;
|
| 578 |
border: 1px solid var(--border-color, #e4e4e7) !important;
|
|
@@ -581,105 +665,51 @@ button.secondary:hover {
|
|
| 581 |
}
|
| 582 |
|
| 583 |
.dark .command-center-card .accordion {
|
| 584 |
-
background:
|
| 585 |
-
border-color: rgba(249, 115, 22, 0.
|
| 586 |
-
}
|
| 587 |
-
|
| 588 |
-
/* Button row spacing */
|
| 589 |
-
.command-center-card .row {
|
| 590 |
-
margin-top: 20px !important;
|
| 591 |
-
}
|
| 592 |
-
|
| 593 |
-
/* ========================================
|
| 594 |
-
Special Elements
|
| 595 |
-
======================================== */
|
| 596 |
-
/* Hero section styling */
|
| 597 |
-
.hero-card {
|
| 598 |
-
background: linear-gradient(145deg, var(--bg-card), var(--bg-secondary)) !important;
|
| 599 |
-
border: 1px solid var(--border-color) !important;
|
| 600 |
}
|
| 601 |
|
| 602 |
-
.
|
| 603 |
-
|
| 604 |
-
border: 1px solid rgba(139, 92, 246, 0.2) !important;
|
| 605 |
-
}
|
| 606 |
-
|
| 607 |
-
/* Terminal styling */
|
| 608 |
-
.terminal-header {
|
| 609 |
-
background: linear-gradient(90deg, var(--bg-tertiary), var(--bg-secondary)) !important;
|
| 610 |
-
}
|
| 611 |
-
|
| 612 |
-
.dark .terminal-header {
|
| 613 |
-
background: linear-gradient(90deg, rgba(28, 28, 31, 0.9), rgba(24, 24, 27, 0.9)) !important;
|
| 614 |
-
}
|
| 615 |
-
|
| 616 |
-
/* Status indicator */
|
| 617 |
-
.status-online {
|
| 618 |
-
width: 10px;
|
| 619 |
-
height: 10px;
|
| 620 |
-
border-radius: 50%;
|
| 621 |
-
background: var(--accent-green);
|
| 622 |
-
animation: pulse 2s infinite;
|
| 623 |
-
box-shadow: 0 0 10px var(--accent-green);
|
| 624 |
-
}
|
| 625 |
-
|
| 626 |
-
/* Badge styling */
|
| 627 |
-
.badge {
|
| 628 |
-
display: inline-flex;
|
| 629 |
-
align-items: center;
|
| 630 |
-
padding: 6px 14px;
|
| 631 |
-
border-radius: 20px;
|
| 632 |
-
font-size: 12px;
|
| 633 |
-
font-weight: 600;
|
| 634 |
-
transition: var(--transition);
|
| 635 |
}
|
| 636 |
|
| 637 |
-
|
| 638 |
-
|
| 639 |
-
|
| 640 |
-
border:
|
| 641 |
-
|
| 642 |
-
|
| 643 |
-
|
| 644 |
-
|
| 645 |
-
|
| 646 |
-
|
| 647 |
-
}
|
| 648 |
-
|
| 649 |
-
.badge-orange {
|
| 650 |
-
background: var(--accent-orange-light);
|
| 651 |
-
color: var(--accent-orange);
|
| 652 |
-
border: 1px solid rgba(249, 115, 22, 0.3);
|
| 653 |
}
|
| 654 |
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
| 658 |
-
border: 1px solid var(--border-color) !important;
|
| 659 |
-
border-radius: var(--radius-lg) !important;
|
| 660 |
-
padding: 16px !important;
|
| 661 |
-
transition: var(--transition);
|
| 662 |
}
|
| 663 |
|
| 664 |
-
.
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
border-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 668 |
}
|
| 669 |
|
| 670 |
-
|
| 671 |
-
.
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
border-radius: var(--radius-md);
|
| 675 |
-
display: flex;
|
| 676 |
-
align-items: center;
|
| 677 |
-
justify-content: center;
|
| 678 |
-
transition: var(--transition);
|
| 679 |
}
|
| 680 |
|
| 681 |
-
.
|
| 682 |
-
|
|
|
|
|
|
|
| 683 |
}
|
| 684 |
"""
|
| 685 |
|
|
@@ -722,7 +752,7 @@ def format_logs() -> str:
|
|
| 722 |
for log in current_job["logs"]:
|
| 723 |
color = color_map.get(log["color"], "var(--text-primary, #18181b)")
|
| 724 |
lines.append(
|
| 725 |
-
f'<div style="margin: 6px 0; padding: 4px
|
| 726 |
f'<span style="color: var(--text-muted, #71717a);">βΊ</span> '
|
| 727 |
f'<span style="color: {color}; font-weight: 600;">[{log["agent"]}]</span> '
|
| 728 |
f'<span style="color: var(--text-secondary, #52525b);">{log["message"]}</span>'
|
|
@@ -733,20 +763,20 @@ def format_logs() -> str:
|
|
| 733 |
|
| 734 |
def get_progress_html(progress: int, status: str) -> str:
|
| 735 |
"""Generate progress bar HTML."""
|
| 736 |
-
|
| 737 |
-
"idle": ("
|
| 738 |
-
"analyzing": ("#8b5cf6", "
|
| 739 |
-
"generating": ("#22c55e", "
|
| 740 |
-
"completed": ("#22c55e", "
|
| 741 |
-
"failed": ("#ef4444", "
|
| 742 |
}
|
| 743 |
-
text_color,
|
| 744 |
|
| 745 |
return f"""
|
| 746 |
-
<div style="margin-bottom:
|
| 747 |
-
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom:
|
| 748 |
-
<span style="color: #8b5cf6; font-weight: 600; font-size: 14px;
|
| 749 |
-
<span style="color: {text_color}; font-size:
|
| 750 |
</div>
|
| 751 |
<div style="width: 100%; height: 10px; background: var(--bg-tertiary, #f5f5f5); border-radius: 5px; overflow: hidden; border: 1px solid var(--border-color, #e4e4e7);">
|
| 752 |
<div style="width: {progress}%; height: 100%; background: linear-gradient(90deg, #8b5cf6, #22c55e); transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1); border-radius: 5px;"></div>
|
|
@@ -1228,7 +1258,7 @@ def create_app():
|
|
| 1228 |
panel_background_fill_dark="#1c1c1f",
|
| 1229 |
# Borders
|
| 1230 |
block_border_color="#e4e4e7",
|
| 1231 |
-
block_border_color_dark="
|
| 1232 |
border_color_primary="#8b5cf6",
|
| 1233 |
border_color_primary_dark="#a78bfa",
|
| 1234 |
# Inputs
|
|
@@ -1258,7 +1288,7 @@ def create_app():
|
|
| 1258 |
block_shadow="0 4px 6px -1px rgba(0, 0, 0, 0.1)",
|
| 1259 |
block_shadow_dark="0 4px 6px -1px rgba(0, 0, 0, 0.4)",
|
| 1260 |
# Radius
|
| 1261 |
-
block_radius="
|
| 1262 |
button_large_radius="12px",
|
| 1263 |
button_small_radius="8px",
|
| 1264 |
)
|
|
@@ -1278,22 +1308,22 @@ def create_app():
|
|
| 1278 |
app.theme = custom_theme
|
| 1279 |
app.css = CUSTOM_CSS
|
| 1280 |
app.js = DARK_MODE_JS
|
| 1281 |
-
# Header
|
| 1282 |
-
with gr.Row(
|
| 1283 |
-
with gr.Column(
|
| 1284 |
gr.HTML(
|
| 1285 |
"""
|
| 1286 |
-
<div style="display: flex; align-items: center; justify-content: space-between; padding:
|
| 1287 |
<div style="display: flex; align-items: center; gap: 16px;">
|
| 1288 |
-
<div style="width:
|
| 1289 |
-
<span style="font-size:
|
| 1290 |
</div>
|
| 1291 |
<div>
|
| 1292 |
-
<h1 style="margin: 0; background: linear-gradient(135deg, #8b5cf6, #22c55e); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; font-size:
|
| 1293 |
-
<p style="margin:
|
| 1294 |
</div>
|
| 1295 |
</div>
|
| 1296 |
-
<div style="display: flex; align-items: center; gap: 10px; padding: 10px 18px; background:
|
| 1297 |
<div style="width: 10px; height: 10px; border-radius: 50%; background: #22c55e; animation: pulse 2s infinite; box-shadow: 0 0 12px rgba(34, 197, 94, 0.6);"></div>
|
| 1298 |
<span style="font-size: 13px; font-weight: 600; color: #22c55e;">System Online</span>
|
| 1299 |
</div>
|
|
@@ -1312,7 +1342,7 @@ def create_app():
|
|
| 1312 |
with gr.Column():
|
| 1313 |
gr.HTML(
|
| 1314 |
"""
|
| 1315 |
-
<div style="background: var(--bg-card, #ffffff); border: 1px solid var(--border-color, #e4e4e7); border-radius: 20px; padding: 32px; margin-bottom: 24px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1)
|
| 1316 |
<!-- Header -->
|
| 1317 |
<div style="display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 24px;">
|
| 1318 |
<div style="display: flex; align-items: center; gap: 16px;">
|
|
@@ -1428,15 +1458,13 @@ def create_app():
|
|
| 1428 |
with gr.Group(elem_classes=["command-center-card"]):
|
| 1429 |
gr.HTML(
|
| 1430 |
"""
|
| 1431 |
-
<div style="display: flex; align-items:
|
| 1432 |
-
<div style="display: flex; align-items: center;
|
| 1433 |
-
<
|
| 1434 |
-
|
| 1435 |
-
|
| 1436 |
-
<
|
| 1437 |
-
|
| 1438 |
-
<p style="margin: 6px 0 0 0; color: var(--text-muted, #71717a); font-size: 14px;">Configure and launch your campaign</p>
|
| 1439 |
-
</div>
|
| 1440 |
</div>
|
| 1441 |
</div>
|
| 1442 |
"""
|
|
@@ -1463,7 +1491,7 @@ def create_app():
|
|
| 1463 |
# Settings Accordion for API Keys
|
| 1464 |
with gr.Accordion("βοΈ Settings (API Keys)", open=False):
|
| 1465 |
gr.HTML(
|
| 1466 |
-
'<div style="padding: 12px 0; color: var(--text-muted, #71717a); font-size:
|
| 1467 |
)
|
| 1468 |
anthropic_key = gr.Textbox(
|
| 1469 |
label="Anthropic API Key (Claude)",
|
|
@@ -1478,7 +1506,7 @@ def create_app():
|
|
| 1478 |
lines=1,
|
| 1479 |
)
|
| 1480 |
gr.HTML(
|
| 1481 |
-
'''<div style="padding: 12px 0; color: var(--text-muted, #71717a); font-size:
|
| 1482 |
<p style="margin: 0 0 8px 0;">π <a href="https://console.anthropic.com" target="_blank" style="color: #8b5cf6; text-decoration: none; font-weight: 500;">Get Anthropic API Key β</a></p>
|
| 1483 |
<p style="margin: 0;">π <a href="https://github.com/settings/tokens" target="_blank" style="color: #22c55e; text-decoration: none; font-weight: 500;">Get GitHub Token β</a></p>
|
| 1484 |
</div>'''
|
|
@@ -1496,15 +1524,13 @@ def create_app():
|
|
| 1496 |
with gr.Group(elem_classes=["pipeline-status-card"]):
|
| 1497 |
gr.HTML(
|
| 1498 |
"""
|
| 1499 |
-
<div style="display: flex; align-items:
|
| 1500 |
-
<div style="display: flex; align-items: center;
|
| 1501 |
-
<
|
| 1502 |
-
|
| 1503 |
-
|
| 1504 |
-
<
|
| 1505 |
-
|
| 1506 |
-
<p style="margin: 6px 0 0 0; color: var(--text-muted, #71717a); font-size: 14px;">Real-time generation progress</p>
|
| 1507 |
-
</div>
|
| 1508 |
</div>
|
| 1509 |
</div>
|
| 1510 |
"""
|
|
@@ -1516,8 +1542,8 @@ def create_app():
|
|
| 1516 |
# Event Log Section Header
|
| 1517 |
gr.HTML(
|
| 1518 |
"""
|
| 1519 |
-
<div style="
|
| 1520 |
-
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom:
|
| 1521 |
<div style="display: flex; align-items: center; gap: 12px;">
|
| 1522 |
<div style="display: flex; gap: 6px;">
|
| 1523 |
<div style="width: 12px; height: 12px; border-radius: 50%; background: linear-gradient(135deg, #ef4444, #dc2626); box-shadow: 0 0 6px rgba(239, 68, 68, 0.4);"></div>
|
|
@@ -1526,9 +1552,9 @@ def create_app():
|
|
| 1526 |
</div>
|
| 1527 |
<span style="font-weight: 600; color: var(--text-primary, #18181b); font-size: 14px;">Event Log</span>
|
| 1528 |
</div>
|
| 1529 |
-
<div style="
|
| 1530 |
<div style="width: 6px; height: 6px; border-radius: 50%; background: #22c55e; animation: pulse 2s infinite; box-shadow: 0 0 8px rgba(34, 197, 94, 0.6);"></div>
|
| 1531 |
-
<span style="color: #22c55e; font-size:
|
| 1532 |
</div>
|
| 1533 |
</div>
|
| 1534 |
</div>
|
|
@@ -1544,12 +1570,12 @@ def create_app():
|
|
| 1544 |
# Footer
|
| 1545 |
gr.HTML(
|
| 1546 |
"""
|
| 1547 |
-
<div style="display: flex; align-items: center; justify-content: space-between;
|
| 1548 |
-
<div style="display: flex; align-items: center; gap: 12px;
|
| 1549 |
-
<span style="color: var(--text-muted, #71717a);
|
| 1550 |
-
<span style="background: linear-gradient(135deg, rgba(139, 92, 246, 0.15), rgba(139, 92, 246, 0.05)); color: #8b5cf6; padding:
|
| 1551 |
-
<span style="color: var(--text-muted, #71717a);
|
| 1552 |
-
<span style="background: linear-gradient(135deg, rgba(249, 115, 22, 0.15), rgba(249, 115, 22, 0.05)); color: #f97316; padding:
|
| 1553 |
</div>
|
| 1554 |
</div>
|
| 1555 |
"""
|
|
@@ -1561,18 +1587,18 @@ def create_app():
|
|
| 1561 |
with gr.Group(elem_classes=["campaign-output-card"]):
|
| 1562 |
gr.HTML(
|
| 1563 |
"""
|
| 1564 |
-
<div style="display: flex; align-items:
|
| 1565 |
-
<div style="display: flex; align-items: center; gap:
|
| 1566 |
-
<div style="width:
|
| 1567 |
-
<span style="font-size:
|
| 1568 |
</div>
|
| 1569 |
<div>
|
| 1570 |
-
<
|
| 1571 |
-
<p style="margin:
|
| 1572 |
</div>
|
| 1573 |
</div>
|
| 1574 |
-
<div style="display: flex; gap: 10px;
|
| 1575 |
-
<span style="background:
|
| 1576 |
</div>
|
| 1577 |
</div>
|
| 1578 |
"""
|
|
@@ -1660,8 +1686,8 @@ if __name__ == "__main__":
|
|
| 1660 |
app = create_app()
|
| 1661 |
app.launch(
|
| 1662 |
server_name="0.0.0.0",
|
| 1663 |
-
server_port=
|
| 1664 |
-
share=
|
| 1665 |
show_error=True,
|
| 1666 |
ssr_mode=False, # Disable experimental SSR to avoid potential issues
|
| 1667 |
)
|
|
|
|
| 110 |
}
|
| 111 |
|
| 112 |
/* ========================================
|
| 113 |
+
Cards & Groups - Glass Morphism Style
|
| 114 |
======================================== */
|
| 115 |
.group {
|
| 116 |
background: var(--bg-card) !important;
|
| 117 |
border: 1px solid var(--border-color) !important;
|
| 118 |
+
border-radius: var(--radius-xl) !important;
|
| 119 |
+
padding: 28px !important;
|
| 120 |
margin-bottom: 24px !important;
|
| 121 |
+
box-shadow: var(--shadow-md) !important;
|
| 122 |
+
backdrop-filter: blur(10px) !important;
|
| 123 |
transition: var(--transition);
|
| 124 |
}
|
| 125 |
|
| 126 |
.group:hover {
|
| 127 |
+
box-shadow: var(--shadow-lg), var(--shadow-glow) !important;
|
| 128 |
+
transform: translateY(-2px);
|
| 129 |
}
|
| 130 |
|
| 131 |
.dark .group {
|
| 132 |
+
background: linear-gradient(145deg, var(--bg-card) 0%, rgba(28, 28, 31, 0.8) 100%) !important;
|
| 133 |
+
border: 1px solid rgba(139, 92, 246, 0.15) !important;
|
| 134 |
}
|
| 135 |
|
| 136 |
/* ========================================
|
|
|
|
| 199 |
Tabs - Premium Look
|
| 200 |
======================================== */
|
| 201 |
.tabs {
|
| 202 |
+
background: var(--bg-card) !important;
|
| 203 |
border: 1px solid var(--border-color) !important;
|
| 204 |
+
border-radius: var(--radius-xl) !important;
|
| 205 |
overflow: hidden !important;
|
| 206 |
+
box-shadow: var(--shadow-md) !important;
|
| 207 |
}
|
| 208 |
|
| 209 |
.dark .tabs {
|
| 210 |
+
background: linear-gradient(145deg, var(--bg-card) 0%, rgba(28, 28, 31, 0.9) 100%) !important;
|
| 211 |
+
border: 1px solid rgba(74, 222, 128, 0.15) !important;
|
| 212 |
}
|
| 213 |
|
| 214 |
.tab-nav {
|
|
|
|
| 243 |
|
| 244 |
.tabitem {
|
| 245 |
background: var(--bg-secondary) !important;
|
| 246 |
+
padding: 28px !important;
|
| 247 |
}
|
| 248 |
|
| 249 |
/* ========================================
|
| 250 |
Accordion - Expandable Sections
|
| 251 |
======================================== */
|
| 252 |
.accordion {
|
| 253 |
+
background: var(--bg-card) !important;
|
| 254 |
border: 1px solid var(--border-color) !important;
|
| 255 |
+
border-radius: var(--radius-lg) !important;
|
| 256 |
+
margin-top: 20px !important;
|
| 257 |
overflow: hidden !important;
|
| 258 |
transition: var(--transition);
|
| 259 |
}
|
| 260 |
|
| 261 |
.dark .accordion {
|
| 262 |
+
background: linear-gradient(145deg, rgba(28, 28, 31, 0.8), rgba(39, 39, 42, 0.5)) !important;
|
| 263 |
+
border: 1px solid rgba(249, 115, 22, 0.15) !important;
|
| 264 |
}
|
| 265 |
|
| 266 |
.accordion:hover {
|
|
|
|
| 384 |
padding: 0 !important;
|
| 385 |
}
|
| 386 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 387 |
/* Container max width */
|
| 388 |
.gradio-container > .main {
|
| 389 |
padding: 0 !important;
|
|
|
|
| 410 |
}
|
| 411 |
|
| 412 |
/* ========================================
|
| 413 |
+
Special Elements
|
| 414 |
======================================== */
|
| 415 |
+
/* Hero section styling */
|
| 416 |
+
.hero-card {
|
| 417 |
+
background: linear-gradient(145deg, var(--bg-card), var(--bg-secondary)) !important;
|
| 418 |
+
border: 1px solid var(--border-color) !important;
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
.dark .hero-card {
|
| 422 |
+
background: linear-gradient(145deg, rgba(28, 28, 31, 0.9), rgba(18, 18, 20, 0.9)) !important;
|
| 423 |
+
border: 1px solid rgba(139, 92, 246, 0.2) !important;
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
/* Terminal styling */
|
| 427 |
+
.terminal-header {
|
| 428 |
+
background: linear-gradient(90deg, var(--bg-tertiary), var(--bg-secondary)) !important;
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
.dark .terminal-header {
|
| 432 |
+
background: linear-gradient(90deg, rgba(28, 28, 31, 0.9), rgba(24, 24, 27, 0.9)) !important;
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
/* Status indicator */
|
| 436 |
+
.status-online {
|
| 437 |
+
width: 10px;
|
| 438 |
+
height: 10px;
|
| 439 |
+
border-radius: 50%;
|
| 440 |
+
background: var(--accent-green);
|
| 441 |
+
animation: pulse 2s infinite;
|
| 442 |
+
box-shadow: 0 0 10px var(--accent-green);
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
/* Badge styling */
|
| 446 |
+
.badge {
|
| 447 |
+
display: inline-flex;
|
| 448 |
+
align-items: center;
|
| 449 |
+
padding: 6px 14px;
|
| 450 |
+
border-radius: 20px;
|
| 451 |
+
font-size: 12px;
|
| 452 |
+
font-weight: 600;
|
| 453 |
+
transition: var(--transition);
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
.badge-purple {
|
| 457 |
+
background: var(--accent-purple-light);
|
| 458 |
+
color: var(--accent-purple);
|
| 459 |
+
border: 1px solid rgba(139, 92, 246, 0.3);
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
.badge-green {
|
| 463 |
+
background: var(--accent-green-light);
|
| 464 |
+
color: var(--accent-green);
|
| 465 |
+
border: 1px solid rgba(34, 197, 94, 0.3);
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
.badge-orange {
|
| 469 |
+
background: var(--accent-orange-light);
|
| 470 |
+
color: var(--accent-orange);
|
| 471 |
+
border: 1px solid rgba(249, 115, 22, 0.3);
|
| 472 |
+
}
|
| 473 |
|
| 474 |
+
/* Feature card */
|
| 475 |
+
.feature-card {
|
| 476 |
+
background: var(--bg-secondary) !important;
|
| 477 |
+
border: 1px solid var(--border-color) !important;
|
| 478 |
+
border-radius: var(--radius-lg) !important;
|
| 479 |
+
padding: 16px !important;
|
| 480 |
+
transition: var(--transition);
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
.feature-card:hover {
|
| 484 |
+
transform: translateY(-3px);
|
| 485 |
+
box-shadow: var(--shadow-md);
|
| 486 |
+
border-color: var(--accent-purple) !important;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
/* Icon box */
|
| 490 |
+
.icon-box {
|
| 491 |
+
width: 44px;
|
| 492 |
+
height: 44px;
|
| 493 |
+
border-radius: var(--radius-md);
|
| 494 |
+
display: flex;
|
| 495 |
+
align-items: center;
|
| 496 |
+
justify-content: center;
|
| 497 |
+
transition: var(--transition);
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
.icon-box:hover {
|
| 501 |
+
transform: scale(1.1);
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
/* ========================================
|
| 505 |
+
Custom Card Classes - Matching About Section Style
|
| 506 |
+
======================================== */
|
| 507 |
.command-center-card,
|
| 508 |
.pipeline-status-card,
|
| 509 |
.campaign-output-card {
|
|
|
|
| 513 |
padding: 32px !important;
|
| 514 |
margin-bottom: 24px !important;
|
| 515 |
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
|
| 516 |
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
| 517 |
}
|
| 518 |
|
| 519 |
.command-center-card:hover,
|
| 520 |
.pipeline-status-card:hover,
|
| 521 |
.campaign-output-card:hover {
|
| 522 |
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05), 0 0 40px rgba(139, 92, 246, 0.1) !important;
|
| 523 |
}
|
| 524 |
|
| 525 |
+
/* Dark mode for all business cards */
|
| 526 |
.dark .command-center-card,
|
| 527 |
.dark .pipeline-status-card,
|
| 528 |
+
.dark .campaign-output-card {
|
|
|
|
|
|
|
|
|
|
| 529 |
background: var(--bg-card, #1c1c1f) !important;
|
| 530 |
+
border: 1px solid rgba(139, 92, 246, 0.15) !important;
|
| 531 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3) !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 532 |
}
|
| 533 |
|
| 534 |
+
.dark .command-center-card:hover,
|
| 535 |
+
.dark .pipeline-status-card:hover,
|
| 536 |
+
.dark .campaign-output-card:hover {
|
| 537 |
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.4), 0 0 60px rgba(139, 92, 246, 0.2) !important;
|
| 538 |
+
border-color: rgba(139, 92, 246, 0.25) !important;
|
| 539 |
}
|
| 540 |
|
| 541 |
+
/* Command Center - Purple accent border on hover */
|
| 542 |
+
.command-center-card:hover {
|
| 543 |
+
border-color: rgba(139, 92, 246, 0.3) !important;
|
|
|
|
| 544 |
}
|
| 545 |
|
| 546 |
+
/* Pipeline Status - Green accent border on hover */
|
| 547 |
+
.pipeline-status-card:hover {
|
| 548 |
+
border-color: rgba(34, 197, 94, 0.3) !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 549 |
}
|
| 550 |
|
| 551 |
+
/* Campaign Output - Cyan accent border on hover */
|
| 552 |
+
.campaign-output-card:hover {
|
| 553 |
+
border-color: rgba(6, 182, 212, 0.3) !important;
|
|
|
|
| 554 |
}
|
| 555 |
|
| 556 |
/* Terminal content styling */
|
|
|
|
| 566 |
line-height: 1.6 !important;
|
| 567 |
}
|
| 568 |
|
| 569 |
+
.dark .terminal-content {
|
| 570 |
+
background: rgba(39, 39, 42, 0.5) !important;
|
| 571 |
+
border-color: rgba(63, 63, 70, 0.5) !important;
|
|
|
|
| 572 |
}
|
| 573 |
|
| 574 |
+
/* Tabs inside Campaign Output - matching card style */
|
| 575 |
.campaign-output-card .tabs {
|
| 576 |
background: transparent !important;
|
| 577 |
+
border: none !important;
|
|
|
|
|
|
|
| 578 |
box-shadow: none !important;
|
| 579 |
+
margin-top: 0 !important;
|
| 580 |
}
|
| 581 |
|
| 582 |
.campaign-output-card .tab-nav {
|
| 583 |
background: var(--bg-tertiary, #f5f5f5) !important;
|
| 584 |
+
border: 1px solid var(--border-color, #e4e4e7) !important;
|
| 585 |
+
border-radius: 14px !important;
|
| 586 |
+
padding: 8px !important;
|
| 587 |
+
gap: 6px !important;
|
| 588 |
+
margin-bottom: 16px !important;
|
| 589 |
}
|
| 590 |
|
| 591 |
+
.dark .campaign-output-card .tab-nav {
|
| 592 |
+
background: rgba(39, 39, 42, 0.4) !important;
|
| 593 |
+
border-color: rgba(63, 63, 70, 0.4) !important;
|
| 594 |
}
|
| 595 |
|
| 596 |
+
.campaign-output-card .tab-nav button {
|
| 597 |
+
background: transparent !important;
|
| 598 |
+
border: none !important;
|
| 599 |
+
border-radius: 10px !important;
|
| 600 |
+
color: var(--text-muted, #71717a) !important;
|
| 601 |
+
font-weight: 500 !important;
|
| 602 |
+
font-size: 13px !important;
|
| 603 |
+
padding: 10px 16px !important;
|
| 604 |
+
transition: all 0.2s ease !important;
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
.campaign-output-card .tab-nav button:hover {
|
| 608 |
+
background: rgba(139, 92, 246, 0.1) !important;
|
| 609 |
+
color: var(--accent-purple, #8b5cf6) !important;
|
| 610 |
+
}
|
| 611 |
+
|
| 612 |
+
.campaign-output-card .tab-nav button.selected {
|
| 613 |
+
background: linear-gradient(135deg, rgba(139, 92, 246, 0.15), rgba(34, 197, 94, 0.1)) !important;
|
| 614 |
+
color: var(--accent-purple, #8b5cf6) !important;
|
| 615 |
+
font-weight: 600 !important;
|
| 616 |
+
box-shadow: 0 2px 4px rgba(139, 92, 246, 0.15) !important;
|
| 617 |
}
|
| 618 |
|
| 619 |
.campaign-output-card .tabitem {
|
| 620 |
+
background: var(--bg-tertiary, #f5f5f5) !important;
|
| 621 |
+
border: 1px solid var(--border-color, #e4e4e7) !important;
|
| 622 |
+
border-radius: 14px !important;
|
| 623 |
padding: 24px !important;
|
| 624 |
+
min-height: 300px !important;
|
| 625 |
}
|
| 626 |
|
| 627 |
+
.dark .campaign-output-card .tabitem {
|
| 628 |
+
background: rgba(39, 39, 42, 0.3) !important;
|
| 629 |
+
border-color: rgba(63, 63, 70, 0.4) !important;
|
| 630 |
}
|
| 631 |
|
| 632 |
+
/* Markdown content inside tabs */
|
| 633 |
+
.campaign-output-card .markdown {
|
| 634 |
+
color: var(--text-primary, #18181b) !important;
|
| 635 |
+
font-size: 14px !important;
|
| 636 |
+
line-height: 1.7 !important;
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
.dark .campaign-output-card .markdown {
|
| 640 |
+
color: var(--text-primary, #fafafa) !important;
|
| 641 |
+
}
|
| 642 |
+
|
| 643 |
+
/* Form elements inside cards */
|
| 644 |
.command-center-card input,
|
| 645 |
.command-center-card textarea,
|
| 646 |
.command-center-card select {
|
|
|
|
| 652 |
.dark .command-center-card input,
|
| 653 |
.dark .command-center-card textarea,
|
| 654 |
.dark .command-center-card select {
|
| 655 |
+
background: rgba(39, 39, 42, 0.5) !important;
|
| 656 |
+
border-color: rgba(63, 63, 70, 0.5) !important;
|
| 657 |
}
|
| 658 |
|
| 659 |
+
/* Accordion styling inside cards */
|
| 660 |
.command-center-card .accordion {
|
| 661 |
background: var(--bg-tertiary, #f5f5f5) !important;
|
| 662 |
border: 1px solid var(--border-color, #e4e4e7) !important;
|
|
|
|
| 665 |
}
|
| 666 |
|
| 667 |
.dark .command-center-card .accordion {
|
| 668 |
+
background: rgba(39, 39, 42, 0.4) !important;
|
| 669 |
+
border-color: rgba(249, 115, 22, 0.15) !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 670 |
}
|
| 671 |
|
| 672 |
+
.command-center-card .accordion:hover {
|
| 673 |
+
border-color: rgba(249, 115, 22, 0.3) !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 674 |
}
|
| 675 |
|
| 676 |
+
/* Buttons inside cards */
|
| 677 |
+
.command-center-card button.primary {
|
| 678 |
+
background: linear-gradient(135deg, #8b5cf6, #7c3aed) !important;
|
| 679 |
+
border: none !important;
|
| 680 |
+
border-radius: 12px !important;
|
| 681 |
+
color: white !important;
|
| 682 |
+
font-weight: 600 !important;
|
| 683 |
+
padding: 14px 24px !important;
|
| 684 |
+
box-shadow: 0 4px 6px rgba(139, 92, 246, 0.25), 0 0 20px rgba(139, 92, 246, 0.2) !important;
|
| 685 |
+
transition: all 0.3s ease !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 686 |
}
|
| 687 |
|
| 688 |
+
.command-center-card button.primary:hover {
|
| 689 |
+
transform: translateY(-2px) !important;
|
| 690 |
+
box-shadow: 0 6px 12px rgba(139, 92, 246, 0.35), 0 0 30px rgba(139, 92, 246, 0.3) !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
}
|
| 692 |
|
| 693 |
+
.command-center-card button.secondary {
|
| 694 |
+
background: var(--bg-tertiary, #f5f5f5) !important;
|
| 695 |
+
border: 1px solid var(--border-color, #e4e4e7) !important;
|
| 696 |
+
border-radius: 12px !important;
|
| 697 |
+
color: var(--text-secondary, #52525b) !important;
|
| 698 |
+
font-weight: 500 !important;
|
| 699 |
+
padding: 14px 24px !important;
|
| 700 |
+
transition: all 0.3s ease !important;
|
| 701 |
}
|
| 702 |
|
| 703 |
+
.dark .command-center-card button.secondary {
|
| 704 |
+
background: rgba(39, 39, 42, 0.5) !important;
|
| 705 |
+
border-color: rgba(63, 63, 70, 0.5) !important;
|
| 706 |
+
color: var(--text-secondary, #a1a1aa) !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 707 |
}
|
| 708 |
|
| 709 |
+
.command-center-card button.secondary:hover {
|
| 710 |
+
background: var(--bg-secondary, #ffffff) !important;
|
| 711 |
+
border-color: var(--accent-purple, #8b5cf6) !important;
|
| 712 |
+
color: var(--accent-purple, #8b5cf6) !important;
|
| 713 |
}
|
| 714 |
"""
|
| 715 |
|
|
|
|
| 752 |
for log in current_job["logs"]:
|
| 753 |
color = color_map.get(log["color"], "var(--text-primary, #18181b)")
|
| 754 |
lines.append(
|
| 755 |
+
f'<div style="margin: 6px 0; padding: 4px 0;">'
|
| 756 |
f'<span style="color: var(--text-muted, #71717a);">βΊ</span> '
|
| 757 |
f'<span style="color: {color}; font-weight: 600;">[{log["agent"]}]</span> '
|
| 758 |
f'<span style="color: var(--text-secondary, #52525b);">{log["message"]}</span>'
|
|
|
|
| 763 |
|
| 764 |
def get_progress_html(progress: int, status: str) -> str:
|
| 765 |
"""Generate progress bar HTML."""
|
| 766 |
+
status_colors = {
|
| 767 |
+
"idle": ("var(--text-muted, #71717a)", "var(--border-color, #e4e4e7)"),
|
| 768 |
+
"analyzing": ("#8b5cf6", "rgba(139, 92, 246, 0.2)"),
|
| 769 |
+
"generating": ("#22c55e", "rgba(34, 197, 94, 0.2)"),
|
| 770 |
+
"completed": ("#22c55e", "rgba(34, 197, 94, 0.2)"),
|
| 771 |
+
"failed": ("#ef4444", "rgba(239, 68, 68, 0.2)"),
|
| 772 |
}
|
| 773 |
+
text_color, bg_color = status_colors.get(status, status_colors["idle"])
|
| 774 |
|
| 775 |
return f"""
|
| 776 |
+
<div style="margin-bottom: 16px;">
|
| 777 |
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
| 778 |
+
<span style="color: #8b5cf6; font-weight: 600; font-size: 14px;">Pipeline Status</span>
|
| 779 |
+
<span style="color: {text_color}; font-size: 12px; padding: 4px 12px; background: {bg_color}; border: 1px solid {text_color}33; border-radius: 16px; font-weight: 500; text-transform: capitalize;">{status}</span>
|
| 780 |
</div>
|
| 781 |
<div style="width: 100%; height: 10px; background: var(--bg-tertiary, #f5f5f5); border-radius: 5px; overflow: hidden; border: 1px solid var(--border-color, #e4e4e7);">
|
| 782 |
<div style="width: {progress}%; height: 100%; background: linear-gradient(90deg, #8b5cf6, #22c55e); transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1); border-radius: 5px;"></div>
|
|
|
|
| 1258 |
panel_background_fill_dark="#1c1c1f",
|
| 1259 |
# Borders
|
| 1260 |
block_border_color="#e4e4e7",
|
| 1261 |
+
block_border_color_dark="rgba(139, 92, 246, 0.2)",
|
| 1262 |
border_color_primary="#8b5cf6",
|
| 1263 |
border_color_primary_dark="#a78bfa",
|
| 1264 |
# Inputs
|
|
|
|
| 1288 |
block_shadow="0 4px 6px -1px rgba(0, 0, 0, 0.1)",
|
| 1289 |
block_shadow_dark="0 4px 6px -1px rgba(0, 0, 0, 0.4)",
|
| 1290 |
# Radius
|
| 1291 |
+
block_radius="16px",
|
| 1292 |
button_large_radius="12px",
|
| 1293 |
button_small_radius="8px",
|
| 1294 |
)
|
|
|
|
| 1308 |
app.theme = custom_theme
|
| 1309 |
app.css = CUSTOM_CSS
|
| 1310 |
app.js = DARK_MODE_JS
|
| 1311 |
+
# Header
|
| 1312 |
+
with gr.Row():
|
| 1313 |
+
with gr.Column():
|
| 1314 |
gr.HTML(
|
| 1315 |
"""
|
| 1316 |
+
<div style="display: flex; align-items: center; justify-content: space-between; padding: 20px 0; margin-bottom: 8px;">
|
| 1317 |
<div style="display: flex; align-items: center; gap: 16px;">
|
| 1318 |
+
<div style="width: 52px; height: 52px; background: linear-gradient(135deg, rgba(139, 92, 246, 0.15), rgba(34, 197, 94, 0.1)); border: 1px solid rgba(139, 92, 246, 0.3); border-radius: 14px; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 30px rgba(139, 92, 246, 0.2);">
|
| 1319 |
+
<span style="font-size: 26px;">β¨</span>
|
| 1320 |
</div>
|
| 1321 |
<div>
|
| 1322 |
+
<h1 style="margin: 0; background: linear-gradient(135deg, #8b5cf6, #22c55e); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; font-size: 28px; font-weight: 800; letter-spacing: -0.5px;">DevRel Campaign Generator</h1>
|
| 1323 |
+
<p style="margin: 4px 0 0 0; color: var(--text-muted, #71717a); font-size: 14px;">AI-Powered Content for Developer Relations</p>
|
| 1324 |
</div>
|
| 1325 |
</div>
|
| 1326 |
+
<div style="display: flex; align-items: center; gap: 10px; padding: 10px 18px; background: rgba(34, 197, 94, 0.1); border: 1px solid rgba(34, 197, 94, 0.2); border-radius: 24px;">
|
| 1327 |
<div style="width: 10px; height: 10px; border-radius: 50%; background: #22c55e; animation: pulse 2s infinite; box-shadow: 0 0 12px rgba(34, 197, 94, 0.6);"></div>
|
| 1328 |
<span style="font-size: 13px; font-weight: 600; color: #22c55e;">System Online</span>
|
| 1329 |
</div>
|
|
|
|
| 1342 |
with gr.Column():
|
| 1343 |
gr.HTML(
|
| 1344 |
"""
|
| 1345 |
+
<div style="background: var(--bg-card, #ffffff); border: 1px solid var(--border-color, #e4e4e7); border-radius: 20px; padding: 32px; margin-bottom: 24px; box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1)); transition: all 0.3s ease;">
|
| 1346 |
<!-- Header -->
|
| 1347 |
<div style="display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 24px;">
|
| 1348 |
<div style="display: flex; align-items: center; gap: 16px;">
|
|
|
|
| 1458 |
with gr.Group(elem_classes=["command-center-card"]):
|
| 1459 |
gr.HTML(
|
| 1460 |
"""
|
| 1461 |
+
<div style="display: flex; align-items: center; gap: 14px; margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border-color, #e4e4e7);">
|
| 1462 |
+
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, rgba(139, 92, 246, 0.2), rgba(139, 92, 246, 0.05)); border: 1px solid rgba(139, 92, 246, 0.3); border-radius: 14px; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 20px rgba(139, 92, 246, 0.15);">
|
| 1463 |
+
<span style="font-size: 24px;">π</span>
|
| 1464 |
+
</div>
|
| 1465 |
+
<div>
|
| 1466 |
+
<h3 style="margin: 0; font-size: 20px; font-weight: 700; color: var(--text-primary, #18181b);">Command Center</h3>
|
| 1467 |
+
<p style="margin: 4px 0 0 0; color: var(--text-muted, #71717a); font-size: 13px;">Configure and launch your campaign</p>
|
|
|
|
|
|
|
| 1468 |
</div>
|
| 1469 |
</div>
|
| 1470 |
"""
|
|
|
|
| 1491 |
# Settings Accordion for API Keys
|
| 1492 |
with gr.Accordion("βοΈ Settings (API Keys)", open=False):
|
| 1493 |
gr.HTML(
|
| 1494 |
+
'<div style="padding: 12px 0; color: var(--text-muted, #71717a); font-size: 13px;">π‘ Add your own API keys if the default quota is exhausted</div>'
|
| 1495 |
)
|
| 1496 |
anthropic_key = gr.Textbox(
|
| 1497 |
label="Anthropic API Key (Claude)",
|
|
|
|
| 1506 |
lines=1,
|
| 1507 |
)
|
| 1508 |
gr.HTML(
|
| 1509 |
+
'''<div style="padding: 12px 0; color: var(--text-muted, #71717a); font-size: 13px;">
|
| 1510 |
<p style="margin: 0 0 8px 0;">π <a href="https://console.anthropic.com" target="_blank" style="color: #8b5cf6; text-decoration: none; font-weight: 500;">Get Anthropic API Key β</a></p>
|
| 1511 |
<p style="margin: 0;">π <a href="https://github.com/settings/tokens" target="_blank" style="color: #22c55e; text-decoration: none; font-weight: 500;">Get GitHub Token β</a></p>
|
| 1512 |
</div>'''
|
|
|
|
| 1524 |
with gr.Group(elem_classes=["pipeline-status-card"]):
|
| 1525 |
gr.HTML(
|
| 1526 |
"""
|
| 1527 |
+
<div style="display: flex; align-items: center; gap: 14px; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--border-color, #e4e4e7);">
|
| 1528 |
+
<div style="width: 44px; height: 44px; background: linear-gradient(135deg, rgba(34, 197, 94, 0.2), rgba(34, 197, 94, 0.05)); border: 1px solid rgba(34, 197, 94, 0.3); border-radius: 12px; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 20px rgba(34, 197, 94, 0.15);">
|
| 1529 |
+
<span style="font-size: 22px;">π</span>
|
| 1530 |
+
</div>
|
| 1531 |
+
<div>
|
| 1532 |
+
<h3 style="margin: 0; font-size: 18px; font-weight: 700; color: var(--text-primary, #18181b);">Pipeline Status</h3>
|
| 1533 |
+
<p style="margin: 4px 0 0 0; color: var(--text-muted, #71717a); font-size: 12px;">Real-time generation progress</p>
|
|
|
|
|
|
|
| 1534 |
</div>
|
| 1535 |
</div>
|
| 1536 |
"""
|
|
|
|
| 1542 |
# Event Log Section Header
|
| 1543 |
gr.HTML(
|
| 1544 |
"""
|
| 1545 |
+
<div style="margin-top: 16px; border-top: 1px solid var(--border-color, #e4e4e7); padding-top: 16px;">
|
| 1546 |
+
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;">
|
| 1547 |
<div style="display: flex; align-items: center; gap: 12px;">
|
| 1548 |
<div style="display: flex; gap: 6px;">
|
| 1549 |
<div style="width: 12px; height: 12px; border-radius: 50%; background: linear-gradient(135deg, #ef4444, #dc2626); box-shadow: 0 0 6px rgba(239, 68, 68, 0.4);"></div>
|
|
|
|
| 1552 |
</div>
|
| 1553 |
<span style="font-weight: 600; color: var(--text-primary, #18181b); font-size: 14px;">Event Log</span>
|
| 1554 |
</div>
|
| 1555 |
+
<div style="display: flex; align-items: center; gap: 6px; padding: 4px 12px; background: rgba(34, 197, 94, 0.1); border: 1px solid rgba(34, 197, 94, 0.25); border-radius: 16px;">
|
| 1556 |
<div style="width: 6px; height: 6px; border-radius: 50%; background: #22c55e; animation: pulse 2s infinite; box-shadow: 0 0 8px rgba(34, 197, 94, 0.6);"></div>
|
| 1557 |
+
<span style="color: #22c55e; font-size: 11px; font-weight: 600;">LIVE</span>
|
| 1558 |
</div>
|
| 1559 |
</div>
|
| 1560 |
</div>
|
|
|
|
| 1570 |
# Footer
|
| 1571 |
gr.HTML(
|
| 1572 |
"""
|
| 1573 |
+
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border-color, #e4e4e7); font-size: 12px;">
|
| 1574 |
+
<div style="display: flex; align-items: center; gap: 12px;">
|
| 1575 |
+
<span style="color: var(--text-muted, #71717a);">Powered by:</span>
|
| 1576 |
+
<span style="background: linear-gradient(135deg, rgba(139, 92, 246, 0.15), rgba(139, 92, 246, 0.05)); color: #8b5cf6; padding: 4px 12px; border-radius: 14px; font-weight: 600; font-size: 11px; border: 1px solid rgba(139, 92, 246, 0.2);">Claude</span>
|
| 1577 |
+
<span style="color: var(--text-muted, #71717a);">Γ</span>
|
| 1578 |
+
<span style="background: linear-gradient(135deg, rgba(249, 115, 22, 0.15), rgba(249, 115, 22, 0.05)); color: #f97316; padding: 4px 12px; border-radius: 14px; font-weight: 600; font-size: 11px; border: 1px solid rgba(249, 115, 22, 0.2);">Gradio 6</span>
|
| 1579 |
</div>
|
| 1580 |
</div>
|
| 1581 |
"""
|
|
|
|
| 1587 |
with gr.Group(elem_classes=["campaign-output-card"]):
|
| 1588 |
gr.HTML(
|
| 1589 |
"""
|
| 1590 |
+
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border-color, #e4e4e7);">
|
| 1591 |
+
<div style="display: flex; align-items: center; gap: 14px;">
|
| 1592 |
+
<div style="width: 48px; height: 48px; background: linear-gradient(135deg, rgba(34, 197, 94, 0.2), rgba(6, 182, 212, 0.1)); border: 1px solid rgba(34, 197, 94, 0.3); border-radius: 14px; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 20px rgba(34, 197, 94, 0.15);">
|
| 1593 |
+
<span style="font-size: 24px;">π€</span>
|
| 1594 |
</div>
|
| 1595 |
<div>
|
| 1596 |
+
<h3 style="margin: 0; font-size: 20px; font-weight: 700; color: var(--text-primary, #18181b);">Campaign Output</h3>
|
| 1597 |
+
<p style="margin: 4px 0 0 0; color: var(--text-muted, #71717a); font-size: 13px;">Generated content for all platforms</p>
|
| 1598 |
</div>
|
| 1599 |
</div>
|
| 1600 |
+
<div style="display: flex; gap: 10px;">
|
| 1601 |
+
<span style="background: rgba(34, 197, 94, 0.1); color: #22c55e; padding: 6px 14px; border-radius: 16px; font-size: 12px; font-weight: 600; border: 1px solid rgba(34, 197, 94, 0.2);">6 Formats</span>
|
| 1602 |
</div>
|
| 1603 |
</div>
|
| 1604 |
"""
|
|
|
|
| 1686 |
app = create_app()
|
| 1687 |
app.launch(
|
| 1688 |
server_name="0.0.0.0",
|
| 1689 |
+
server_port=7860,
|
| 1690 |
+
share=False,
|
| 1691 |
show_error=True,
|
| 1692 |
ssr_mode=False, # Disable experimental SSR to avoid potential issues
|
| 1693 |
)
|