kshitijthakkar
commited on
Commit
Β·
db58867
1
Parent(s):
f68f944
fixed panel colors
Browse files- outage_odyssey_ui.py +147 -59
outage_odyssey_ui.py
CHANGED
@@ -548,45 +548,155 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
548 |
|
549 |
|
550 |
def create_app(self):
|
|
|
551 |
import gradio as gr
|
552 |
|
553 |
-
# Custom CSS for dark
|
554 |
custom_css = """
|
555 |
-
|
556 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
557 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
558 |
.panel {
|
559 |
-
background:
|
560 |
backdrop-filter: blur(10px);
|
561 |
border-radius: 10px;
|
562 |
-
border: 1px solid
|
563 |
-
box-shadow: 0 4px 8px
|
564 |
padding: 16px;
|
565 |
}
|
566 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
567 |
"""
|
568 |
|
569 |
with gr.Blocks(theme="soft", fill_height=True, css=custom_css) as demo:
|
570 |
-
# Add session state to store session-specific data
|
571 |
session_state = gr.State({})
|
572 |
stored_messages = gr.State([])
|
573 |
file_uploads_log = gr.State([])
|
574 |
|
575 |
## Header
|
576 |
gr.HTML("""
|
577 |
-
<div
|
578 |
-
<h1 style="color: white; margin: 0; font-size: 2.5em;">π¨ Outage Odyssey π§©</h1>
|
579 |
-
<p style="color: white; margin: 10px 0 0 0; font-size: 1.2em;">Transform boring incidents into hilarious learning experiences!</p>
|
580 |
-
</div>
|
581 |
""")
|
582 |
-
with gr.Tab("
|
583 |
with gr.Row():
|
584 |
with gr.Column(scale=1):
|
585 |
with gr.Group():
|
586 |
-
|
587 |
-
|
588 |
|
589 |
-
# Quick templates dropdown (unchanged)
|
590 |
with gr.Row(elem_classes="panel"):
|
591 |
template_dropdown = gr.Dropdown(
|
592 |
choices=["server_down", "database_slow", "network_issue", "security_breach"],
|
@@ -594,29 +704,20 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
594 |
value=None,
|
595 |
)
|
596 |
|
597 |
-
# Text input box (by default itβs white; leave as-is or wrap in panel if you want)
|
598 |
text_input = gr.Textbox(
|
599 |
lines=8,
|
600 |
label="Describe your IT incident",
|
601 |
-
container=False,
|
602 |
placeholder="Paste your incident report here or describe what went wrong...",
|
603 |
-
|
604 |
)
|
605 |
|
606 |
submit_btn = gr.Button("β¨ Generate Comic Story", variant="primary", size="lg")
|
607 |
|
608 |
-
|
609 |
-
if template_type:
|
610 |
-
return self.get_incident_template(template_type)
|
611 |
-
return ""
|
612 |
-
|
613 |
-
template_dropdown.change(load_template, [template_dropdown], [text_input])
|
614 |
|
615 |
-
# File upload section
|
616 |
if self.file_upload_folder is not None:
|
617 |
with gr.Group():
|
618 |
-
|
619 |
-
gr.Markdown("### π **Upload Incident Files**")
|
620 |
upload_file = gr.File(
|
621 |
label="Upload incident reports, logs, or documentation",
|
622 |
file_types=[".pdf", ".docx", ".txt", ".json", ".log", ".csv", ".xlsx"]
|
@@ -627,12 +728,12 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
627 |
[upload_file, file_uploads_log],
|
628 |
[upload_status, file_uploads_log],
|
629 |
)
|
630 |
-
with gr.Accordion("βΉοΈ Note on Incident Template", open=False
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
gr.Markdown("""
|
637 |
### π― **What Outage Odyssey does:**
|
638 |
1. **π Analyze** your IT incident
|
@@ -651,7 +752,6 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
651 |
|
652 |
with gr.Column(scale=2):
|
653 |
with gr.Group():
|
654 |
-
# Main chat interface (already has elem_classes="chatbot")
|
655 |
chatbot = gr.Chatbot(
|
656 |
label="π€ Outage Odyssey Agent",
|
657 |
type="messages",
|
@@ -665,22 +765,18 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
665 |
{"left": r"$$", "right": r"$$", "display": True},
|
666 |
{"left": r"$", "right": r"$", "display": False},
|
667 |
],
|
668 |
-
elem_classes="chatbot"
|
669 |
)
|
670 |
-
with gr.Accordion("βΉοΈ Note on generated Image", open=False
|
|
|
671 |
gr.Markdown("""
|
672 |
-
|
673 |
-
|
674 |
with gr.Tab("Generated Images"):
|
675 |
with gr.Row():
|
676 |
with gr.Column():
|
677 |
-
|
678 |
-
# Markdown for the gallery section
|
679 |
gr.Markdown("### π¨ **Generated Comic Panels**", elem_classes="panel")
|
680 |
-
# Button to trigger image generation
|
681 |
generate_image_button = gr.Button("π Refresh Comic Panel")
|
682 |
-
|
683 |
-
# Gallery to display generated images
|
684 |
image_gallery = gr.Gallery(
|
685 |
label="Comic Panels",
|
686 |
show_label=True,
|
@@ -688,23 +784,21 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
688 |
rows=5,
|
689 |
height="auto",
|
690 |
elem_classes="gallery",
|
691 |
-
value=self.update_gallery()
|
692 |
)
|
693 |
-
# Connect the button click to the function that generates and updates the gallery
|
694 |
generate_image_button.click(
|
695 |
fn=self.update_gallery,
|
696 |
-
outputs=image_gallery
|
697 |
)
|
698 |
|
699 |
with gr.Tab("About"):
|
700 |
with gr.Row():
|
701 |
-
# About section
|
702 |
with gr.Column(scale=1):
|
703 |
gr.Markdown("""
|
704 |
### π€ **About Outage Odyssey**
|
705 |
Outage Odyssey is a fun and educational tool that transforms IT incidents into engaging comic stories!
|
706 |
Upload your incident reports, describe what went wrong, and watch as we analyze the root cause, generate solutions, and create a hilarious comic strip to help you learn from IT mishaps.
|
707 |
-
|
708 |
### π **Powered by:**
|
709 |
- [HuggingFace](https://huggingface.co/)
|
710 |
- [Gradio](https://gradio.app/)
|
@@ -714,23 +808,18 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
714 |
- [Nebius](https://nebius.com/)
|
715 |
- [Mistral](https://mistral.ai/)
|
716 |
- [Hyperbolic](https://hyperbolic.xyz/)
|
717 |
-
|
718 |
### π **Making IT incidents fun to learn from, one comic at a time!**
|
719 |
""", elem_classes="panel")
|
720 |
-
# Add a link to the GitHub repository
|
721 |
gr.Markdown("""
|
722 |
### π **Source Code**
|
723 |
Check out the source code on [GitHub](https://github.com/Mandark-droid/OutageOdyssey)
|
724 |
""", elem_classes="panel")
|
725 |
-
|
726 |
|
727 |
-
# Footer
|
728 |
gr.HTML("""
|
729 |
-
<div
|
730 |
-
<p style="
|
731 |
-
<p style="color: #777; font-size: 0.9em;">Making IT incidents fun to learn from, one comic at a time! π</p>
|
732 |
-
<p style="color: #777; font-size: 0.5em;">Developed by <strong><a href="https://huggingface.co/kshitijthakkar" target="_blank">Kshitij Thakkar</a></strong> β Building smart tools for better learning experiences. Β© 2025</p>
|
733 |
-
</div>
|
734 |
""")
|
735 |
|
736 |
# Set up event handlers
|
@@ -776,7 +865,6 @@ Actions taken: Rolled back changes, investigating access controls"""
|
|
776 |
|
777 |
return demo
|
778 |
|
779 |
-
|
780 |
# Backward compatibility aliases
|
781 |
class ITOpsComicUI(OutageOdysseyUI):
|
782 |
"""Alias for backward compatibility"""
|
|
|
548 |
|
549 |
|
550 |
def create_app(self):
|
551 |
+
# Import Gradio inside the method if it's a class method like this
|
552 |
import gradio as gr
|
553 |
|
554 |
+
# Custom CSS for dark and light mode compatibility, while respecting Gradio's soft theme
|
555 |
custom_css = """
|
556 |
+
/* Define CSS variables for light and dark modes */
|
557 |
+
:root {
|
558 |
+
/* These variables will define colors for your custom elements */
|
559 |
+
--header-gradient-start-light: #ff6b6b;
|
560 |
+
--header-gradient-end-light: #4ecdc4;
|
561 |
+
--header-text-light: white;
|
562 |
+
|
563 |
+
--panel-bg-light: rgba(255, 122, 127, 0.1); /* Lighter, less opaque for soft theme */
|
564 |
+
--panel-border-light: rgba(255, 255, 255, 0.4);
|
565 |
+
--panel-shadow-light: rgba(0,0,0,0.08);
|
566 |
+
|
567 |
+
--footer-text-light: #666; /* Adjust to match soft theme's subdued text */
|
568 |
+
--footer-link-light: #333; /* Adjust to match soft theme's primary text/link color */
|
569 |
+
--footer-border-light: #ccc;
|
570 |
}
|
571 |
+
|
572 |
+
/* Gradio adds a 'dark' class to the body when in dark mode */
|
573 |
+
body.dark {
|
574 |
+
--header-gradient-start-dark: #8b0000; /* Darker red for header */
|
575 |
+
--header-gradient-end-dark: #005a5a; /* Darker teal for header */
|
576 |
+
--header-text-dark: white; /* Often still white in dark mode headers */
|
577 |
+
|
578 |
+
--panel-bg-dark: rgba(255, 122, 127, 0.05); /* Even less opaque in dark mode */
|
579 |
+
--panel-border-dark: rgba(0, 0, 0, 0.3);
|
580 |
+
--panel-shadow-dark: rgba(0,0,0,0.5);
|
581 |
+
|
582 |
+
--footer-text-dark: #a0a0a0; /* Lighter for dark mode */
|
583 |
+
--footer-link-dark: #e0e0e0; /* Lighter for dark mode */
|
584 |
+
--footer-border-dark: #555;
|
585 |
+
}
|
586 |
+
|
587 |
+
/* --- Custom Styles Applied to Specific Elements --- */
|
588 |
+
|
589 |
+
/* Main Gradio container - Remove background override for full theme */
|
590 |
+
/* .gradio-container {
|
591 |
+
// REMOVE THIS RULE if you want Gradio's theme background
|
592 |
+
// background: linear-gradient(var(--gradient-start-light), var(--gradient-end-light));
|
593 |
+
}
|
594 |
+
body.dark .gradio-container {
|
595 |
+
// background: linear-gradient(var(--gradient-start-dark), var(--gradient-end-dark));
|
596 |
+
} */
|
597 |
+
|
598 |
+
|
599 |
+
/* Custom Header Styling */
|
600 |
+
.header-container {
|
601 |
+
text-align: center;
|
602 |
+
padding: 20px;
|
603 |
+
background: linear-gradient(90deg, var(--header-gradient-start-light), var(--header-gradient-end-light));
|
604 |
+
border-radius: 15px;
|
605 |
+
margin-bottom: 20px;
|
606 |
+
}
|
607 |
+
|
608 |
+
body.dark .header-container {
|
609 |
+
background: linear-gradient(90deg, var(--header-gradient-start-dark), var(--header-gradient-end-dark));
|
610 |
+
}
|
611 |
+
|
612 |
+
.header-container h1 {
|
613 |
+
color: var(--header-text-light);
|
614 |
+
margin: 0;
|
615 |
+
font-size: 2.5em;
|
616 |
+
}
|
617 |
+
body.dark .header-container h1 {
|
618 |
+
color: var(--header-text-dark);
|
619 |
+
}
|
620 |
+
|
621 |
+
.header-container p {
|
622 |
+
color: var(--header-text-light);
|
623 |
+
margin: 10px 0 0 0;
|
624 |
+
font-size: 1.2em;
|
625 |
+
}
|
626 |
+
body.dark .header-container p {
|
627 |
+
color: var(--header-text-dark);
|
628 |
+
}
|
629 |
+
|
630 |
+
|
631 |
+
/* Custom Panel Styling */
|
632 |
.panel {
|
633 |
+
background: var(--panel-bg-light);
|
634 |
backdrop-filter: blur(10px);
|
635 |
border-radius: 10px;
|
636 |
+
border: 1px solid var(--panel-border-light);
|
637 |
+
box-shadow: 0 4px 8px var(--panel-shadow-light);
|
638 |
padding: 16px;
|
639 |
}
|
640 |
+
|
641 |
+
body.dark .panel {
|
642 |
+
background: var(--panel-bg-dark);
|
643 |
+
border: 1px solid var(--panel-border-dark);
|
644 |
+
box-shadow: 0 4px 8px var(--panel-shadow-dark);
|
645 |
+
}
|
646 |
+
|
647 |
+
/* Footer Styling */
|
648 |
+
.footer-container {
|
649 |
+
text-align: center;
|
650 |
+
padding: 20px;
|
651 |
+
margin-top: 20px;
|
652 |
+
border-top: 1px solid var(--footer-border-light); /* Use variable for border */
|
653 |
+
}
|
654 |
+
body.dark .footer-container {
|
655 |
+
border-top: 1px solid var(--footer-border-dark);
|
656 |
+
}
|
657 |
+
|
658 |
+
.footer-container p {
|
659 |
+
color: var(--footer-text-light);
|
660 |
+
}
|
661 |
+
body.dark .footer-container p {
|
662 |
+
color: var(--footer-text-dark);
|
663 |
+
}
|
664 |
+
|
665 |
+
.footer-container a {
|
666 |
+
color: var(--footer-link-light);
|
667 |
+
text-decoration: none; /* Optional: remove underline by default */
|
668 |
+
}
|
669 |
+
body.dark .footer-container a {
|
670 |
+
color: var(--footer-link-dark);
|
671 |
+
}
|
672 |
+
|
673 |
+
.footer-container a:hover {
|
674 |
+
text-decoration: underline; /* Optional: add underline on hover */
|
675 |
+
}
|
676 |
+
|
677 |
+
/* Ensure Markdown elements within panels also respect theme colors */
|
678 |
+
/* Gradio usually handles this well, but explicit rules can be added if needed */
|
679 |
+
.panel h3, .panel p, .panel li {
|
680 |
+
color: inherit; /* Inherit color from parent or Gradio's theme */
|
681 |
+
}
|
682 |
"""
|
683 |
|
684 |
with gr.Blocks(theme="soft", fill_height=True, css=custom_css) as demo:
|
|
|
685 |
session_state = gr.State({})
|
686 |
stored_messages = gr.State([])
|
687 |
file_uploads_log = gr.State([])
|
688 |
|
689 |
## Header
|
690 |
gr.HTML("""
|
691 |
+
<div class="header-container"> <h1>π¨ Outage Odyssey π§©</h1> <p>Transform boring incidents into hilarious learning experiences!</p> </div>
|
|
|
|
|
|
|
692 |
""")
|
693 |
+
with gr.Tab("The Outage Portal"):
|
694 |
with gr.Row():
|
695 |
with gr.Column(scale=1):
|
696 |
with gr.Group():
|
697 |
+
gr.Markdown("### π¨ **Incident Input**",
|
698 |
+
elem_classes="panel") # Apply panel class to Markdown if desired
|
699 |
|
|
|
700 |
with gr.Row(elem_classes="panel"):
|
701 |
template_dropdown = gr.Dropdown(
|
702 |
choices=["server_down", "database_slow", "network_issue", "security_breach"],
|
|
|
704 |
value=None,
|
705 |
)
|
706 |
|
|
|
707 |
text_input = gr.Textbox(
|
708 |
lines=8,
|
709 |
label="Describe your IT incident",
|
710 |
+
container=False, # This means it won't be wrapped in a default Gradio container
|
711 |
placeholder="Paste your incident report here or describe what went wrong...",
|
|
|
712 |
)
|
713 |
|
714 |
submit_btn = gr.Button("β¨ Generate Comic Story", variant="primary", size="lg")
|
715 |
|
716 |
+
template_dropdown.change(self.get_incident_template, [template_dropdown], [text_input])
|
|
|
|
|
|
|
|
|
|
|
717 |
|
|
|
718 |
if self.file_upload_folder is not None:
|
719 |
with gr.Group():
|
720 |
+
gr.Markdown("### π **Upload Incident Files**", elem_classes="panel")
|
|
|
721 |
upload_file = gr.File(
|
722 |
label="Upload incident reports, logs, or documentation",
|
723 |
file_types=[".pdf", ".docx", ".txt", ".json", ".log", ".csv", ".xlsx"]
|
|
|
728 |
[upload_file, file_uploads_log],
|
729 |
[upload_status, file_uploads_log],
|
730 |
)
|
731 |
+
with gr.Accordion("βΉοΈ Note on Incident Template", open=False,
|
732 |
+
elem_classes="panel"): # Apply panel class
|
733 |
+
gr.Markdown("""
|
734 |
+
> β οΈ **Note:** The incident templates are just examples to help you get started. Feel free to modify them or describe your own incidents in detail. The more specific you are, the better the analysis and comic story will be!""")
|
735 |
+
|
736 |
+
with gr.Accordion("βΉοΈ How it works", open=False, elem_classes="panel"): # Apply panel class
|
737 |
gr.Markdown("""
|
738 |
### π― **What Outage Odyssey does:**
|
739 |
1. **π Analyze** your IT incident
|
|
|
752 |
|
753 |
with gr.Column(scale=2):
|
754 |
with gr.Group():
|
|
|
755 |
chatbot = gr.Chatbot(
|
756 |
label="π€ Outage Odyssey Agent",
|
757 |
type="messages",
|
|
|
765 |
{"left": r"$$", "right": r"$$", "display": True},
|
766 |
{"left": r"$", "right": r"$", "display": False},
|
767 |
],
|
768 |
+
elem_classes="chatbot"
|
769 |
)
|
770 |
+
with gr.Accordion("βΉοΈ Note on generated Image", open=False,
|
771 |
+
elem_classes="panel"): # Apply panel class
|
772 |
gr.Markdown("""
|
773 |
+
> β οΈ **Note:** Due to a rendering issue, the generated images may not appear directly in the chatbot window. Please go to the "Generated Images" tab and click the "Refresh" button to view the latest image and download them.
|
774 |
+
""")
|
775 |
with gr.Tab("Generated Images"):
|
776 |
with gr.Row():
|
777 |
with gr.Column():
|
|
|
|
|
778 |
gr.Markdown("### π¨ **Generated Comic Panels**", elem_classes="panel")
|
|
|
779 |
generate_image_button = gr.Button("π Refresh Comic Panel")
|
|
|
|
|
780 |
image_gallery = gr.Gallery(
|
781 |
label="Comic Panels",
|
782 |
show_label=True,
|
|
|
784 |
rows=5,
|
785 |
height="auto",
|
786 |
elem_classes="gallery",
|
787 |
+
value=self.update_gallery()
|
788 |
)
|
|
|
789 |
generate_image_button.click(
|
790 |
fn=self.update_gallery,
|
791 |
+
outputs=image_gallery
|
792 |
)
|
793 |
|
794 |
with gr.Tab("About"):
|
795 |
with gr.Row():
|
|
|
796 |
with gr.Column(scale=1):
|
797 |
gr.Markdown("""
|
798 |
### π€ **About Outage Odyssey**
|
799 |
Outage Odyssey is a fun and educational tool that transforms IT incidents into engaging comic stories!
|
800 |
Upload your incident reports, describe what went wrong, and watch as we analyze the root cause, generate solutions, and create a hilarious comic strip to help you learn from IT mishaps.
|
801 |
+
|
802 |
### π **Powered by:**
|
803 |
- [HuggingFace](https://huggingface.co/)
|
804 |
- [Gradio](https://gradio.app/)
|
|
|
808 |
- [Nebius](https://nebius.com/)
|
809 |
- [Mistral](https://mistral.ai/)
|
810 |
- [Hyperbolic](https://hyperbolic.xyz/)
|
811 |
+
|
812 |
### π **Making IT incidents fun to learn from, one comic at a time!**
|
813 |
""", elem_classes="panel")
|
|
|
814 |
gr.Markdown("""
|
815 |
### π **Source Code**
|
816 |
Check out the source code on [GitHub](https://github.com/Mandark-droid/OutageOdyssey)
|
817 |
""", elem_classes="panel")
|
|
|
818 |
|
819 |
+
# Footer
|
820 |
gr.HTML("""
|
821 |
+
<div class="footer-container"> <p>π <strong>Gradio Agents & MCP Hackathon Project</strong> | Powered by <a href="https://huggingface.co/" target="_blank">HuggingFace</a> | <a href="https://github.com/huggingface/smolagents" target="_blank">smolagents</a> | <a href="https://gradio.app/" target="_blank">Gradio</a> | <a href="https://modelcontextprotocol.io/" target="_blank">MCP</a> | <a href="https://anthropic.com/" target="_blank">Anthropic</a> | <a href="https://openai.com/" target="_blank">OpenAI</a> | <a href="https://nebius.com/" target="_blank">Nebius</a> | <a href="https://mistral.ai/" target="_blank">Mistral</a> | <a href="https://hyperbolic.xyz/" target="_blank">Hyperbolic</a></p>
|
822 |
+
<p style="font-size: 0.9em;">Making IT incidents fun to learn from, one comic at a time! π</p> <p style="font-size: 0.5em;">Developed by <strong><a href="https://huggingface.co/kshitijthakkar" target="_blank">Kshitij Thakkar</a></strong> β Building smart tools for better learning experiences. Β© 2025</p> </div>
|
|
|
|
|
|
|
823 |
""")
|
824 |
|
825 |
# Set up event handlers
|
|
|
865 |
|
866 |
return demo
|
867 |
|
|
|
868 |
# Backward compatibility aliases
|
869 |
class ITOpsComicUI(OutageOdysseyUI):
|
870 |
"""Alias for backward compatibility"""
|