import streamlit as st import pandas as pd from typing import Dict, List, Any, Optional from datetime import datetime, timedelta import logging from pathlib import Path import sys # Add parent directory to path to import existing tools parent_dir = str(Path(__file__).parent.parent.parent.parent.parent) if parent_dir not in sys.path: sys.path.append(parent_dir) from lib.database.models import ContentItem, ContentType, Platform, SEOData from lib.ai_seo_tools.content_calendar.core.content_repurposer import SmartContentRepurposingEngine from lib.ai_seo_tools.content_calendar.core.content_generator import ContentGenerator logger = logging.getLogger(__name__) class ContentRepurposingUI: """ Streamlit UI component for the Smart Content Repurposing Engine. """ def __init__(self): self.repurposing_engine = SmartContentRepurposingEngine() self.content_generator = ContentGenerator() self.logger = logging.getLogger('content_calendar.repurposing_ui') def render_repurposing_interface(self): """Render the main repurposing interface.""" st.header("🔄 Smart Content Repurposing Engine") st.markdown("Transform your content into multiple platform-optimized pieces with AI-powered repurposing.") # Create tabs for different repurposing functions tab1, tab2, tab3, tab4 = st.tabs([ "📝 Single Content Repurposing", "📚 Content Series Creation", "🔍 Content Analysis", "📊 Repurposing Dashboard" ]) with tab1: self._render_single_content_repurposing() with tab2: self._render_content_series_creation() with tab3: self._render_content_analysis() with tab4: self._render_repurposing_dashboard() def _render_single_content_repurposing(self): """Render the single content repurposing interface.""" st.subheader("Repurpose Single Content") st.markdown("Transform one piece of content into multiple platform-optimized variations.") # Content input section col1, col2 = st.columns([2, 1]) with col1: st.markdown("### 📄 Source Content") # Content input options input_method = st.radio( "How would you like to provide content?", ["Manual Input", "Upload File", "Select from Calendar"], horizontal=True ) source_content = None if input_method == "Manual Input": source_content = self._render_manual_content_input() elif input_method == "Upload File": source_content = self._render_file_upload_input() else: # Select from Calendar source_content = self._render_calendar_selection() with col2: st.markdown("### 🎯 Target Platforms") # Platform selection available_platforms = [ Platform.TWITTER, Platform.LINKEDIN, Platform.INSTAGRAM, Platform.FACEBOOK, Platform.WEBSITE ] selected_platforms = st.multiselect( "Select target platforms:", options=available_platforms, default=[Platform.TWITTER, Platform.LINKEDIN], format_func=lambda x: x.name.title() ) # Repurposing strategy strategy = st.selectbox( "Repurposing Strategy:", ["adaptive", "atomic", "series"], help="Adaptive: AI chooses best approach, Atomic: Break into small pieces, Series: Create connected content" ) # Generate repurposed content if st.button("🚀 Generate Repurposed Content", type="primary"): if source_content and selected_platforms: with st.spinner("Repurposing content..."): try: repurposed_content = self.content_generator.repurpose_content_for_platforms( content_item=source_content, target_platforms=selected_platforms, strategy=strategy ) if repurposed_content: self._display_repurposed_content(repurposed_content) else: st.error("Failed to generate repurposed content. Please try again.") except Exception as e: st.error(f"Error during repurposing: {str(e)}") else: st.warning("Please provide source content and select at least one target platform.") def _render_content_series_creation(self): """Render the content series creation interface.""" st.subheader("Create Cross-Platform Content Series") st.markdown("Generate a strategic content series that progressively reveals information across platforms.") # Source content input source_content = self._render_manual_content_input(key_suffix="_series") if source_content: col1, col2 = st.columns(2) with col1: st.markdown("### 🌐 Platform Strategy") # Platform selection with strategy platforms = st.multiselect( "Select platforms for series:", options=[Platform.TWITTER, Platform.LINKEDIN, Platform.INSTAGRAM, Platform.FACEBOOK, Platform.WEBSITE], default=[Platform.TWITTER, Platform.LINKEDIN, Platform.WEBSITE], format_func=lambda x: x.name.title(), key="series_platforms" ) series_type = st.selectbox( "Series Strategy:", ["progressive_disclosure", "platform_native"], help="Progressive: Gradually reveal info across platforms, Native: Optimize for each platform's strengths" ) with col2: st.markdown("### 📅 Timeline Preview") if platforms: # Show timeline preview timeline_df = self._create_series_timeline_preview(source_content, platforms) st.dataframe(timeline_df, use_container_width=True) # Generate series if st.button("📚 Create Content Series", type="primary", key="create_series"): if platforms: with st.spinner("Creating content series..."): try: series_content = self.content_generator.create_content_series_across_platforms( source_content=source_content, platforms=platforms, series_type=series_type ) if series_content: self._display_content_series(series_content) else: st.error("Failed to create content series. Please try again.") except Exception as e: st.error(f"Error creating series: {str(e)}") else: st.warning("Please select at least one platform for the series.") def _render_content_analysis(self): """Render the content analysis interface.""" st.subheader("Content Repurposing Analysis") st.markdown("Analyze your content's repurposing potential and get AI-powered recommendations.") # Content input content_to_analyze = self._render_manual_content_input(key_suffix="_analysis") if content_to_analyze: col1, col2 = st.columns([1, 1]) with col1: available_platforms = st.multiselect( "Available platforms for analysis:", options=[Platform.TWITTER, Platform.LINKEDIN, Platform.INSTAGRAM, Platform.FACEBOOK, Platform.WEBSITE], default=[Platform.TWITTER, Platform.LINKEDIN, Platform.INSTAGRAM, Platform.FACEBOOK, Platform.WEBSITE], format_func=lambda x: x.name.title(), key="analysis_platforms" ) with col2: if st.button("🔍 Analyze Content", type="primary"): if available_platforms: with st.spinner("Analyzing content..."): try: analysis = self.content_generator.analyze_content_for_repurposing( content_item=content_to_analyze, available_platforms=available_platforms ) if analysis: self._display_content_analysis(analysis) else: st.error("Failed to analyze content. Please try again.") except Exception as e: st.error(f"Error during analysis: {str(e)}") else: st.warning("Please select at least one platform for analysis.") def _render_repurposing_dashboard(self): """Render the repurposing dashboard with metrics and insights.""" st.subheader("Repurposing Dashboard") st.markdown("Track your content repurposing performance and insights.") # Mock data for demonstration col1, col2, col3, col4 = st.columns(4) with col1: st.metric("Content Pieces Created", "156", "+23") with col2: st.metric("Time Saved", "312 hours", "+45 hours") with col3: st.metric("Platform Coverage", "85%", "+12%") with col4: st.metric("Engagement Boost", "34%", "+8%") # Recent repurposing activity st.markdown("### 📈 Recent Repurposing Activity") # Mock data for recent activity recent_activity = pd.DataFrame({ 'Date': ['2024-01-15', '2024-01-14', '2024-01-13', '2024-01-12'], 'Source Content': ['AI Writing Tips', 'SEO Best Practices', 'Content Strategy Guide', 'Social Media Trends'], 'Platforms': ['Twitter, LinkedIn', 'LinkedIn, Instagram', 'All Platforms', 'Twitter, Facebook'], 'Pieces Created': [3, 2, 5, 2], 'Status': ['Published', 'Scheduled', 'Draft', 'Published'] }) st.dataframe(recent_activity, use_container_width=True) # Performance insights st.markdown("### 💡 Performance Insights") insights_col1, insights_col2 = st.columns(2) with insights_col1: st.info("🎯 **Best Performing Platform**: LinkedIn posts show 45% higher engagement when repurposed from blog content.") with insights_col2: st.success("📊 **Optimization Tip**: Twitter threads perform 60% better when created from long-form content with statistics.") def _render_manual_content_input(self, key_suffix: str = "") -> Optional[ContentItem]: """Render manual content input form.""" with st.form(f"content_input_form{key_suffix}"): title = st.text_input("Content Title:", key=f"title{key_suffix}") content_type = st.selectbox( "Content Type:", options=[ContentType.BLOG_POST, ContentType.SOCIAL_MEDIA, ContentType.VIDEO, ContentType.NEWSLETTER], format_func=lambda x: x.name.replace('_', ' ').title(), key=f"content_type{key_suffix}" ) description = st.text_area( "Content Description/Body:", height=200, help="Paste your content here. This will be analyzed and repurposed.", key=f"description{key_suffix}" ) col1, col2 = st.columns(2) with col1: author = st.text_input("Author:", value="Content Creator", key=f"author{key_suffix}") with col2: tags = st.text_input("Tags (comma-separated):", key=f"tags{key_suffix}") submitted = st.form_submit_button("📝 Use This Content") if submitted and title and description: # Create ContentItem content_item = ContentItem( title=title, description=description, content_type=content_type, platforms=[], publish_date=datetime.now(), status="draft", author=author, tags=tags.split(',') if tags else [], notes="", seo_data=SEOData(title=title, meta_description="", keywords=[], structured_data={}) ) return content_item return None def _render_file_upload_input(self) -> Optional[ContentItem]: """Render file upload input.""" uploaded_file = st.file_uploader( "Upload content file:", type=['txt', 'md', 'docx'], help="Upload a text file, markdown file, or Word document" ) if uploaded_file: try: # Read file content if uploaded_file.type == "text/plain": content = str(uploaded_file.read(), "utf-8") else: content = str(uploaded_file.read(), "utf-8") # Simplified for demo # Extract title from filename title = uploaded_file.name.split('.')[0].replace('_', ' ').title() # Create ContentItem content_item = ContentItem( title=title, description=content, content_type=ContentType.BLOG_POST, platforms=[], publish_date=datetime.now(), status="draft", author="Uploaded Content", tags=[], notes=f"Uploaded from file: {uploaded_file.name}", seo_data=SEOData(title=title, meta_description="", keywords=[], structured_data={}) ) st.success(f"✅ File uploaded: {uploaded_file.name}") return content_item except Exception as e: st.error(f"Error reading file: {str(e)}") return None def _render_calendar_selection(self) -> Optional[ContentItem]: """Render calendar content selection.""" st.info("📅 Calendar integration coming soon! For now, please use manual input or file upload.") return None def _display_repurposed_content(self, repurposed_content: List[ContentItem]): """Display the repurposed content results.""" st.success(f"✅ Successfully created {len(repurposed_content)} repurposed content pieces!") for i, content in enumerate(repurposed_content): with st.expander(f"📱 {content.platforms[0].name.title()} - {content.title}"): st.markdown(f"**Platform:** {content.platforms[0].name.title()}") st.markdown(f"**Content Type:** {content.content_type.name.replace('_', ' ').title()}") st.markdown(f"**Scheduled for:** {content.publish_date.strftime('%Y-%m-%d')}") st.markdown("**Content:**") st.write(content.description) if content.tags: st.markdown(f"**Tags:** {', '.join(content.tags)}") # Action buttons col1, col2, col3 = st.columns(3) with col1: if st.button(f"📝 Edit", key=f"edit_{i}"): st.info("Edit functionality coming soon!") with col2: if st.button(f"📅 Schedule", key=f"schedule_{i}"): st.info("Scheduling functionality coming soon!") with col3: if st.button(f"📋 Copy", key=f"copy_{i}"): st.code(content.description) def _display_content_series(self, series_content: Dict[str, List[ContentItem]]): """Display the content series results.""" total_pieces = sum(len(pieces) for pieces in series_content.values()) st.success(f"✅ Successfully created content series with {total_pieces} pieces across {len(series_content)} platforms!") for platform, content_pieces in series_content.items(): st.markdown(f"### 📱 {platform.title()} Series ({len(content_pieces)} pieces)") for i, content in enumerate(content_pieces): with st.expander(f"Part {i+1}: {content.title}"): st.markdown(f"**Scheduled for:** {content.publish_date.strftime('%Y-%m-%d')}") st.markdown("**Content:**") st.write(content.description) if content.tags: st.markdown(f"**Tags:** {', '.join(content.tags)}") def _display_content_analysis(self, analysis: Dict[str, Any]): """Display content analysis results.""" st.markdown("### 📊 Content Analysis Results") # Content metrics col1, col2, col3 = st.columns(3) content_analysis = analysis.get('content_analysis', {}) with col1: st.metric("Word Count", content_analysis.get('word_count', 0)) with col2: richness = content_analysis.get('content_richness', 'Unknown') st.metric("Content Richness", richness) with col3: potential = content_analysis.get('repurposing_potential', 'Unknown') st.metric("Repurposing Potential", potential) # Recommendations st.markdown("### 💡 Recommendations") col1, col2 = st.columns(2) with col1: st.markdown("**Recommended Platforms:**") platforms = analysis.get('platform_suggestions', []) for platform in platforms: st.write(f"• {platform.name.title()}") with col2: st.markdown("**Suggested Strategies:**") strategies = analysis.get('strategy_suggestions', []) for strategy in strategies: st.write(f"• {strategy.replace('_', ' ').title()}") # Content atoms st.markdown("### 🔬 Content Atoms Analysis") atoms = content_analysis.get('content_atoms', {}) for atom_type, atom_list in atoms.items(): if atom_list: with st.expander(f"{atom_type.title()} ({len(atom_list)} found)"): for atom in atom_list: st.write(f"• {atom}") # Estimated output estimated = analysis.get('estimated_output', {}) if estimated: st.markdown("### 📈 Estimated Output") col1, col2, col3 = st.columns(3) with col1: st.metric("Total Pieces", estimated.get('total_pieces', 0)) with col2: st.metric("Time Savings", estimated.get('time_savings', '0 hours')) with col3: st.metric("Content Multiplication", estimated.get('content_multiplication', '1x')) def _create_series_timeline_preview(self, content: ContentItem, platforms: List[Platform]) -> pd.DataFrame: """Create a preview timeline for content series.""" timeline_data = [] base_date = datetime.now() for i, platform in enumerate(platforms): release_date = base_date + timedelta(days=i) timeline_data.append({ 'Platform': platform.name.title(), 'Release Date': release_date.strftime('%Y-%m-%d'), 'Content Type': self._get_platform_content_type(platform), 'Strategy': self._get_platform_strategy(platform) }) return pd.DataFrame(timeline_data) def _get_platform_content_type(self, platform: Platform) -> str: """Get content type for platform.""" types = { Platform.TWITTER: "Thread/Tweet", Platform.LINKEDIN: "Professional Post", Platform.INSTAGRAM: "Visual Post", Platform.FACEBOOK: "Engaging Post", Platform.WEBSITE: "Blog Article" } return types.get(platform, "Standard Post") def _get_platform_strategy(self, platform: Platform) -> str: """Get strategy for platform.""" strategies = { Platform.TWITTER: "Hook & Engage", Platform.LINKEDIN: "Authority Building", Platform.INSTAGRAM: "Visual Storytelling", Platform.FACEBOOK: "Community Discussion", Platform.WEBSITE: "Complete Information" } return strategies.get(platform, "Standard Approach") # Main function to render the UI def render_content_repurposing_ui(): """Main function to render the content repurposing UI.""" ui = ContentRepurposingUI() ui.render_repurposing_interface() # For testing if __name__ == "__main__": render_content_repurposing_ui()