cryogenic22 commited on
Commit
7166956
Β·
verified Β·
1 Parent(s): 6a0a931

Create updated_components.py

Browse files
Files changed (1) hide show
  1. updated_components.py +396 -0
updated_components.py ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from visual_elements import (
3
+ search_stock_images,
4
+ download_image,
5
+ analyze_slide_for_visuals,
6
+ generate_html_preview_with_visuals,
7
+ STANDARD_SHAPES,
8
+ ICON_CATEGORIES
9
+ )
10
+ import os
11
+ import requests
12
+ from PIL import Image
13
+ from io import BytesIO
14
+ import base64
15
+
16
+ def render_enhanced_slide_editor(slide_index, slide, template_name="professional"):
17
+ """Render the enhanced editor for a single slide with visual elements"""
18
+ from utils import TEMPLATES, create_slide_preview
19
+
20
+ # Get template info
21
+ template = TEMPLATES.get(template_name, TEMPLATES["professional"])
22
+ colors = template["colors"]
23
+
24
+ # Split into preview and editor columns
25
+ col1, col2 = st.columns([2, 3])
26
+
27
+ with col1:
28
+ st.subheader("Preview")
29
+ # Generate and display HTML preview with visuals
30
+ try:
31
+ # Use enhanced preview with visuals
32
+ preview_html = generate_html_preview_with_visuals(slide, template_name)
33
+ st.components.v1.html(preview_html, height=400)
34
+ except Exception as e:
35
+ st.error(f"Error generating preview: {str(e)}")
36
+ # Fall back to standard preview
37
+ preview_html = create_slide_preview(slide, template_name)
38
+ st.components.v1.html(preview_html, height=350)
39
+
40
+ # Visual elements analysis
41
+ analysis = analyze_slide_for_visuals(slide)
42
+
43
+ # Quick styling options
44
+ with st.expander("🎨 Layout & Style"):
45
+ # Smart layout suggestion
46
+ suggested_layout = analysis['suggested_layout']
47
+ layout_options = ["Standard", "Two Column", "Title Only", "Quote", "Picture with Caption"]
48
+
49
+ st.write(f"πŸ’‘ **Suggested layout:** {suggested_layout}")
50
+
51
+ selected_layout = st.selectbox(
52
+ "Layout",
53
+ options=layout_options,
54
+ index=layout_options.index(suggested_layout) if suggested_layout in layout_options else 0,
55
+ key=f"layout_{slide_index}"
56
+ )
57
+
58
+ # Color scheme options
59
+ st.write("🎭 **Color Accent**")
60
+ color_options = {
61
+ "Default": colors["accent"],
62
+ "Blue": "#0066CC",
63
+ "Green": "#00AA55",
64
+ "Red": "#CC3300",
65
+ "Purple": "#9933CC",
66
+ "Orange": "#FF6600"
67
+ }
68
+ selected_color = st.color_picker(
69
+ "Accent Color",
70
+ value=colors["accent"],
71
+ key=f"color_{slide_index}"
72
+ )
73
+
74
+ # Apply button
75
+ if st.button("Apply Style", key=f"apply_style_{slide_index}"):
76
+ if "design" not in slide:
77
+ slide["design"] = {}
78
+ slide["design"]["layout"] = selected_layout
79
+ slide["design"]["accent_color"] = selected_color
80
+ st.success("Style applied!")
81
+
82
+ # Visual elements section
83
+ with st.expander("πŸ–ΌοΈ Visual Elements"):
84
+ # Chart options if analysis suggests a chart
85
+ if analysis['need_chart']:
86
+ st.write("πŸ“Š **Chart Recommendation**")
87
+ st.write(f"The content suggests a {analysis['chart_type']} chart would be appropriate.")
88
+
89
+ chart_types = ["column", "bar", "line", "pie", "area", "scatter"]
90
+ selected_chart = st.selectbox(
91
+ "Chart Type",
92
+ options=chart_types,
93
+ index=chart_types.index(analysis['chart_type']) if analysis['chart_type'] in chart_types else 0,
94
+ key=f"chart_{slide_index}"
95
+ )
96
+
97
+ if st.button("Add Chart", key=f"add_chart_{slide_index}"):
98
+ if "visuals" not in slide:
99
+ slide["visuals"] = {}
100
+ slide["visuals"]["chart"] = {
101
+ "type": selected_chart,
102
+ "data": "sample" # Will be replaced with actual data
103
+ }
104
+ st.success(f"Added {selected_chart} chart!")
105
+
106
+ # Image options
107
+ st.write("🏞️ **Images**")
108
+ image_source = st.radio(
109
+ "Image Source",
110
+ ["Stock Images", "Upload Image"],
111
+ key=f"img_source_{slide_index}"
112
+ )
113
+
114
+ if image_source == "Stock Images":
115
+ search_query = st.text_input(
116
+ "Search for images",
117
+ value=analysis['image_query'],
118
+ key=f"img_search_{slide_index}"
119
+ )
120
+
121
+ if st.button("Search", key=f"search_btn_{slide_index}"):
122
+ with st.spinner("Searching for images..."):
123
+ images = search_stock_images(search_query)
124
+
125
+ if not images:
126
+ st.warning("No images found. Try a different search term.")
127
+ else:
128
+ # Store images in session state for this slide
129
+ if "stock_images" not in st.session_state:
130
+ st.session_state.stock_images = {}
131
+ st.session_state.stock_images[slide_index] = images
132
+
133
+ st.success(f"Found {len(images)} images!")
134
+
135
+ # Display stored images if available
136
+ if "stock_images" in st.session_state and slide_index in st.session_state.stock_images:
137
+ images = st.session_state.stock_images[slide_index]
138
+
139
+ # Create a grid of images using columns
140
+ columns = st.columns(3)
141
+
142
+ for i, img in enumerate(images[:6]): # Limit to 6 images
143
+ with columns[i % 3]:
144
+ # Display thumbnail
145
+ st.image(img["thumbnail"], use_column_width=True)
146
+
147
+ if st.button("Select", key=f"select_img_{slide_index}_{i}"):
148
+ # Add image to slide
149
+ if "visuals" not in slide:
150
+ slide["visuals"] = {}
151
+ slide["visuals"]["image"] = {
152
+ "url": img["url"],
153
+ "source": "stock"
154
+ }
155
+ st.success("Image selected!")
156
+ else:
157
+ # Upload image
158
+ uploaded_file = st.file_uploader(
159
+ "Upload an image",
160
+ type=["jpg", "jpeg", "png", "gif"],
161
+ key=f"upload_{slide_index}"
162
+ )
163
+
164
+ if uploaded_file:
165
+ image = Image.open(uploaded_file)
166
+ st.image(image, width=250)
167
+
168
+ if st.button("Use This Image", key=f"use_upload_{slide_index}"):
169
+ # Store image in session state
170
+ if "uploaded_images" not in st.session_state:
171
+ st.session_state.uploaded_images = {}
172
+
173
+ # Convert image to base64 for storage
174
+ buffered = BytesIO()
175
+ image.save(buffered, format="PNG")
176
+ img_str = base64.b64encode(buffered.getvalue()).decode()
177
+
178
+ st.session_state.uploaded_images[slide_index] = img_str
179
+
180
+ # Add to slide
181
+ if "visuals" not in slide:
182
+ slide["visuals"] = {}
183
+ slide["visuals"]["image"] = {
184
+ "data": img_str,
185
+ "source": "upload"
186
+ }
187
+ st.success("Image added to slide!")
188
+
189
+ # Icon options
190
+ st.write("πŸ” **Icons & Shapes**")
191
+
192
+ # Create tabs for different icon categories
193
+ icon_tabs = st.tabs(list(ICON_CATEGORIES.keys()))
194
+
195
+ for i, (category, icons) in enumerate(ICON_CATEGORIES.items()):
196
+ with icon_tabs[i]:
197
+ # Display icons in a grid
198
+ cols = st.columns(4)
199
+ for j, icon in enumerate(icons):
200
+ with cols[j % 4]:
201
+ if st.button(icon, key=f"icon_{slide_index}_{category}_{j}"):
202
+ # Add icon to slide
203
+ if "visuals" not in slide:
204
+ slide["visuals"] = {}
205
+ if "icons" not in slide["visuals"]:
206
+ slide["visuals"]["icons"] = []
207
+
208
+ slide["visuals"]["icons"].append(icon)
209
+ st.success(f"Added {icon} icon!")
210
+
211
+ # AI image generation
212
+ with st.expander("πŸ€– AI Image Generation"):
213
+ st.write("Generate a custom image using AI based on your slide content")
214
+
215
+ # Image prompt
216
+ prompt_base = f"Creating an image for slide '{slide.get('title', '')}'"
217
+ image_prompt = st.text_area(
218
+ "Image description",
219
+ value=prompt_base,
220
+ key=f"img_prompt_{slide_index}",
221
+ height=100
222
+ )
223
+
224
+ image_style = st.selectbox(
225
+ "Style",
226
+ ["Realistic", "Digital Art", "Watercolor", "Minimalist", "Corporate"],
227
+ key=f"img_style_{slide_index}"
228
+ )
229
+
230
+ if st.button("Generate Image", key=f"gen_img_{slide_index}"):
231
+ # In a real implementation, this would call an AI image generation API
232
+ st.info("AI Image generation would be implemented here with your preferred provider (DALL-E, Midjourney, etc.)")
233
+ st.info("For now, we'll use a placeholder to demonstrate the functionality")
234
+
235
+ if "visuals" not in slide:
236
+ slide["visuals"] = {}
237
+ slide["visuals"]["ai_image"] = {
238
+ "prompt": image_prompt,
239
+ "style": image_style
240
+ }
241
+ st.success("AI image generation request saved!")
242
+
243
+ with col2:
244
+ st.subheader("Content Editor")
245
+
246
+ # Title editing with AI assistance
247
+ st.write("##### πŸ“ Slide Title")
248
+ col1, col2 = st.columns([3, 1])
249
+ with col1:
250
+ slide_title = st.text_input(f"Title ###{slide_index}", value=slide.get('title', ''))
251
+ with col2:
252
+ if st.button("πŸͺ„ Improve", key=f"improve_title_{slide_index}"):
253
+ try:
254
+ with st.spinner("🐊 SlideGator.AI is enhancing your title..."):
255
+ from agents import enhance_slide_component
256
+ updated_slide, result = enhance_slide_component(slide, "title", "Make it concise and impactful")
257
+ if "error" not in result:
258
+ st.session_state.slides_content[slide_index] = updated_slide
259
+ st.success("Title improved!")
260
+ st.rerun()
261
+ else:
262
+ st.error(f"Error: {result.get('error')}")
263
+ except Exception as e:
264
+ st.error(f"Error improving title: {str(e)}")
265
+
266
+ # Content editing
267
+ st.write("##### πŸ“„ Content")
268
+ if isinstance(slide.get('content', []), list):
269
+ content_text = "\n".join(slide.get('content', []))
270
+ else:
271
+ content_text = slide.get('content', '')
272
+
273
+ col1, col2 = st.columns([3, 1])
274
+ with col1:
275
+ content = st.text_area(f"Content ###{slide_index}", value=content_text, height=150)
276
+ with col2:
277
+ st.write("")
278
+ st.write("")
279
+ if st.button("πŸͺ„ Improve", key=f"improve_content_{slide_index}"):
280
+ try:
281
+ with st.spinner("🐊 SlideGator.AI is enhancing your content..."):
282
+ from agents import enhance_slide_component
283
+ slide["content"] = content.split("\n") if "\n" in content else [content]
284
+ updated_slide, result = enhance_slide_component(slide, "content", "Make it clear and concise")
285
+ if "error" not in result:
286
+ st.session_state.slides_content[slide_index] = updated_slide
287
+ st.success("Content improved!")
288
+ st.rerun()
289
+ else:
290
+ st.error(f"Error: {result.get('error')}")
291
+ except Exception as e:
292
+ st.error(f"Error improving content: {str(e)}")
293
+
294
+ # Visual elements with AI assistance
295
+ st.write("##### πŸ–ΌοΈ Visual Suggestions")
296
+ if isinstance(slide.get('visual_elements', []), list):
297
+ visuals_text = "\n".join(slide.get('visual_elements', []))
298
+ else:
299
+ visuals_text = slide.get('visual_elements', '')
300
+
301
+ col1, col2 = st.columns([3, 1])
302
+ with col1:
303
+ visuals = st.text_area(f"Visual Elements ###{slide_index}", value=visuals_text, height=100)
304
+ with col2:
305
+ st.write("")
306
+ if st.button("🎨 Suggest", key=f"suggest_visuals_{slide_index}"):
307
+ try:
308
+ with st.spinner("🐊 SlideGator.AI is suggesting visuals..."):
309
+ from agents import enhance_slide_component
310
+ slide["visual_elements"] = visuals.split("\n") if "\n" in visuals else [visuals]
311
+ updated_slide, result = enhance_slide_component(slide, "visuals", "Be specific and creative")
312
+ if "error" not in result:
313
+ st.session_state.slides_content[slide_index] = updated_slide
314
+ st.success("Visual suggestions added!")
315
+ st.rerun()
316
+ else:
317
+ st.error(f"Error: {result.get('error')}")
318
+ except Exception as e:
319
+ st.error(f"Error suggesting visuals: {str(e)}")
320
+
321
+ # Presenter notes
322
+ st.write("##### 🎀 Presenter Notes")
323
+ notes = st.text_area(f"Notes ###{slide_index}", value=slide.get('notes', ''), height=100)
324
+ if st.button("πŸͺ„ Generate Notes", key=f"generate_notes_{slide_index}"):
325
+ try:
326
+ with st.spinner("🐊 SlideGator.AI is writing speaker notes..."):
327
+ from agents import enhance_slide_component
328
+ updated_slide, result = enhance_slide_component(slide, "notes")
329
+ if "error" not in result:
330
+ st.session_state.slides_content[slide_index] = updated_slide
331
+ st.success("Speaker notes generated!")
332
+ st.rerun()
333
+ else:
334
+ st.error(f"Error: {result.get('error')}")
335
+ except Exception as e:
336
+ st.error(f"Error generating notes: {str(e)}")
337
+
338
+ # LLM model selection for this specific slide
339
+ st.write("##### 🧠 AI Enhancement Settings")
340
+ with st.expander("Advanced AI Settings"):
341
+ llm_options = {
342
+ "claude-3-sonnet": "Claude 3 Sonnet (Default)",
343
+ "claude-3-haiku": "Claude 3 Haiku (Faster)",
344
+ "claude-3-opus": "Claude 3 Opus (Highest Quality)",
345
+ "gpt-4": "GPT-4 (If OpenAI key provided)",
346
+ "gpt-3.5-turbo": "GPT-3.5 Turbo (Faster)",
347
+ "deepseek-chat": "DeepSeek Chat"
348
+ }
349
+
350
+ selected_llm = st.selectbox(
351
+ "AI Model for this slide",
352
+ options=list(llm_options.keys()),
353
+ format_func=lambda x: llm_options[x],
354
+ key=f"llm_{slide_index}"
355
+ )
356
+
357
+ if "ai_settings" not in slide:
358
+ slide["ai_settings"] = {}
359
+
360
+ slide["ai_settings"]["model"] = selected_llm
361
+
362
+ # Web search integration
363
+ st.write("##### πŸ” Web Search Integration")
364
+ enable_search = st.checkbox(
365
+ "Enable web search for up-to-date content",
366
+ value=slide.get("ai_settings", {}).get("web_search", False),
367
+ key=f"search_{slide_index}"
368
+ )
369
+
370
+ if enable_search:
371
+ search_query = st.text_input(
372
+ "Search query",
373
+ value=slide.get("ai_settings", {}).get("search_query", f"latest {slide.get('title', '')}"),
374
+ key=f"search_query_{slide_index}"
375
+ )
376
+
377
+ slide["ai_settings"]["web_search"] = enable_search
378
+ slide["ai_settings"]["search_query"] = search_query
379
+
380
+ if st.button("Fetch Latest Content", key=f"fetch_{slide_index}"):
381
+ st.info("This would fetch the latest information from the web to update your slide.")
382
+ # In a real implementation, this would call a search API
383
+
384
+ # Update slide with edits
385
+ slide["title"] = slide_title
386
+ if "\n" in content:
387
+ slide["content"] = content.split("\n")
388
+ else:
389
+ slide["content"] = [content] if content else []
390
+ if "\n" in visuals:
391
+ slide["visual_elements"] = visuals.split("\n")
392
+ else:
393
+ slide["visual_elements"] = [visuals] if visuals else []
394
+ slide["notes"] = notes
395
+
396
+ return slide