Files
ALwrity/ToBeMigrated/content_calendar/ui/components/content_repurposing_ui.py
2025-08-06 16:29:49 +05:30

517 lines
22 KiB
Python

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()