Content Calendar, Content Gap Analysis, and Content Optimization
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
UI setup module for ALwrity application.
|
||||
Provides consistent navigation and layout structure.
|
||||
"""
|
||||
|
||||
import os
|
||||
import streamlit as st
|
||||
from lib.utils.file_processor import load_image
|
||||
@@ -15,6 +20,99 @@ from lib.ai_writers.insta_ai_writer import insta_writer
|
||||
from lib.ai_writers.youtube_writers.youtube_ai_writer import youtube_main_menu
|
||||
from lib.ai_writers.ai_writer_dashboard import get_ai_writers, list_ai_writers
|
||||
|
||||
def render_social_tools_dashboard():
|
||||
"""Render a modern dashboard for social media tools."""
|
||||
st.markdown("""
|
||||
<style>
|
||||
.social-card {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s ease;
|
||||
height: 100%;
|
||||
}
|
||||
.social-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
.social-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.social-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.social-description {
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.social-button {
|
||||
width: 100%;
|
||||
padding: 8px 16px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Define social tools with their details and paths
|
||||
social_tools = {
|
||||
"Facebook": {
|
||||
"icon": "📘",
|
||||
"description": "Create engaging Facebook posts and manage your content strategy",
|
||||
"color": "#4267B2",
|
||||
"path": "facebook"
|
||||
},
|
||||
"LinkedIn": {
|
||||
"icon": "💼",
|
||||
"description": "Generate professional LinkedIn content and optimize your profile",
|
||||
"color": "#0077B5",
|
||||
"path": "linkedin"
|
||||
},
|
||||
"Twitter": {
|
||||
"icon": "🐦",
|
||||
"description": "Craft viral tweets and manage your Twitter presence",
|
||||
"color": "#1DA1F2",
|
||||
"path": "twitter"
|
||||
},
|
||||
"Instagram": {
|
||||
"icon": "📸",
|
||||
"description": "Create Instagram captions and plan your visual content",
|
||||
"color": "#E1306C",
|
||||
"path": "instagram"
|
||||
},
|
||||
"YouTube": {
|
||||
"icon": "🎥",
|
||||
"description": "Generate video scripts and optimize your YouTube content",
|
||||
"color": "#FF0000",
|
||||
"path": "youtube"
|
||||
}
|
||||
}
|
||||
|
||||
# Create a grid of cards
|
||||
cols = st.columns(3)
|
||||
for idx, (platform, details) in enumerate(social_tools.items()):
|
||||
with cols[idx % 3]:
|
||||
st.markdown(f"""
|
||||
<div class="social-card">
|
||||
<div class="social-icon">{details['icon']}</div>
|
||||
<div class="social-title">{platform}</div>
|
||||
<div class="social-description">{details['description']}</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
if st.button(f"Open {platform}", key=f"btn_{platform}",
|
||||
help=f"Launch {platform} tools",
|
||||
use_container_width=True):
|
||||
# Set query parameters to redirect to the specific tool
|
||||
st.query_params["tool"] = details["path"]
|
||||
st.rerun()
|
||||
|
||||
def setup_ui():
|
||||
"""Set up the UI with custom styling."""
|
||||
@@ -314,29 +412,18 @@ def setup_alwrity_ui():
|
||||
"AI Writers": ("📝", get_ai_writers),
|
||||
"Content Planning": ("📅", content_planning_tools),
|
||||
"AI SEO Tools": ("🔍", ai_seo_tools),
|
||||
"AI Social Tools": ("📱", None), # Set to None as we'll handle this separately
|
||||
"AI Social Tools": ("📱", render_social_tools_dashboard),
|
||||
"ALwrity Settings": ("⚙️", render_settings_page),
|
||||
"Agents Teams(TBD)": ("🤝", lambda: st.subheader("Agents Teams - Coming Soon!")),
|
||||
"Ask Alwrity(TBD)": ("💬", lambda: (
|
||||
st.subheader("Chat with your Data, Chat with any Data.. COMING SOON !"),
|
||||
st.markdown("Create a collection by uploading files (PDF, MD, CSV, etc), or crawl a data source (Websites, more sources coming soon."),
|
||||
st.markdown("One can ask/chat, summarize and do semantic search over the uploaded data")
|
||||
)),
|
||||
"ALwrity Settings": ("⚙️", render_settings_page)
|
||||
))
|
||||
}
|
||||
|
||||
logger.info(f"Defined {len(nav_items)} navigation items")
|
||||
|
||||
# Define sub-menu items for AI Social Tools
|
||||
social_tools_submenu = {
|
||||
"Facebook": ("📘", lambda: facebook_main_menu()),
|
||||
"LinkedIn": ("💼", lambda: linkedin_main_menu()),
|
||||
"Twitter": ("🐦", lambda: run_dashboard()),
|
||||
"Instagram": ("📸", lambda: insta_writer()),
|
||||
"YouTube": ("🎥", lambda: youtube_main_menu())
|
||||
}
|
||||
|
||||
logger.info(f"Defined {len(social_tools_submenu)} social tools submenu items")
|
||||
|
||||
# Create sidebar navigation
|
||||
st.sidebar.markdown("### ALwrity Options")
|
||||
st.sidebar.markdown('<div class="sidebar-nav">', unsafe_allow_html=True)
|
||||
@@ -345,53 +432,12 @@ def setup_alwrity_ui():
|
||||
for name, (icon, func) in nav_items.items():
|
||||
button_class = "nav-button active" if st.session_state.active_tab == name else "nav-button"
|
||||
|
||||
if name == "AI Social Tools":
|
||||
# For AI Social Tools, we'll create a button that toggles the sub-menu
|
||||
if st.sidebar.button(f"{icon} {name}", key=f"nav_{name}",
|
||||
help=f"Navigate to {name}", use_container_width=True):
|
||||
st.session_state.active_tab = name
|
||||
# Reset sub-tab when main tab changes
|
||||
st.session_state.active_sub_tab = None
|
||||
logger.info(f"Selected main tab: {name}")
|
||||
|
||||
# If AI Social Tools is active, show the sub-menu
|
||||
if st.session_state.active_tab == "AI Social Tools":
|
||||
st.sidebar.markdown('<div class="sub-menu">', unsafe_allow_html=True)
|
||||
|
||||
# Create sub-menu buttons
|
||||
for sub_name, (sub_icon, sub_func) in social_tools_submenu.items():
|
||||
# Create the button with a custom key that includes the platform name
|
||||
button_key = f"sub_{sub_name}"
|
||||
|
||||
# Determine if this button is active
|
||||
is_active = st.session_state.active_sub_tab == sub_name
|
||||
|
||||
# Create a container with the platform-specific class
|
||||
platform_class = f"{sub_name.lower()}-button"
|
||||
if is_active:
|
||||
platform_class += " active"
|
||||
|
||||
# Add the platform-specific class to the button container
|
||||
st.sidebar.markdown(f'<div class="{platform_class}">', unsafe_allow_html=True)
|
||||
|
||||
# Create the button
|
||||
if st.sidebar.button(f"{sub_icon} {sub_name}", key=button_key,
|
||||
help=f"Navigate to {sub_name}", use_container_width=True):
|
||||
st.session_state.active_sub_tab = sub_name
|
||||
logger.info(f"Selected social tool: {sub_name}")
|
||||
|
||||
# Close the div
|
||||
st.sidebar.markdown('</div>', unsafe_allow_html=True)
|
||||
|
||||
st.sidebar.markdown('</div>', unsafe_allow_html=True)
|
||||
else:
|
||||
# For other navigation items, create regular buttons
|
||||
if st.sidebar.button(f"{icon} {name}", key=f"nav_{name}",
|
||||
help=f"Navigate to {name}", use_container_width=True):
|
||||
st.session_state.active_tab = name
|
||||
# Reset sub-tab when main tab changes
|
||||
st.session_state.active_sub_tab = None
|
||||
logger.info(f"Selected main tab: {name}")
|
||||
if st.sidebar.button(f"{icon} {name}", key=f"nav_{name}",
|
||||
help=f"Navigate to {name}", use_container_width=True):
|
||||
st.session_state.active_tab = name
|
||||
# Reset sub-tab when main tab changes
|
||||
st.session_state.active_sub_tab = None
|
||||
logger.info(f"Selected main tab: {name}")
|
||||
|
||||
st.sidebar.markdown('</div>', unsafe_allow_html=True)
|
||||
|
||||
@@ -402,10 +448,36 @@ def setup_alwrity_ui():
|
||||
st.sidebar.image(icon_path, use_container_width=False)
|
||||
st.sidebar.markdown('</div>', unsafe_allow_html=True)
|
||||
|
||||
# Display content based on active tab
|
||||
# Display content based on active tab and tool selection
|
||||
if st.session_state.active_tab == "AI Social Tools":
|
||||
if not st.session_state.active_sub_tab:
|
||||
# Only show title and info when no sub-tab is selected
|
||||
# Check if a specific tool is selected
|
||||
selected_tool = st.query_params.get("tool")
|
||||
if selected_tool:
|
||||
# Add a back button at the top
|
||||
if st.button("← Back to Social Tools Dashboard", key=f"back_to_dashboard_{selected_tool}"):
|
||||
# Clear the tool query parameter
|
||||
st.query_params.clear()
|
||||
st.rerun()
|
||||
|
||||
# Map tool paths to their respective functions
|
||||
tool_functions = {
|
||||
"facebook": facebook_main_menu,
|
||||
"linkedin": linkedin_main_menu,
|
||||
"twitter": run_dashboard,
|
||||
"instagram": insta_writer,
|
||||
"youtube": youtube_main_menu
|
||||
}
|
||||
|
||||
if selected_tool in tool_functions:
|
||||
# Clear any existing content
|
||||
st.empty()
|
||||
# Execute the selected tool's function
|
||||
tool_functions[selected_tool]()
|
||||
else:
|
||||
st.error(f"Invalid tool selected: {selected_tool}")
|
||||
render_social_tools_dashboard()
|
||||
else:
|
||||
# Show the dashboard if no tool is selected
|
||||
st.markdown("""
|
||||
<style>
|
||||
.main .block-container {
|
||||
@@ -414,40 +486,14 @@ def setup_alwrity_ui():
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
st.title(f"{nav_items[st.session_state.active_tab][0]} {st.session_state.active_tab}")
|
||||
st.info("Please select a social media platform from the sidebar.")
|
||||
else:
|
||||
# When a platform is selected, show no title and minimize spacing
|
||||
st.markdown("""
|
||||
<style>
|
||||
.main .block-container {
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* Remove all margins and padding from content area */
|
||||
.element-container {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/* Hide any automatic headers */
|
||||
.main .block-container > div:first-child {
|
||||
margin-top: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
# Call the function directly without any title
|
||||
social_tools_submenu[st.session_state.active_sub_tab][1]()
|
||||
render_social_tools_dashboard()
|
||||
else:
|
||||
# Check if we're in the AI Writers section and handle writer selection
|
||||
# Handle other tabs as before
|
||||
if st.session_state.active_tab == "AI Writers":
|
||||
# Get the writer parameter from the URL using st.query_params
|
||||
writer = st.query_params.get("writer")
|
||||
logger.info(f"Current writer from query params: {writer}")
|
||||
|
||||
if writer:
|
||||
# Get the list of writers without rendering the dashboard
|
||||
writers = list_ai_writers()
|
||||
logger.info(f"Found {len(writers)} writers")
|
||||
|
||||
@@ -457,9 +503,7 @@ def setup_alwrity_ui():
|
||||
if w["path"] == writer:
|
||||
writer_found = True
|
||||
logger.info(f"Found matching writer: {w['name']}, executing function")
|
||||
# Clear any existing content
|
||||
st.empty()
|
||||
# Execute the writer function
|
||||
w["function"]()
|
||||
break
|
||||
|
||||
@@ -467,11 +511,9 @@ def setup_alwrity_ui():
|
||||
logger.error(f"No writer found with path: {writer}")
|
||||
st.error(f"No writer found with path: {writer}")
|
||||
else:
|
||||
# If no writer selected, show the dashboard
|
||||
logger.info("No writer selected, showing dashboard")
|
||||
get_ai_writers()
|
||||
else:
|
||||
# For all other tabs, show the title
|
||||
st.markdown("""
|
||||
<style>
|
||||
.main .block-container {
|
||||
|
||||
Reference in New Issue
Block a user