diff --git a/CHANGELOG.md b/CHANGELOG.md index f094ba14..03329286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # IGNY8 Change Log -**Current Version:** 1.1.7 +**Current Version:** 1.1.8 **Last Updated:** December 27, 2025 --- @@ -9,6 +9,7 @@ | Version | Date | Summary | |---------|------|---------| +| 1.1.8 | Dec 27, 2025 | Section 6 SIDEBAR restructure - Dropdowns, breadcrumbs, navigation cleanup | | 1.1.7 | Dec 27, 2025 | Section 5 HELP module - Support links, Documentation, FAQ updates | | 1.1.6 | Dec 27, 2025 | Section 4 ACCOUNT modules - Profile API, Password Change, Billing improvements | | 1.1.5 | Jan 2, 2025 | Section 3 WORKFLOW modules - Planner, Writer, Progress Modal fixes | @@ -26,6 +27,60 @@ --- +## v1.1.8 - December 27, 2025 + +### Section 6 Sidebar & Navigation Restructure + +**Sidebar Module Changes:** +- **REMOVED** Linker from sidebar (module not ready for launch) +- **REMOVED** Optimizer from sidebar (module not ready for launch) +- **REORDERED** SETUP menu: Sites → Add Keywords → Content Settings → Thinker + +**Sidebar Dropdown Navigation:** +- Added sub-item dropdowns for major modules in AppSidebar.tsx: + - **Planner**: Keywords, Clusters, Ideas + - **Writer**: Queue, Drafts, Images, Review, Published + - **Content Settings**: Content Generation, Publishing, Image Settings + - **Thinker**: Prompts, Author Profiles + - **Account Settings**: Account, Profile, Team + - **Plans & Billing**: Current Plan, Upgrade Plan, History + - **Usage Analytics**: Limits & Usage, Credit History, Activity Log + +**URL-Based Tab Navigation:** +- Converted Account pages from useState tabs to URL-based navigation: + - `AccountSettingsPage.tsx` - `/account/settings`, `/account/settings/profile`, `/account/settings/team` + - `PlansAndBillingPage.tsx` - `/account/plans`, `/account/plans/upgrade`, `/account/plans/history` + - `UsageAnalyticsPage.tsx` - `/account/usage`, `/account/usage/credits`, `/account/usage/activity` + - `ContentSettingsPage.tsx` - `/account/content-settings`, `/account/content-settings/publishing`, `/account/content-settings/images` +- Added corresponding routes in App.tsx + +**ModuleNavigationTabs Removal:** +- Removed redundant ModuleNavigationTabs from all pages (navigation now via sidebar): + - Planner: Keywords.tsx, Clusters.tsx, Ideas.tsx + - Writer: Tasks.tsx, Content.tsx, Images.tsx, Review.tsx, Published.tsx + - Thinker: Prompts.tsx, AuthorProfiles.tsx, Strategies.tsx, ImageTesting.tsx + - Sites: List.tsx + +**Breadcrumb Navigation:** +- Added `breadcrumb` prop to PageHeader component +- Implemented breadcrumb display across all module pages +- Format: "Module / Page" (e.g., "Planner / Keywords", "Writer / Drafts") + +**Files Modified:** +- `frontend/src/layout/AppSidebar.tsx` - Sidebar restructure with dropdowns +- `frontend/src/App.tsx` - Added sub-routes for URL-based navigation +- `frontend/src/components/common/PageHeader.tsx` - Added breadcrumb prop +- `frontend/src/pages/account/AccountSettingsPage.tsx` - URL-based tabs +- `frontend/src/pages/account/PlansAndBillingPage.tsx` - URL-based tabs +- `frontend/src/pages/account/UsageAnalyticsPage.tsx` - URL-based tabs +- `frontend/src/pages/account/ContentSettingsPage.tsx` - URL-based tabs +- `frontend/src/pages/Planner/*.tsx` - Removed tabs, added breadcrumb +- `frontend/src/pages/Writer/*.tsx` - Removed tabs, added breadcrumb +- `frontend/src/pages/Thinker/*.tsx` - Removed tabs, added breadcrumb +- `frontend/src/pages/Sites/List.tsx` - Removed tabs, added breadcrumb + +--- + ## v1.1.7 - December 27, 2025 ### Section 5 HELP Module Implementation diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index cdb3ed7e..a6c06853 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -189,13 +189,28 @@ export default function App() { } /> {/* Account Section - Billing & Management Pages */} - } /> - } /> + {/* Account Settings - with sub-routes for sidebar navigation */} } /> + } /> + } /> {/* Legacy redirect - Team is now a tab in Account Settings */} - } /> + } /> + + {/* Plans & Billing - with sub-routes for sidebar navigation */} + } /> + } /> + } /> + } /> + + {/* Usage - with sub-routes for sidebar navigation */} } /> + } /> + } /> + + {/* Content Settings - with sub-routes for sidebar navigation */} } /> + } /> + } /> {/* Reference Data */} } /> diff --git a/frontend/src/components/common/PageHeader.tsx b/frontend/src/components/common/PageHeader.tsx index aeebff47..625043a4 100644 --- a/frontend/src/components/common/PageHeader.tsx +++ b/frontend/src/components/common/PageHeader.tsx @@ -14,6 +14,7 @@ import { WorkflowInsights, WorkflowInsight } from './WorkflowInsights'; interface PageHeaderProps { title: string; description?: string; // Optional page description shown below title + breadcrumb?: string; // Optional breadcrumb text (e.g., "Thinker / Prompts") lastUpdated?: Date; showRefresh?: boolean; onRefresh?: () => void; @@ -30,6 +31,7 @@ interface PageHeaderProps { export default function PageHeader({ title, description, + breadcrumb, lastUpdated, showRefresh = false, onRefresh, @@ -104,6 +106,13 @@ export default function PageHeader({ return (
+ {/* Breadcrumb */} + {breadcrumb && ( +
+ {breadcrumb} +
+ )} + {/* Main header row - single row with 3 sections */}
{/* Left side: Title, badge, and site/sector info */} diff --git a/frontend/src/layout/AppSidebar.tsx b/frontend/src/layout/AppSidebar.tsx index 0ea7c65f..23a0e2d0 100644 --- a/frontend/src/layout/AppSidebar.tsx +++ b/frontend/src/layout/AppSidebar.tsx @@ -52,7 +52,13 @@ const AppSidebar: React.FC = () => { const subMenuRefs = useRef>({}); const isActive = useCallback( - (path: string) => location.pathname === path, + (path: string) => { + // Exact match + if (location.pathname === path) return true; + // For sub-pages, match if pathname starts with the path (except for root) + if (path !== '/' && location.pathname.startsWith(path + '/')) return true; + return false; + }, [location.pathname] ); @@ -60,35 +66,45 @@ const AppSidebar: React.FC = () => { // New structure: Dashboard (standalone) → SETUP → WORKFLOW → SETTINGS // Module visibility is controlled by GlobalModuleSettings (Django Admin only) const menuSections: MenuSection[] = useMemo(() => { - // SETUP section items (single items, no dropdowns - submenus shown as in-page navigation) - const setupItems: NavItem[] = [ - { - icon: , - name: "Add Keywords", - path: "/setup/add-keywords", - }, - { - icon: , - name: "Content Settings", - path: "/account/content-settings", - }, - ]; + // SETUP section items - Ordered: Sites → Add Keywords → Content Settings → Thinker + const setupItems: NavItem[] = []; - // Add Sites (Site Builder) if enabled + // Add Sites first (if enabled) if (isModuleEnabled('site_builder')) { setupItems.push({ icon: , name: "Sites", - path: "/sites", // Submenus shown as in-page navigation + path: "/sites", }); } - // Add Thinker if enabled (admin only - prompts and AI settings) + // Add Keywords second + setupItems.push({ + icon: , + name: "Add Keywords", + path: "/setup/add-keywords", + }); + + // Content Settings third - with dropdown + setupItems.push({ + icon: , + name: "Content Settings", + subItems: [ + { name: "Content Generation", path: "/account/content-settings" }, + { name: "Publishing", path: "/account/content-settings/publishing" }, + { name: "Image Settings", path: "/account/content-settings/images" }, + ], + }); + + // Add Thinker last (admin only - prompts and AI settings) if (isModuleEnabled('thinker')) { setupItems.push({ icon: , name: "Thinker", - path: "/thinker/prompts", // Default to prompts, submenus shown as in-page navigation + subItems: [ + { name: "Prompts", path: "/thinker/prompts" }, + { name: "Author Profiles", path: "/thinker/author-profiles" }, + ], adminOnly: true, // Only visible to admin/staff users }); } @@ -96,25 +112,35 @@ const AppSidebar: React.FC = () => { // WORKFLOW section items (conditionally shown based on global settings) const workflowItems: NavItem[] = []; - // Add Planner if enabled + // Add Planner with dropdown if enabled if (isModuleEnabled('planner')) { workflowItems.push({ icon: , name: "Planner", - path: "/planner/keywords", // Default to keywords, submenus shown as in-page navigation + subItems: [ + { name: "Keywords", path: "/planner/keywords" }, + { name: "Clusters", path: "/planner/clusters" }, + { name: "Ideas", path: "/planner/ideas" }, + ], }); } - // Add Writer if enabled + // Add Writer with dropdown if enabled if (isModuleEnabled('writer')) { workflowItems.push({ icon: , name: "Writer", - path: "/writer/tasks", // Default to tasks, submenus shown as in-page navigation + subItems: [ + { name: "Queue", path: "/writer/tasks" }, + { name: "Drafts", path: "/writer/content" }, + { name: "Images", path: "/writer/images" }, + { name: "Review", path: "/writer/review" }, + { name: "Published", path: "/writer/published" }, + ], }); } - // Add Automation if enabled + // Add Automation if enabled (no dropdown - single page) if (isModuleEnabled('automation')) { workflowItems.push({ icon: , @@ -123,23 +149,7 @@ const AppSidebar: React.FC = () => { }); } - // Add Linker if enabled - if (isModuleEnabled('linker')) { - workflowItems.push({ - icon: , - name: "Linker", - path: "/linker/content", - }); - } - - // Add Optimizer if enabled - if (isModuleEnabled('optimizer')) { - workflowItems.push({ - icon: , - name: "Optimizer", - path: "/optimizer/content", - }); - } + // Linker and Optimizer removed - not active modules return [ // Dashboard is standalone (no section header) @@ -167,17 +177,29 @@ const AppSidebar: React.FC = () => { { icon: , name: "Account Settings", - path: "/account/settings", + subItems: [ + { name: "Account", path: "/account/settings" }, + { name: "Profile", path: "/account/settings/profile" }, + { name: "Team", path: "/account/settings/team" }, + ], }, { icon: , name: "Plans & Billing", - path: "/account/plans", + subItems: [ + { name: "Current Plan", path: "/account/plans" }, + { name: "Upgrade Plan", path: "/account/plans/upgrade" }, + { name: "History", path: "/account/plans/history" }, + ], }, { icon: , name: "Usage", - path: "/account/usage", + subItems: [ + { name: "Limits & Usage", path: "/account/usage" }, + { name: "Credit History", path: "/account/usage/credits" }, + { name: "Activity", path: "/account/usage/activity" }, + ], }, { icon: , diff --git a/frontend/src/pages/Planner/Clusters.tsx b/frontend/src/pages/Planner/Clusters.tsx index 30009195..4b4ca62b 100644 --- a/frontend/src/pages/Planner/Clusters.tsx +++ b/frontend/src/pages/Planner/Clusters.tsx @@ -27,7 +27,6 @@ import { useSectorStore } from '../../store/sectorStore'; import { usePageSizeStore } from '../../store/pageSizeStore'; import { getDifficultyLabelFromNumber, getDifficultyRange } from '../../utils/difficulty'; import PageHeader from '../../components/common/PageHeader'; -import ModuleNavigationTabs from '../../components/navigation/ModuleNavigationTabs'; import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter'; import { WorkflowInsight } from '../../components/common/WorkflowInsights'; @@ -442,20 +441,13 @@ export default function Clusters() { } }; - // Planner navigation tabs - const plannerTabs = [ - { label: 'Keywords', path: '/planner/keywords', icon: }, - { label: 'Clusters', path: '/planner/clusters', icon: }, - { label: 'Ideas', path: '/planner/ideas', icon: }, - ]; - return ( <> , color: 'purple' }} - navigation={} + breadcrumb="Planner / Clusters" workflowInsights={workflowInsights} /> }, - { label: 'Clusters', path: '/planner/clusters', icon: }, - { label: 'Ideas', path: '/planner/ideas', icon: }, - ]; - return ( <> , color: 'orange' }} - navigation={} + breadcrumb="Planner / Ideas" workflowInsights={workflowInsights} /> }, - { label: 'Clusters', path: '/planner/clusters', icon: }, - { label: 'Ideas', path: '/planner/ideas', icon: }, - ]; - return ( <> , color: 'green' }} - navigation={} + breadcrumb="Planner / Keywords" workflowInsights={workflowInsights} /> }, - ]; - return (
@@ -496,7 +490,7 @@ export default function SiteList() { title="Your Websites" badge={{ icon: , color: 'blue' }} hideSiteSector={true} - navigation={} + breadcrumb="Setup / Sites" /> {/* Custom Header Actions - Add Site button and view toggle */} diff --git a/frontend/src/pages/Thinker/AuthorProfiles.tsx b/frontend/src/pages/Thinker/AuthorProfiles.tsx index 87175a11..07d1f3a5 100644 --- a/frontend/src/pages/Thinker/AuthorProfiles.tsx +++ b/frontend/src/pages/Thinker/AuthorProfiles.tsx @@ -1,14 +1,13 @@ import { useState, useEffect } from 'react'; import PageMeta from '../../components/common/PageMeta'; import PageHeader from '../../components/common/PageHeader'; -import ModuleNavigationTabs from '../../components/navigation/ModuleNavigationTabs'; import { useToast } from '../../components/ui/toast/ToastContainer'; import { fetchAuthorProfiles, createAuthorProfile, updateAuthorProfile, deleteAuthorProfile, AuthorProfile } from '../../services/api'; import { Card } from '../../components/ui/card'; import Button from '../../components/ui/button/Button'; import FormModal, { FormField } from '../../components/common/FormModal'; import Badge from '../../components/ui/badge/Badge'; -import { PlusIcon, BoltIcon, UserIcon, ShootingStarIcon, ImageIcon } from '../../icons'; +import { PlusIcon, UserIcon } from '../../icons'; export default function AuthorProfiles() { const toast = useToast(); @@ -99,21 +98,13 @@ export default function AuthorProfiles() { { name: 'is_active', label: 'Active', type: 'checkbox', required: false }, ]; - // Thinker navigation tabs - const thinkerTabs = [ - { label: 'Prompts', path: '/thinker/prompts', icon: }, - { label: 'Author Profiles', path: '/thinker/author-profiles', icon: }, - { label: 'Strategies', path: '/thinker/strategies', icon: }, - { label: 'Image Testing', path: '/thinker/image-testing', icon: }, - ]; - return (
, color: 'blue' }} - navigation={} + breadcrumb="Thinker / Author Profiles" />
- ))} - -
- {/* Tab Content */}
{/* Account Tab */} diff --git a/frontend/src/pages/account/ContentSettingsPage.tsx b/frontend/src/pages/account/ContentSettingsPage.tsx index 3c69c8d7..bf913119 100644 --- a/frontend/src/pages/account/ContentSettingsPage.tsx +++ b/frontend/src/pages/account/ContentSettingsPage.tsx @@ -5,6 +5,7 @@ */ import { useState, useEffect, useCallback } from 'react'; +import { useLocation } from 'react-router-dom'; import { Save, Loader2, Image as ImageIcon, FileText, Send, Settings } from 'lucide-react'; @@ -83,9 +84,17 @@ const getImageSizes = (provider: string, model: string) => { return [{ value: '1024x1024', label: '1024×1024 pixels' }]; }; +// Get tab from URL path +function getTabFromPath(pathname: string): TabType { + if (pathname.includes('/publishing')) return 'publishing'; + if (pathname.includes('/images')) return 'images'; + return 'content'; +} + export default function ContentSettingsPage() { const toast = useToast(); - const [activeTab, setActiveTab] = useState('content'); + const location = useLocation(); + const activeTab = getTabFromPath(location.pathname); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); @@ -293,11 +302,11 @@ export default function ContentSettingsPage() { } }; - const tabs = [ - { id: 'content' as TabType, label: 'Content Generation', icon: }, - { id: 'publishing' as TabType, label: 'Publishing', icon: }, - { id: 'images' as TabType, label: 'Image Settings', icon: }, - ]; + const tabTitles: Record = { + content: 'Content Generation', + publishing: 'Publishing', + images: 'Image Settings', + }; if (loading) { return ( @@ -319,35 +328,17 @@ export default function ContentSettingsPage() { {/* Page Header */}
-

