Spaces:
Running
Running
| # ui_components.py | |
| """UI components and helper functions for PPT Generator""" | |
| import gradio as gr | |
| from typing import List, Dict, Tuple | |
| from constants import STYLE_TEMPLATES, PPT_TEMPLATES, DESIGN_THEMES, EXAMPLE_TOPICS, AUDIENCE_TYPES | |
| from content_utils import generate_dynamic_slides | |
| def create_custom_slides_ui(initial_count=5): | |
| """Custom slides configuration UI (3-20 slides)""" | |
| slides = [] | |
| for i in range(20): # Max 20 slides | |
| row = gr.Row(visible=(i < initial_count)) | |
| with row: | |
| with gr.Column(scale=2): | |
| title = gr.Textbox( | |
| label=f"Slide {i+1} Title", | |
| placeholder="e.g., Current Analysis, Solution, Roadmap...", | |
| ) | |
| with gr.Column(scale=3): | |
| style = gr.Dropdown( | |
| choices=list(STYLE_TEMPLATES.keys()), | |
| label=f"Style Selection", | |
| value="Colorful Mind Map" | |
| ) | |
| with gr.Column(scale=3): | |
| hint = gr.Textbox( | |
| label=f"Prompt Hint", | |
| placeholder="Content to express in this slide" | |
| ) | |
| slides.append({"title": title, "style": style, "hint": hint, "row": row}) | |
| return slides | |
| def load_example(template_name, language): | |
| """Load example topic for template""" | |
| lang_key = "Korean" if language == "Korean" else "English" | |
| example_topic = EXAMPLE_TOPICS[lang_key].get(template_name, "") | |
| return example_topic | |
| def update_audience_info(audience_type): | |
| """Display audience information""" | |
| info = AUDIENCE_TYPES.get(audience_type, {}) | |
| return f"""**{info.get('description', '')}** | |
| - Tone: {info.get('tone', '')} | |
| - Focus: {info.get('focus', '')}""" | |
| def update_theme_preview(theme_name): | |
| """Generate theme preview HTML""" | |
| theme = DESIGN_THEMES.get(theme_name, DESIGN_THEMES["Minimal Light"]) | |
| # Convert RGB to hex | |
| def rgb_to_hex(rgb_color): | |
| return f"#{rgb_color[0]:02x}{rgb_color[1]:02x}{rgb_color[2]:02x}" | |
| bg_hex = rgb_to_hex(theme["background"]) | |
| box_hex = rgb_to_hex(theme["box_fill"]) | |
| title_hex = rgb_to_hex(theme["title_color"]) | |
| text_hex = rgb_to_hex(theme["text_color"]) | |
| accent_hex = rgb_to_hex(theme["accent_color"]) | |
| preview_html = f""" | |
| <div style=" | |
| background: {bg_hex}; | |
| padding: 20px; | |
| border-radius: 8px; | |
| margin: 10px 0; | |
| "> | |
| <div style=" | |
| background: {box_hex}; | |
| opacity: {theme['box_opacity']}; | |
| padding: 15px; | |
| border-radius: 12px; | |
| margin-bottom: 10px; | |
| {'box-shadow: 0 4px 8px rgba(0,0,0,0.1);' if theme['shadow'] else ''} | |
| "> | |
| <h4 style="color: {title_hex}; margin: 0 0 10px 0;">{theme['name']}</h4> | |
| <p style="color: {text_hex}; margin: 0; font-size: 14px;"> | |
| {theme['description']} | |
| </p> | |
| <div style=" | |
| width: 40px; | |
| height: 4px; | |
| background: {accent_hex}; | |
| margin-top: 10px; | |
| border-radius: 2px; | |
| "></div> | |
| </div> | |
| </div> | |
| """ | |
| return preview_html | |
| def update_template_info(template_name, slide_count): | |
| is_custom = template_name == "Custom" | |
| info = "" | |
| if not is_custom and template_name in PPT_TEMPLATES: | |
| template = PPT_TEMPLATES[template_name] | |
| info = f"**{template['description']}**\n\n" | |
| # Show dynamically generated slide composition | |
| slides = generate_dynamic_slides("", template, slide_count) | |
| info += f"Slides to be generated ({len(slides)} total):\n" | |
| for i, slide in enumerate(slides): | |
| style_info = STYLE_TEMPLATES.get(slide['style'], {}) | |
| info += f"{i+1}. {slide['title']} - {style_info.get('use_case', '')}" | |
| if style_info.get('is_process_flow'): | |
| info += " ๐ง" | |
| info += "\n" | |
| elif is_custom: | |
| info = "**Custom Template**\n\nConfigure your slides directly in the 'Custom Slide Configuration' section below." | |
| # Hide slide count selection for custom template | |
| slide_count_visible = not is_custom | |
| custom_accordion_open = is_custom | |
| return info, gr.update(visible=slide_count_visible), gr.update(open=custom_accordion_open) | |
| def update_custom_slides_visibility(count): | |
| """Update UI visibility based on custom slide count""" | |
| updates = [] | |
| for i in range(20): | |
| updates.append(gr.update(visible=(i < count))) # row | |
| return updates | |
| def clear_all(): | |
| """๋ชจ๋ ๋ด์ฉ ์ด๊ธฐํ""" | |
| return "", "", "", None, "๐ ์ด๊ธฐํ๋์์ต๋๋ค." | |
| def get_css(): | |
| """Get custom CSS for the interface""" | |
| return """ | |
| .preview-container { max-width: 1400px; margin: 0 auto; } | |
| .slide-container { transition: all 0.3s ease; } | |
| .slide-container:hover { transform: translateY(-2px); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15) !important; } | |
| #custom_accordion .form { | |
| max-height: 600px; | |
| overflow-y: auto; | |
| padding-right: 10px; | |
| } | |
| #custom_accordion .form::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| #custom_accordion .form::-webkit-scrollbar-track { | |
| background: #f1f1f1; | |
| border-radius: 3px; | |
| } | |
| #custom_accordion .form::-webkit-scrollbar-thumb { | |
| background: #888; | |
| border-radius: 3px; | |
| } | |
| #custom_accordion .form::-webkit-scrollbar-thumb:hover { | |
| background: #555; | |
| } | |
| .supervisor-box textarea { | |
| border-left: 4px solid #667eea !important; | |
| padding-left: 10px !important; | |
| } | |
| .researcher-box textarea { | |
| border-left: 4px solid #10b981 !important; | |
| padding-left: 10px !important; | |
| } | |
| .executor-box textarea { | |
| border-left: 4px solid #764ba2 !important; | |
| padding-left: 10px !important; | |
| } | |
| """ | |
| def get_usage_instructions(): | |
| """Get usage instructions markdown""" | |
| return """ | |
| ### ๐ Workflow: | |
| 1. **Select Language**: Choose English or Korean for your presentation content | |
| 2. **Load Example** or enter your own topic | |
| 3. **Select Audience**: Content will be automatically optimized for your target audience | |
| 4. **Choose Template and Theme**, then click generate | |
| 5. **Download**: Download the PPTX file when generation is complete | |
| ### ๐ค 3-AI Collaboration System: | |
| - **Supervisor AI**: Designs PPT structure and provides guidance | |
| - **Researcher AI**: Searches and organizes content information | |
| - **Executor AI**: Creates actual PPT slides | |
| ### ๐ Language Support: | |
| - **English**: Default interface language with English content generation | |
| - **Korean**: Select for Korean content generation (full Korean PPT support) | |
| ### ๐ญ Audience Features: | |
| - **Executives/C-Level**: Strategic value, ROI, business impact focus | |
| - **Investors**: Market opportunity, growth potential, profitability emphasis | |
| - **Technical Team**: Technical details, implementation methods, performance metrics | |
| - **General Staff**: Practical content, collaboration methods, execution plans | |
| - **Customers/Partners**: Customer value, benefits, success stories | |
| - **General Public**: Easy explanations, usability, practical benefits | |
| ### ๐ก Text Style Features: | |
| - **Concise noun-ending style**: Ends with nouns or short phrases | |
| - **Emoji usage**: Relevant emojis automatically added before each point | |
| - **8-12 words**: Each bullet point is very concise | |
| ### ๐ Custom Slides: | |
| - **Build your own**: Activated when selecting "Custom" template | |
| - **3-20 slides freely**: Choose number of slides with slider | |
| - **Style per slide**: Choose from 16 styles for each slide | |
| - **Provide hints**: Guide content direction with prompt hints | |
| ### ๐ง Process Flow Diagrams: | |
| - **Automatic generation** for Business Workflow or Flowchart styles | |
| - Full support for both English and Korean text | |
| - Process, decision, input/output node types supported | |
| """ |