Added new features to the project
This commit is contained in:
@@ -1,16 +1,22 @@
|
||||
"""
|
||||
Twitter Dashboard with modern UI components.
|
||||
Enhanced Twitter Dashboard with modern UI components and improved user experience.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
from typing import Dict, List
|
||||
from typing import Dict, List, Optional, Any
|
||||
import json
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import plotly.express as px
|
||||
import plotly.graph_objects as go
|
||||
from plotly.subplots import make_subplots
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
from .tweet_generator import smart_tweet_generator
|
||||
from .twitter_streamlit_ui import (
|
||||
TwitterDashboard,
|
||||
FeatureCard,
|
||||
TweetCard,
|
||||
TweetForm,
|
||||
SettingsForm,
|
||||
Sidebar,
|
||||
@@ -22,290 +28,702 @@ from .twitter_streamlit_ui import (
|
||||
get_from_session,
|
||||
clear_session,
|
||||
show_success_message,
|
||||
show_error_message
|
||||
show_error_message,
|
||||
show_info_message,
|
||||
show_warning_message
|
||||
)
|
||||
|
||||
def load_feature_data() -> Dict:
|
||||
"""Load feature data from a structured format."""
|
||||
return {
|
||||
"tweet_generation": {
|
||||
"title": "Tweet Generation & Optimization",
|
||||
"icon": "🐦",
|
||||
"description": "Create and optimize engaging tweets with AI assistance",
|
||||
"features": [
|
||||
{
|
||||
"name": "Smart Tweet Generator",
|
||||
"description": "Generate multiple tweet variations with optimal character count, hashtags, and emojis",
|
||||
"status": "active",
|
||||
"icon": "✨",
|
||||
"function": smart_tweet_generator
|
||||
},
|
||||
{
|
||||
"name": "Tweet Performance Predictor",
|
||||
"description": "Predict engagement rates and best posting times for maximum impact",
|
||||
"status": "coming_soon",
|
||||
"icon": "📊"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content_strategy": {
|
||||
"title": "Content Strategy Tools",
|
||||
"icon": "📅",
|
||||
"description": "Plan and manage your Twitter content strategy effectively",
|
||||
"features": [
|
||||
{
|
||||
"name": "Content Calendar Generator",
|
||||
"description": "Create weekly/monthly content plans with theme-based scheduling",
|
||||
"status": "coming_soon",
|
||||
"icon": "🗓️"
|
||||
},
|
||||
{
|
||||
"name": "Hashtag Strategy Manager",
|
||||
"description": "Research and manage trending hashtags for better reach",
|
||||
"status": "coming_soon",
|
||||
"icon": "#️⃣"
|
||||
}
|
||||
]
|
||||
},
|
||||
"visual_content": {
|
||||
"title": "Visual Content Creation",
|
||||
"icon": "🎨",
|
||||
"description": "Create engaging visual content for your tweets",
|
||||
"features": [
|
||||
{
|
||||
"name": "Image Generator",
|
||||
"description": "Create tweet cards, infographics, and quote designs",
|
||||
"status": "coming_soon",
|
||||
"icon": "🖼️"
|
||||
},
|
||||
{
|
||||
"name": "Video Content Assistant",
|
||||
"description": "Generate video scripts and optimize captions",
|
||||
"status": "coming_soon",
|
||||
"icon": "🎥"
|
||||
}
|
||||
]
|
||||
},
|
||||
"engagement": {
|
||||
"title": "Engagement & Community",
|
||||
"icon": "🤝",
|
||||
"description": "Manage and enhance community engagement",
|
||||
"features": [
|
||||
{
|
||||
"name": "Reply Generator",
|
||||
"description": "Generate context-aware responses with appropriate tone",
|
||||
"status": "coming_soon",
|
||||
"icon": "💬"
|
||||
},
|
||||
{
|
||||
"name": "Community Tools",
|
||||
"description": "Create polls and plan Q&A sessions",
|
||||
"status": "coming_soon",
|
||||
"icon": "👥"
|
||||
}
|
||||
]
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Analytics & Optimization",
|
||||
"icon": "📈",
|
||||
"description": "Track performance and optimize your Twitter strategy",
|
||||
"features": [
|
||||
{
|
||||
"name": "Performance Analytics",
|
||||
"description": "Track tweet performance and engagement metrics",
|
||||
"status": "coming_soon",
|
||||
"icon": "📊"
|
||||
},
|
||||
{
|
||||
"name": "A/B Testing Assistant",
|
||||
"description": "Test and optimize tweet variations for better results",
|
||||
"status": "coming_soon",
|
||||
"icon": "🔍"
|
||||
}
|
||||
]
|
||||
},
|
||||
"research": {
|
||||
"title": "Research & Intelligence",
|
||||
"icon": "🔎",
|
||||
"description": "Gain insights and stay ahead of trends",
|
||||
"features": [
|
||||
{
|
||||
"name": "Market Research",
|
||||
"description": "Analyze competitors and track industry trends",
|
||||
"status": "coming_soon",
|
||||
"icon": "📊"
|
||||
},
|
||||
{
|
||||
"name": "Content Inspiration",
|
||||
"description": "Get trending topic suggestions and content ideas",
|
||||
"status": "coming_soon",
|
||||
"icon": "💡"
|
||||
}
|
||||
]
|
||||
def apply_modern_styling():
|
||||
"""Apply modern CSS styling to the dashboard."""
|
||||
st.markdown("""
|
||||
<style>
|
||||
/* Import Google Fonts */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
||||
|
||||
/* Global Styles */
|
||||
.stApp {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Main Container */
|
||||
.main-container {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 20px;
|
||||
padding: 2rem;
|
||||
margin: 1rem;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Header Styles */
|
||||
.dashboard-header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
padding: 2rem 0;
|
||||
background: linear-gradient(135deg, #1DA1F2, #0C85D0);
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
box-shadow: 0 10px 30px rgba(29, 161, 242, 0.3);
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dashboard-subtitle {
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.9;
|
||||
margin-top: 0.5rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Feature Cards */
|
||||
.feature-card {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: #2D3748;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.feature-description {
|
||||
color: #718096;
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-status {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 20px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
background: linear-gradient(135deg, #48BB78, #38A169);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-coming-soon {
|
||||
background: linear-gradient(135deg, #ED8936, #DD6B20);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Metrics Cards */
|
||||
.metric-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
|
||||
border-left: 4px solid #1DA1F2;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #2D3748;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
color: #718096;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.stButton > button {
|
||||
background: linear-gradient(135deg, #1DA1F2, #0C85D0);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(29, 161, 242, 0.3);
|
||||
}
|
||||
|
||||
.stButton > button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(29, 161, 242, 0.4);
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
.stTabs [data-baseweb="tab-list"] {
|
||||
gap: 0.5rem;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 0.5rem;
|
||||
border-radius: 12px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.stTabs [data-baseweb="tab"] {
|
||||
background: transparent;
|
||||
border-radius: 8px;
|
||||
color: #4A5568;
|
||||
font-weight: 500;
|
||||
padding: 0.75rem 1.5rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.stTabs [aria-selected="true"] {
|
||||
background: white;
|
||||
color: #1DA1F2;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Connection Status */
|
||||
.connection-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 1.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-connected {
|
||||
background: linear-gradient(135deg, #C6F6D5, #9AE6B4);
|
||||
color: #22543D;
|
||||
border: 1px solid #9AE6B4;
|
||||
}
|
||||
|
||||
.status-disconnected {
|
||||
background: linear-gradient(135deg, #FED7D7, #FEB2B2);
|
||||
color: #742A2A;
|
||||
border: 1px solid #FEB2B2;
|
||||
}
|
||||
|
||||
/* Quick Actions */
|
||||
.quick-actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.quick-action-btn {
|
||||
background: white;
|
||||
border: 2px solid #E2E8F0;
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.quick-action-btn:hover {
|
||||
border-color: #1DA1F2;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(29, 161, 242, 0.15);
|
||||
}
|
||||
|
||||
.quick-action-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.quick-action-title {
|
||||
font-weight: 600;
|
||||
color: #2D3748;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.quick-action-desc {
|
||||
font-size: 0.85rem;
|
||||
color: #718096;
|
||||
}
|
||||
|
||||
/* Analytics Charts */
|
||||
.chart-container {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem;
|
||||
margin: 1rem 0;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.main-container {
|
||||
margin: 0.5rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
def run_dashboard():
|
||||
"""Main function to run the Twitter dashboard."""
|
||||
# Initialize dashboard
|
||||
dashboard = TwitterDashboard()
|
||||
def render_connection_status():
|
||||
"""Render Twitter connection status with modern styling."""
|
||||
# Simulate connection status (replace with real authentication check)
|
||||
is_connected = get_from_session("twitter_connected", False)
|
||||
|
||||
# Load feature data
|
||||
features = load_feature_data()
|
||||
|
||||
# Setup navigation
|
||||
sidebar = Sidebar(title="Twitter Tools")
|
||||
sidebar.add_menu_item("Dashboard", "📊", "dashboard")
|
||||
sidebar.add_menu_item("Tweet Generator", "✍️", "tweet_generator")
|
||||
sidebar.add_menu_item("Analytics", "📈", "analytics")
|
||||
sidebar.add_menu_item("Settings", "⚙️", "settings")
|
||||
|
||||
# Setup header
|
||||
header = Header(
|
||||
title="Twitter AI Writer",
|
||||
subtitle="Your all-in-one Twitter content creation and management platform"
|
||||
)
|
||||
header.add_action("New Tweet", "✏️", lambda: save_to_session("current_page", "tweet_generator"))
|
||||
header.add_action("Refresh", "🔄", lambda: st.experimental_rerun())
|
||||
|
||||
# Setup tabs
|
||||
tabs = Tabs()
|
||||
tabs.add_tab("Overview", "📊", lambda: render_overview(features))
|
||||
tabs.add_tab("Recent Tweets", "🐦", lambda: render_recent_tweets())
|
||||
tabs.add_tab("Analytics", "📈", lambda: render_analytics())
|
||||
|
||||
# Setup breadcrumbs
|
||||
breadcrumbs = Breadcrumbs()
|
||||
breadcrumbs.add_item("Home", "dashboard", "🏠")
|
||||
breadcrumbs.add_item(get_from_session("current_page", "Dashboard").title())
|
||||
|
||||
# Render dashboard
|
||||
dashboard.render()
|
||||
if is_connected:
|
||||
user_info = get_from_session("twitter_user", {"name": "Demo User", "handle": "@demo_user"})
|
||||
st.markdown(f"""
|
||||
<div class="connection-status status-connected">
|
||||
<span style="font-size: 1.2rem;">✅</span>
|
||||
<div>
|
||||
<strong>Connected as {user_info['name']}</strong>
|
||||
<div style="font-size: 0.9rem; opacity: 0.8;">{user_info['handle']}</div>
|
||||
</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
else:
|
||||
st.markdown("""
|
||||
<div class="connection-status status-disconnected">
|
||||
<span style="font-size: 1.2rem;">⚠️</span>
|
||||
<div>
|
||||
<strong>Twitter Not Connected</strong>
|
||||
<div style="font-size: 0.9rem; opacity: 0.8;">Connect your account to access all features</div>
|
||||
</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
if st.button("🔗 Connect Twitter Account", key="connect_twitter"):
|
||||
# Simulate connection (replace with real OAuth flow)
|
||||
save_to_session("twitter_connected", True)
|
||||
save_to_session("twitter_user", {"name": "Demo User", "handle": "@demo_user"})
|
||||
st.rerun()
|
||||
|
||||
def render_overview(features: Dict):
|
||||
"""Render the overview tab content."""
|
||||
# Feature cards
|
||||
col1, col2, col3 = st.columns(3)
|
||||
def render_dashboard_header():
|
||||
"""Render the modern dashboard header."""
|
||||
st.markdown("""
|
||||
<div class="dashboard-header">
|
||||
<h1 class="dashboard-title">🐦 Twitter AI Dashboard</h1>
|
||||
<p class="dashboard-subtitle">Create, analyze, and optimize your Twitter content with AI-powered tools</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
def render_quick_actions():
|
||||
"""Render quick action buttons."""
|
||||
st.markdown("### 🚀 Quick Actions")
|
||||
|
||||
col1, col2, col3, col4 = st.columns(4)
|
||||
|
||||
with col1:
|
||||
FeatureCard(
|
||||
title="Tweet Generator",
|
||||
description="Create engaging tweets with AI assistance",
|
||||
icon="✍️",
|
||||
features=[
|
||||
{
|
||||
"name": "AI-Powered",
|
||||
"description": "Generate tweets using advanced AI"
|
||||
},
|
||||
{
|
||||
"name": "Customizable",
|
||||
"description": "Adjust tone, length, and style"
|
||||
}
|
||||
],
|
||||
on_click=lambda: save_to_session("current_page", "tweet_generator")
|
||||
).render()
|
||||
if st.button("✍️ Create Tweet", use_container_width=True, key="quick_tweet"):
|
||||
st.session_state.current_page = "tweet_generator"
|
||||
st.rerun()
|
||||
|
||||
with col2:
|
||||
FeatureCard(
|
||||
title="Analytics",
|
||||
description="Track your tweet performance",
|
||||
icon="📈",
|
||||
features=[
|
||||
{
|
||||
"name": "Engagement",
|
||||
"description": "Monitor likes, retweets, and replies"
|
||||
},
|
||||
{
|
||||
"name": "Growth",
|
||||
"description": "Track follower growth over time"
|
||||
}
|
||||
]
|
||||
).render()
|
||||
if st.button("📊 View Analytics", use_container_width=True, key="quick_analytics"):
|
||||
st.session_state.current_page = "analytics"
|
||||
st.rerun()
|
||||
|
||||
with col3:
|
||||
FeatureCard(
|
||||
title="Settings",
|
||||
description="Customize your experience",
|
||||
icon="⚙️",
|
||||
features=[
|
||||
{
|
||||
"name": "Preferences",
|
||||
"description": "Set your default options"
|
||||
},
|
||||
{
|
||||
"name": "API",
|
||||
"description": "Configure Twitter API settings"
|
||||
}
|
||||
]
|
||||
).render()
|
||||
if st.button("📅 Content Calendar", use_container_width=True, key="quick_calendar"):
|
||||
show_info_message("Content Calendar feature coming soon!")
|
||||
|
||||
with col4:
|
||||
if st.button("⚙️ Settings", use_container_width=True, key="quick_settings"):
|
||||
st.session_state.current_page = "settings"
|
||||
st.rerun()
|
||||
|
||||
def render_recent_tweets():
|
||||
"""Render the recent tweets tab content."""
|
||||
# Tweet form
|
||||
tweet_form = TweetForm(
|
||||
on_submit=lambda: handle_tweet_submit()
|
||||
def render_metrics_overview():
|
||||
"""Render key metrics overview."""
|
||||
st.markdown("### 📈 Performance Overview")
|
||||
|
||||
# Generate sample metrics (replace with real data)
|
||||
col1, col2, col3, col4 = st.columns(4)
|
||||
|
||||
with col1:
|
||||
st.markdown("""
|
||||
<div class="metric-card">
|
||||
<div class="metric-value">1,234</div>
|
||||
<div class="metric-label">Total Tweets</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col2:
|
||||
st.markdown("""
|
||||
<div class="metric-card">
|
||||
<div class="metric-value">45.2K</div>
|
||||
<div class="metric-label">Total Engagement</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col3:
|
||||
st.markdown("""
|
||||
<div class="metric-card">
|
||||
<div class="metric-value">3.8%</div>
|
||||
<div class="metric-label">Engagement Rate</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col4:
|
||||
st.markdown("""
|
||||
<div class="metric-card">
|
||||
<div class="metric-value">12.5K</div>
|
||||
<div class="metric-label">Followers</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
def render_engagement_chart():
|
||||
"""Render engagement trends chart."""
|
||||
st.markdown("### 📊 Engagement Trends")
|
||||
|
||||
# Generate sample data (replace with real Twitter data)
|
||||
dates = pd.date_range(start=datetime.now() - timedelta(days=30), periods=30)
|
||||
engagement = np.random.normal(100, 20, 30)
|
||||
engagement = np.maximum(engagement, 0) # Ensure positive values
|
||||
|
||||
df = pd.DataFrame({
|
||||
'Date': dates,
|
||||
'Engagement': engagement,
|
||||
'Likes': engagement * 0.6,
|
||||
'Retweets': engagement * 0.3,
|
||||
'Replies': engagement * 0.1
|
||||
})
|
||||
|
||||
# Create interactive chart
|
||||
fig = make_subplots(
|
||||
rows=2, cols=1,
|
||||
subplot_titles=('Total Engagement', 'Engagement Breakdown'),
|
||||
vertical_spacing=0.1,
|
||||
row_heights=[0.7, 0.3]
|
||||
)
|
||||
tweet_form.render()
|
||||
|
||||
# Recent tweets
|
||||
st.markdown("### Recent Tweets")
|
||||
tweets = get_from_session("tweets", [])
|
||||
for tweet in tweets:
|
||||
TweetCard(
|
||||
content=tweet["content"],
|
||||
engagement_score=tweet["engagement_score"],
|
||||
hashtags=tweet["hashtags"],
|
||||
emojis=tweet["emojis"],
|
||||
metrics=tweet["metrics"],
|
||||
on_copy=lambda: copy_tweet(tweet),
|
||||
on_save=lambda: save_tweet(tweet)
|
||||
).render()
|
||||
|
||||
def render_analytics():
|
||||
"""Render the analytics tab content."""
|
||||
st.markdown("### Tweet Analytics")
|
||||
st.info("Analytics features coming soon!")
|
||||
|
||||
def handle_tweet_submit():
|
||||
"""Handle tweet form submission."""
|
||||
# Get form data
|
||||
content = get_from_session("tweet_content")
|
||||
tone = get_from_session("tone")
|
||||
length = get_from_session("length")
|
||||
hashtags = get_from_session("hashtags")
|
||||
emojis = get_from_session("emojis")
|
||||
engagement_boost = get_from_session("engagement_boost")
|
||||
# Main engagement line
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df['Date'],
|
||||
y=df['Engagement'],
|
||||
mode='lines+markers',
|
||||
name='Total Engagement',
|
||||
line=dict(color='#1DA1F2', width=3),
|
||||
marker=dict(size=6)
|
||||
),
|
||||
row=1, col=1
|
||||
)
|
||||
|
||||
# Create tweet object
|
||||
tweet = {
|
||||
"content": content,
|
||||
"tone": tone,
|
||||
"length": length,
|
||||
"hashtags": hashtags,
|
||||
"emojis": emojis,
|
||||
"engagement_score": engagement_boost,
|
||||
"metrics": {
|
||||
"Engagement": engagement_boost,
|
||||
"Reach": engagement_boost * 0.8,
|
||||
"Growth": engagement_boost * 0.6
|
||||
# Stacked area chart for breakdown
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df['Date'],
|
||||
y=df['Likes'],
|
||||
mode='lines',
|
||||
name='Likes',
|
||||
fill='tonexty',
|
||||
line=dict(color='#E53E3E')
|
||||
),
|
||||
row=2, col=1
|
||||
)
|
||||
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df['Date'],
|
||||
y=df['Retweets'],
|
||||
mode='lines',
|
||||
name='Retweets',
|
||||
fill='tonexty',
|
||||
line=dict(color='#38A169')
|
||||
),
|
||||
row=2, col=1
|
||||
)
|
||||
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df['Date'],
|
||||
y=df['Replies'],
|
||||
mode='lines',
|
||||
name='Replies',
|
||||
fill='tonexty',
|
||||
line=dict(color='#D69E2E')
|
||||
),
|
||||
row=2, col=1
|
||||
)
|
||||
|
||||
fig.update_layout(
|
||||
height=500,
|
||||
showlegend=True,
|
||||
hovermode='x unified',
|
||||
plot_bgcolor='rgba(0,0,0,0)',
|
||||
paper_bgcolor='rgba(0,0,0,0)'
|
||||
)
|
||||
|
||||
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)')
|
||||
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)')
|
||||
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
def render_feature_grid():
|
||||
"""Render the feature grid with modern cards."""
|
||||
st.markdown("### 🛠️ Available Tools")
|
||||
|
||||
features = [
|
||||
{
|
||||
"title": "Smart Tweet Generator",
|
||||
"description": "Create engaging tweets with AI assistance, hashtag suggestions, and emoji optimization",
|
||||
"icon": "✨",
|
||||
"status": "active",
|
||||
"action": "tweet_generator"
|
||||
},
|
||||
{
|
||||
"title": "Performance Predictor",
|
||||
"description": "Predict tweet engagement and find optimal posting times",
|
||||
"icon": "🔮",
|
||||
"status": "coming_soon",
|
||||
"action": None
|
||||
},
|
||||
{
|
||||
"title": "Content Calendar",
|
||||
"description": "Plan and schedule your Twitter content strategy",
|
||||
"icon": "📅",
|
||||
"status": "coming_soon",
|
||||
"action": None
|
||||
},
|
||||
{
|
||||
"title": "Hashtag Research",
|
||||
"description": "Discover trending hashtags and analyze their performance",
|
||||
"icon": "#️⃣",
|
||||
"status": "coming_soon",
|
||||
"action": None
|
||||
},
|
||||
{
|
||||
"title": "Visual Content",
|
||||
"description": "Create quote cards, infographics, and visual tweets",
|
||||
"icon": "🎨",
|
||||
"status": "coming_soon",
|
||||
"action": None
|
||||
},
|
||||
{
|
||||
"title": "Analytics Dashboard",
|
||||
"description": "Deep dive into your Twitter performance metrics",
|
||||
"icon": "📊",
|
||||
"status": "coming_soon",
|
||||
"action": None
|
||||
}
|
||||
]
|
||||
|
||||
# Create grid layout
|
||||
cols = st.columns(3)
|
||||
|
||||
for i, feature in enumerate(features):
|
||||
with cols[i % 3]:
|
||||
status_class = "status-active" if feature["status"] == "active" else "status-coming-soon"
|
||||
|
||||
card_html = f"""
|
||||
<div class="feature-card" onclick="handleFeatureClick('{feature['action']}')">
|
||||
<span class="feature-icon">{feature['icon']}</span>
|
||||
<h3 class="feature-title">{feature['title']}</h3>
|
||||
<p class="feature-description">{feature['description']}</p>
|
||||
<span class="feature-status {status_class}">{feature['status'].replace('_', ' ')}</span>
|
||||
</div>
|
||||
"""
|
||||
|
||||
st.markdown(card_html, unsafe_allow_html=True)
|
||||
|
||||
# Add button for active features
|
||||
if feature["status"] == "active" and feature["action"]:
|
||||
if st.button(f"Launch {feature['title']}", key=f"launch_{i}", use_container_width=True):
|
||||
st.session_state.current_page = feature["action"]
|
||||
st.rerun()
|
||||
|
||||
def render_recent_activity():
|
||||
"""Render recent activity feed."""
|
||||
st.markdown("### 📱 Recent Activity")
|
||||
|
||||
# Sample activity data (replace with real data)
|
||||
activities = [
|
||||
{"time": "2 hours ago", "action": "Generated tweet", "details": "AI-powered content about social media trends"},
|
||||
{"time": "5 hours ago", "action": "Analyzed performance", "details": "Tweet received 45 likes and 12 retweets"},
|
||||
{"time": "1 day ago", "action": "Scheduled tweet", "details": "Content scheduled for optimal posting time"},
|
||||
{"time": "2 days ago", "action": "Updated hashtags", "details": "Added trending hashtags to improve reach"}
|
||||
]
|
||||
|
||||
for activity in activities:
|
||||
st.markdown(f"""
|
||||
<div style="
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
border-left: 3px solid #1DA1F2;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
">
|
||||
<div style="font-weight: 600; color: #2D3748; margin-bottom: 0.25rem;">
|
||||
{activity['action']}
|
||||
</div>
|
||||
<div style="color: #718096; font-size: 0.9rem; margin-bottom: 0.25rem;">
|
||||
{activity['details']}
|
||||
</div>
|
||||
<div style="color: #A0AEC0; font-size: 0.8rem;">
|
||||
{activity['time']}
|
||||
</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
def run_dashboard():
|
||||
"""Main function to run the enhanced Twitter dashboard."""
|
||||
# Apply modern styling
|
||||
apply_modern_styling()
|
||||
|
||||
# Initialize session state
|
||||
if "current_page" not in st.session_state:
|
||||
st.session_state.current_page = "dashboard"
|
||||
|
||||
# Handle page navigation
|
||||
if st.session_state.current_page == "tweet_generator":
|
||||
if st.button("← Back to Dashboard", key="back_to_dashboard"):
|
||||
st.session_state.current_page = "dashboard"
|
||||
st.rerun()
|
||||
smart_tweet_generator()
|
||||
return
|
||||
|
||||
# Main dashboard container
|
||||
st.markdown('<div class="main-container">', unsafe_allow_html=True)
|
||||
|
||||
# Render dashboard header
|
||||
render_dashboard_header()
|
||||
|
||||
# Render connection status
|
||||
render_connection_status()
|
||||
|
||||
# Create main layout
|
||||
tab1, tab2, tab3 = st.tabs(["🏠 Overview", "📊 Analytics", "⚙️ Settings"])
|
||||
|
||||
with tab1:
|
||||
# Quick actions
|
||||
render_quick_actions()
|
||||
|
||||
# Metrics overview
|
||||
render_metrics_overview()
|
||||
|
||||
# Feature grid
|
||||
render_feature_grid()
|
||||
|
||||
# Recent activity
|
||||
col1, col2 = st.columns([2, 1])
|
||||
with col1:
|
||||
render_engagement_chart()
|
||||
with col2:
|
||||
render_recent_activity()
|
||||
|
||||
with tab2:
|
||||
st.markdown("### 📈 Advanced Analytics")
|
||||
|
||||
# Time range selector
|
||||
col1, col2 = st.columns([1, 3])
|
||||
with col1:
|
||||
time_range = st.selectbox(
|
||||
"Time Range",
|
||||
["Last 7 days", "Last 30 days", "Last 90 days", "Last year"],
|
||||
index=1
|
||||
)
|
||||
|
||||
# Detailed analytics
|
||||
render_engagement_chart()
|
||||
|
||||
# Performance insights
|
||||
st.markdown("### 💡 Performance Insights")
|
||||
|
||||
insights = [
|
||||
"Your tweets perform 23% better when posted between 2-4 PM",
|
||||
"Tweets with 2-3 hashtags get 15% more engagement",
|
||||
"Visual content increases engagement by 35%",
|
||||
"Questions in tweets boost replies by 28%"
|
||||
]
|
||||
|
||||
for insight in insights:
|
||||
st.info(f"💡 {insight}")
|
||||
|
||||
with tab3:
|
||||
st.markdown("### ⚙️ Dashboard Settings")
|
||||
|
||||
# Twitter API settings
|
||||
with st.expander("🔑 Twitter API Configuration", expanded=False):
|
||||
st.markdown("Configure your Twitter API credentials to enable full functionality.")
|
||||
|
||||
api_key = st.text_input("API Key", type="password", help="Your Twitter API key")
|
||||
api_secret = st.text_input("API Secret", type="password", help="Your Twitter API secret")
|
||||
access_token = st.text_input("Access Token", type="password", help="Your Twitter access token")
|
||||
access_token_secret = st.text_input("Access Token Secret", type="password", help="Your Twitter access token secret")
|
||||
|
||||
if st.button("Save API Configuration"):
|
||||
# Save configuration (implement secure storage)
|
||||
show_success_message("API configuration saved successfully!")
|
||||
|
||||
# Dashboard preferences
|
||||
with st.expander("🎨 Dashboard Preferences", expanded=True):
|
||||
theme = st.selectbox("Theme", ["Light", "Dark", "Auto"], index=0)
|
||||
default_tone = st.selectbox("Default Tweet Tone", ["Professional", "Casual", "Humorous", "Inspirational"], index=1)
|
||||
auto_hashtags = st.checkbox("Auto-suggest hashtags", value=True)
|
||||
|
||||
if st.button("Save Preferences"):
|
||||
show_success_message("Preferences saved successfully!")
|
||||
|
||||
# Account management
|
||||
with st.expander("👤 Account Management", expanded=False):
|
||||
st.markdown("Manage your connected Twitter accounts and permissions.")
|
||||
|
||||
if get_from_session("twitter_connected", False):
|
||||
st.success("✅ Twitter account connected")
|
||||
if st.button("Disconnect Account"):
|
||||
save_to_session("twitter_connected", False)
|
||||
st.rerun()
|
||||
else:
|
||||
st.warning("⚠️ No Twitter account connected")
|
||||
if st.button("Connect Account"):
|
||||
save_to_session("twitter_connected", True)
|
||||
st.rerun()
|
||||
|
||||
st.markdown('</div>', unsafe_allow_html=True)
|
||||
|
||||
# JavaScript for handling feature clicks
|
||||
st.markdown("""
|
||||
<script>
|
||||
function handleFeatureClick(action) {
|
||||
if (action && action !== 'null') {
|
||||
// This would trigger a Streamlit rerun with the selected action
|
||||
console.log('Feature clicked:', action);
|
||||
}
|
||||
|
||||
# Add to tweets list
|
||||
tweets = get_from_session("tweets", [])
|
||||
tweets.append(tweet)
|
||||
save_to_session("tweets", tweets)
|
||||
|
||||
# Show success message
|
||||
show_success_message("Tweet created successfully!")
|
||||
|
||||
def copy_tweet(tweet: Dict):
|
||||
"""Copy tweet to clipboard."""
|
||||
show_success_message("Tweet copied to clipboard!")
|
||||
|
||||
def save_tweet(tweet: Dict):
|
||||
"""Save tweet for later."""
|
||||
show_success_message("Tweet saved!")
|
||||
}
|
||||
</script>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_dashboard()
|
||||
Reference in New Issue
Block a user