Content Settings

+
+ Content Settings / {tabTitles[activeTab]} +
+

{tabTitles[activeTab]}

- Configure how your content and images are generated + {activeTab === 'content' && 'Customize how your articles are written'} + {activeTab === 'publishing' && 'Configure automatic publishing settings'} + {activeTab === 'images' && 'Set up AI image generation preferences'}

- {/* Tabs */} -
- -
- {/* Tab Content */}
{/* Content Generation Tab */} diff --git a/frontend/src/pages/account/PlansAndBillingPage.tsx b/frontend/src/pages/account/PlansAndBillingPage.tsx index 127b1177..45fbcfc5 100644 --- a/frontend/src/pages/account/PlansAndBillingPage.tsx +++ b/frontend/src/pages/account/PlansAndBillingPage.tsx @@ -1,12 +1,13 @@ /** * Plans & Billing Page - Subscription & Payment Management * Tabs: Current Plan, Upgrade Plan, Billing History + * Tab selection driven by URL path for sidebar navigation * * Note: Usage tracking is consolidated in UsageAnalyticsPage (/account/usage) */ import { useState, useEffect, useRef } from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useLocation } from 'react-router-dom'; import { CreditCard, Package, TrendingUp, FileText, Wallet, ArrowUpCircle, Loader2, AlertCircle, CheckCircle, Download, Zap, Globe, Users, X @@ -49,8 +50,17 @@ import { useAuthStore } from '../../store/authStore'; type TabType = 'plan' | 'upgrade' | 'invoices'; +// Map URL paths to tab types +function getTabFromPath(pathname: string): TabType { + if (pathname.includes('/upgrade')) return 'upgrade'; + if (pathname.includes('/history')) return 'invoices'; + return 'plan'; +} + export default function PlansAndBillingPage() { - const [activeTab, setActiveTab] = useState('plan'); + const location = useLocation(); + // Derive active tab from URL path + const activeTab = getTabFromPath(location.pathname); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [planLoadingId, setPlanLoadingId] = useState(null); @@ -347,18 +357,25 @@ export default function PlansAndBillingPage() { const subscriptionStatus = currentSubscription?.status || (hasActivePlan ? 'active' : 'none'); const hasPendingManualPayment = payments.some((p) => p.status === 'pending_approval'); - const tabs = [ - { id: 'plan' as TabType, label: 'Current Plan', icon: }, - { id: 'upgrade' as TabType, label: 'Upgrade Plan', icon: }, - { id: 'invoices' as TabType, label: 'History', icon: }, - ]; + // Page titles based on active tab + const pageTitles = { + plan: { title: 'Current Plan', description: 'View your subscription details and features' }, + upgrade: { title: 'Upgrade Plan', description: 'Compare plans and upgrade your subscription' }, + invoices: { title: 'Billing History', description: 'View invoices and manage payment methods' }, + }; return (
+ {/* Page Header with Breadcrumb */}
-

Your Subscription

+
+ Plans & Billing + + {pageTitles[activeTab].title} +
+

{pageTitles[activeTab].title}

- Manage your plan and view usage + {pageTitles[activeTab].description}

@@ -367,7 +384,7 @@ export default function PlansAndBillingPage() {
No active plan. Choose a plan below to activate your account.
- )} + )}} {hasPendingManualPayment && (
We received your manual payment. It’s pending admin approval; activation will complete once approved. @@ -381,29 +398,6 @@ export default function PlansAndBillingPage() {
)} - {/* Tabs */} -
- -
- {/* Tab Content */}
{/* Current Plan Tab */} @@ -476,7 +470,8 @@ export default function PlansAndBillingPage() { - ))} - -
- - {/* Period Selector (only show on activity and api tabs) */} - {(activeTab === 'activity' || activeTab === 'api') && ( + {/* Period Selector (only show on activity and api tabs) */} + {(activeTab === 'activity' || activeTab === 'api') && ( +
{[7, 30, 90].map((value) => { const isActive = period === value; @@ -184,8 +177,8 @@ export default function UsageAnalyticsPage() { ); })}
- )} -
+
+ )} {/* Tab Content */}
diff --git a/to-do-s/part1/SECTION_6_FINAL_MODS.md b/to-do-s/part1/SECTION_6_FINAL_MODS.md index eb368aed..fb5cd041 100644 --- a/to-do-s/part1/SECTION_6_FINAL_MODS.md +++ b/to-do-s/part1/SECTION_6_FINAL_MODS.md @@ -462,3 +462,33 @@ To support sidebar navigation, routes need restructuring: - Clean, consistent navigation pattern across all modules --- + + +Section 6 implementation is complete. Here's a summary of what was done: + +## Section 6 Implementation Complete ✅ + +### Sidebar Changes +- **Removed** Linker and Optimizer modules from sidebar (not ready for launch) +- **Reordered** SETUP menu: Sites → Add Keywords → Content Settings → Thinker +- **Added dropdown sub-items** for all major modules with clickable navigation + +### URL-Based Tab Navigation +Account pages now use URL paths instead of internal state for tabs: +- `/account/settings` → Account tab, `/account/settings/profile` → Profile, `/account/settings/team` → Team +- `/account/plans` → Current Plan, `/account/plans/upgrade` → Upgrade, `/account/plans/history` → History +- `/account/usage` → Limits, `/account/usage/credits` → Credits, `/account/usage/activity` → Activity +- `/account/content-settings` → Content Generation, `/account/content-settings/publishing` → Publishing, `/account/content-settings/images` → Images + +### Navigation Cleanup +- **Removed ModuleNavigationTabs** from all module pages (Planner, Writer, Thinker, Sites) +- **Added breadcrumb prop** to PageHeader component +- All pages now display breadcrumb navigation (e.g., "Planner / Keywords") + +### Files Modified +- AppSidebar.tsx - Sidebar restructure +- App.tsx - Added sub-routes +- PageHeader.tsx - Added breadcrumb prop +- 4 account pages - URL-based tab navigation +- 3 Planner pages, 5 Writer pages, 4 Thinker pages, 1 Sites page - Removed tabs, added breadcrumbs +- CHANGELOG.md - Updated to v1.1.8