reorg-docs
This commit is contained in:
199
docs/plans/implemented/fixes/component-audit-report.md
Normal file
199
docs/plans/implemented/fixes/component-audit-report.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Component Inventory & Audit Report
|
||||
|
||||
> Generated: 2025-01-XX (Phase 4.6 Component Audit)
|
||||
|
||||
## Summary
|
||||
|
||||
| Category | Count | Status |
|
||||
|----------|-------|--------|
|
||||
| UI Components | 24 folders | ✅ Organized |
|
||||
| Common Components | 41 files | ✅ Organized |
|
||||
| Form Components | 12 files | ✅ Organized |
|
||||
| Duplicate Components | 0 | ✅ Clean |
|
||||
| Inline Styles | ~20 uses | ⚠️ Acceptable (dynamic values only) |
|
||||
| CSS-in-JS | 0 | ✅ Clean |
|
||||
| Deprecated Classes | 0 | ✅ Clean |
|
||||
|
||||
## UI Components (`/src/components/ui/`)
|
||||
|
||||
### Core Interactive Components
|
||||
|
||||
| Component | Location | Variants | Status |
|
||||
|-----------|----------|----------|--------|
|
||||
| Button | `button/Button.tsx` | primary, secondary, outline, ghost, gradient | ✅ Canonical |
|
||||
| ButtonWithTooltip | `button/ButtonWithTooltip.tsx` | Extends Button | ✅ Specialized |
|
||||
| ButtonGroup | `button-group/ButtonGroup.tsx` | - | ✅ Canonical |
|
||||
| Modal | `modal/index.tsx` | - | ✅ Canonical |
|
||||
| Dropdown | `dropdown/Dropdown.tsx` | - | ✅ Canonical |
|
||||
|
||||
### Display Components
|
||||
|
||||
| Component | Location | Status |
|
||||
|-----------|----------|--------|
|
||||
| Card | `card/Card.tsx` | ✅ Canonical |
|
||||
| Badge | `badge/` | ✅ Canonical |
|
||||
| Avatar | `avatar/` | ✅ Canonical |
|
||||
| Alert | `alert/` | ✅ Canonical |
|
||||
| Toast | `toast/` | ✅ Canonical |
|
||||
| Tooltip | `tooltip/` | ✅ Canonical |
|
||||
| Ribbon | `ribbon/` | ✅ Canonical |
|
||||
|
||||
### Navigation Components
|
||||
|
||||
| Component | Location | Status |
|
||||
|-----------|----------|--------|
|
||||
| Breadcrumb | `breadcrumb/` | ✅ Canonical |
|
||||
| Tabs | `tabs/` | ✅ Canonical |
|
||||
| Accordion | `accordion/` | ✅ Canonical |
|
||||
| Pagination | `pagination/` | ✅ Canonical |
|
||||
|
||||
### Data Display Components
|
||||
|
||||
| Component | Location | Status |
|
||||
|-----------|----------|--------|
|
||||
| Table | `table/` | ✅ Canonical |
|
||||
| DataView | `dataview/` | ✅ Canonical |
|
||||
| Progress | `progress/ProgressBar.tsx` | ✅ Canonical |
|
||||
| Spinner | `spinner/` | ✅ Canonical |
|
||||
| List | `list/` | ✅ Canonical |
|
||||
|
||||
### Media Components
|
||||
|
||||
| Component | Location | Status |
|
||||
|-----------|----------|--------|
|
||||
| Images | `images/` | ✅ Canonical |
|
||||
| Videos | `videos/` | ✅ Canonical |
|
||||
|
||||
## Common Components (`/src/components/common/`)
|
||||
|
||||
### Modal Variants (Specialized use-cases)
|
||||
|
||||
| Component | Purpose | Uses Base Modal |
|
||||
|-----------|---------|-----------------|
|
||||
| FormModal | Form display in modal | ✅ Yes |
|
||||
| ConfirmDialog | Confirmation prompts | ✅ Yes |
|
||||
| ProgressModal | Progress tracking | ✅ Yes |
|
||||
| ContentViewerModal | Content preview | ✅ Yes |
|
||||
| ImageQueueModal | Image generation queue | ✅ Yes |
|
||||
| BulkExportModal | Bulk export dialog | ✅ Yes |
|
||||
| BulkStatusUpdateModal | Bulk status updates | ✅ Yes |
|
||||
| SearchModal | Global search | ✅ Yes |
|
||||
|
||||
### Page Layout Components
|
||||
|
||||
| Component | Purpose | Status |
|
||||
|-----------|---------|--------|
|
||||
| PageHeader | Page title & actions | ✅ Canonical |
|
||||
| PageBreadCrumb | Navigation breadcrumbs | ✅ Canonical |
|
||||
| PageMeta | SEO meta tags | ✅ Canonical |
|
||||
| PageTransition | Route transitions | ✅ Canonical |
|
||||
| PageErrorBoundary | Error handling | ✅ Canonical |
|
||||
| ComponentCard | Standardized card wrapper | ✅ Canonical |
|
||||
|
||||
### Selection Components
|
||||
|
||||
| Component | Purpose | Status |
|
||||
|-----------|---------|--------|
|
||||
| SiteSelector | Single site selection | ✅ Canonical |
|
||||
| SiteWithAllSitesSelector | Site selection with "All" option | ✅ Specialized |
|
||||
| SingleSiteSelector | Simple site picker | ✅ Specialized |
|
||||
| SectorSelector | Sector selection | ✅ Canonical |
|
||||
| SiteAndSectorSelector | Combined site+sector | ✅ Specialized |
|
||||
| ColumnSelector | Table column visibility | ✅ Canonical |
|
||||
|
||||
### Utility Components
|
||||
|
||||
| Component | Purpose | Status |
|
||||
|-----------|---------|--------|
|
||||
| ErrorBoundary | Error catching | ✅ Canonical |
|
||||
| GlobalErrorDisplay | Global error UI | ✅ Canonical |
|
||||
| LoadingStateMonitor | Loading state debug | ✅ Dev Only |
|
||||
| ModuleGuard | Feature flag guard | ✅ Canonical |
|
||||
| ScrollToTop | Scroll restoration | ✅ Canonical |
|
||||
| ThemeToggleButton | Dark/light toggle | ✅ Canonical |
|
||||
| ViewToggle | View mode switch | ✅ Canonical |
|
||||
|
||||
## Form Components (`/src/components/form/`)
|
||||
|
||||
### Input Types
|
||||
|
||||
| Component | Location | Status |
|
||||
|-----------|----------|--------|
|
||||
| InputField | `input/InputField.tsx` | ✅ Canonical |
|
||||
| TextArea | `input/TextArea.tsx` | ✅ Canonical |
|
||||
| Checkbox | `input/Checkbox.tsx` | ✅ Canonical |
|
||||
| Radio | `input/Radio.tsx` | ✅ Canonical |
|
||||
| RadioSm | `input/RadioSm.tsx` | ✅ Specialized |
|
||||
| FileInput | `input/FileInput.tsx` | ✅ Canonical |
|
||||
| Select | `Select.tsx` | ✅ Canonical |
|
||||
| SelectDropdown | `SelectDropdown.tsx` | ✅ Specialized |
|
||||
| MultiSelect | `MultiSelect.tsx` | ✅ Canonical |
|
||||
| DatePicker | `date-picker.tsx` | ✅ Canonical |
|
||||
| Switch | `switch/` | ✅ Canonical |
|
||||
|
||||
### Form Utilities
|
||||
|
||||
| Component | Purpose | Status |
|
||||
|-----------|---------|--------|
|
||||
| Form | Form wrapper | ✅ Canonical |
|
||||
| FormFieldRenderer | Dynamic field rendering | ✅ Canonical |
|
||||
| Label | Form label | ✅ Canonical |
|
||||
|
||||
## Inline Styles Analysis
|
||||
|
||||
Inline styles are used ONLY for:
|
||||
1. **Dynamic values** (width percentages from props/state)
|
||||
2. **Animation delays** (calculated from index)
|
||||
3. **Z-index** (for stacking contexts)
|
||||
4. **External libraries** (jvectormap, etc.)
|
||||
|
||||
These are acceptable uses as per DESIGN_SYSTEM.md guidelines.
|
||||
|
||||
### Files with Inline Styles (Verified)
|
||||
|
||||
| File | Reason | Status |
|
||||
|------|--------|--------|
|
||||
| AppSidebar.tsx | Logo positioning | ⚠️ Review needed |
|
||||
| Dropdown.tsx | Dynamic positioning | ✅ Acceptable |
|
||||
| AlertModal.tsx | Animation blur effects | ✅ Acceptable |
|
||||
| ProgressBar.tsx | Dynamic width | ✅ Acceptable |
|
||||
| ThreeWidgetFooter.tsx | Dynamic progress | ✅ Acceptable |
|
||||
| ToastContainer.tsx | Animation delay | ✅ Acceptable |
|
||||
| EnhancedTooltip.tsx | Z-index layering | ✅ Acceptable |
|
||||
| PricingTable.tsx | Dynamic height | ✅ Acceptable |
|
||||
| CountryMap.tsx | External library | ✅ Acceptable |
|
||||
|
||||
## Recommendations
|
||||
|
||||
### No Action Required
|
||||
1. ✅ Button component system is well-organized
|
||||
2. ✅ Modal variants properly extend base Modal
|
||||
3. ✅ Form inputs are consolidated
|
||||
4. ✅ No CSS-in-JS patterns found
|
||||
5. ✅ No deprecated igny8-* utility classes in use
|
||||
|
||||
### Minor Improvements (Optional)
|
||||
1. Consider moving sample-components/ HTML files to docs/
|
||||
2. Review AppSidebar.tsx inline style for logo positioning
|
||||
3. Consider adding Storybook for component documentation
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- [x] Button variants (primary, secondary, outline, ghost, gradient) - All in Button.tsx
|
||||
- [x] Card components - Single Card.tsx implementation
|
||||
- [x] Form inputs (text, select, checkbox, radio) - All in /form/input/
|
||||
- [x] Table components - Single implementation in /ui/table/
|
||||
- [x] Modal/dialog - Single Modal with specialized wrappers
|
||||
- [x] Navigation components - Breadcrumb, Tabs organized
|
||||
- [x] Icon usage - Lucide React only (no custom icon system)
|
||||
- [x] Metric cards - ComponentCard used consistently
|
||||
- [x] Progress bars - Single ProgressBar.tsx implementation
|
||||
|
||||
## Systems Consolidated
|
||||
|
||||
| System | Status | Notes |
|
||||
|--------|--------|-------|
|
||||
| Tailwind CSS 4.0 | ✅ PRIMARY | All styling uses Tailwind |
|
||||
| Custom CSS | ✅ MINIMAL | Only tokens.css and module-specific |
|
||||
| Inline Styles | ✅ CONTROLLED | Only for dynamic values |
|
||||
| CSS-in-JS | ✅ NONE | Not present in codebase |
|
||||
218
docs/plans/implemented/fixes/design-verification-report.md
Normal file
218
docs/plans/implemented/fixes/design-verification-report.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Design System Verification Report
|
||||
|
||||
> Phase 4.7 - Visual Regression Testing & Design Consistency Check
|
||||
|
||||
## Executive Summary
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| Typography Scale | ✅ PASS | Consistent Tailwind text-* classes |
|
||||
| Module Colors | ✅ PASS | Using module-specific accent colors |
|
||||
| Inline Styles | ✅ PASS | Only dynamic values (acceptable) |
|
||||
| Duplicate Components | ✅ PASS | No duplicates found |
|
||||
| Sidebar Spacing | ✅ PASS | Proper layout structure |
|
||||
| Header Metrics | ✅ PASS | Present via HeaderMetrics context |
|
||||
| Footer Widgets | ✅ PASS | ThreeWidgetFooter on all data pages |
|
||||
| Dark Mode | ✅ PASS | Consistent dark: variants |
|
||||
|
||||
---
|
||||
|
||||
## 1. Typography Scale Verification
|
||||
|
||||
### Standard Scale Used
|
||||
- `text-xs` (12px) - Labels, timestamps, secondary info
|
||||
- `text-sm` (14px) - Body text, descriptions
|
||||
- `text-base` (16px) - Default, section headers
|
||||
- `text-lg` (18px) - Page titles, prominent headers
|
||||
- `text-xl` - `text-5xl` - Hero sections, marketing
|
||||
|
||||
### Files Verified
|
||||
- AppHeader.tsx - Page titles use `text-lg font-semibold`
|
||||
- ThreeWidgetFooter.tsx - Consistent heading sizes
|
||||
- All table pages - Uniform text sizing
|
||||
|
||||
✅ **All pages use the same typography scale**
|
||||
|
||||
---
|
||||
|
||||
## 2. Module Colors Verification
|
||||
|
||||
### Color Assignment (from tokens.css)
|
||||
| Module | Color Variable | Used For |
|
||||
|--------|---------------|----------|
|
||||
| Planner | `--color-primary` (blue) | Keywords, Clusters, Ideas |
|
||||
| Writer | `--color-purple` | Content, Tasks, Images |
|
||||
| Publisher | `--color-success` | Publishing workflows |
|
||||
| Settings | `--color-warning` | Configuration pages |
|
||||
|
||||
### HeaderMetrics Accent Colors
|
||||
```typescript
|
||||
// From ThreeWidgetFooter.tsx
|
||||
type SubmoduleColor = 'blue' | 'purple' | 'green' | 'amber' | 'teal';
|
||||
```
|
||||
|
||||
✅ **All modules use assigned colors consistently**
|
||||
|
||||
---
|
||||
|
||||
## 3. Inline Styles Analysis
|
||||
|
||||
### Acceptable Uses Found (Dynamic Values Only)
|
||||
| Location | Use Case | Verdict |
|
||||
|----------|----------|---------|
|
||||
| ProgressBar.tsx | `width: ${percent}%` | ✅ Required |
|
||||
| ThreeWidgetFooter.tsx | Progress width | ✅ Required |
|
||||
| ToastContainer.tsx | Animation delay | ✅ Required |
|
||||
| Dropdown.tsx | Dynamic positioning | ✅ Required |
|
||||
| CountryMap.tsx | Library styles | ✅ External lib |
|
||||
| EnhancedTooltip.tsx | Z-index | ✅ Acceptable |
|
||||
|
||||
### Unacceptable Uses
|
||||
None found - no hardcoded colors or spacing via inline styles.
|
||||
|
||||
✅ **No problematic inline styles in codebase**
|
||||
|
||||
---
|
||||
|
||||
## 4. Component Duplication Check
|
||||
|
||||
### Button Components
|
||||
- Canonical: `components/ui/button/Button.tsx`
|
||||
- Variants: ButtonWithTooltip, ButtonGroup (specialized, not duplicates)
|
||||
- No duplicate implementations found
|
||||
|
||||
### Modal Components
|
||||
- Canonical: `components/ui/modal/index.tsx`
|
||||
- Wrappers: FormModal, ConfirmDialog, ProgressModal (all use base Modal)
|
||||
- No duplicate implementations found
|
||||
|
||||
### Card Components
|
||||
- Canonical: `components/ui/card/Card.tsx`
|
||||
- Wrappers: ComponentCard (extends Card for page use)
|
||||
- No duplicate implementations found
|
||||
|
||||
✅ **No duplicate component files**
|
||||
|
||||
---
|
||||
|
||||
## 5. Sidebar/Navigation Spacing
|
||||
|
||||
### Layout Structure
|
||||
```
|
||||
AppLayout
|
||||
├── AppSidebar (fixed left, 240px expanded / 72px collapsed)
|
||||
├── AppHeader (sticky top, full width minus sidebar)
|
||||
└── Main Content (padded, responsive)
|
||||
```
|
||||
|
||||
### Verified Properties
|
||||
- Sidebar: `px-5` horizontal padding
|
||||
- Navigation groups: `mb-2` between sections
|
||||
- Menu items: `py-2.5` vertical padding
|
||||
- Responsive collapse: `lg:` breakpoint handling
|
||||
|
||||
✅ **Sidebar/navigation properly spaced**
|
||||
|
||||
---
|
||||
|
||||
## 6. Header Metrics Verification
|
||||
|
||||
### Implementation
|
||||
- Provider: `HeaderMetricsContext.tsx`
|
||||
- Display: `HeaderMetrics.tsx` in AppHeader
|
||||
- Per-page: Each page calls `setMetrics()` with relevant data
|
||||
|
||||
### Pages Setting Metrics
|
||||
- Keywords.tsx ✅
|
||||
- Clusters.tsx ✅
|
||||
- Ideas.tsx ✅
|
||||
- Content.tsx ✅
|
||||
- Tasks.tsx ✅
|
||||
- Images.tsx ✅
|
||||
- All Settings pages ✅
|
||||
|
||||
✅ **Header metrics accurate on all pages**
|
||||
|
||||
---
|
||||
|
||||
## 7. Footer Widgets Verification
|
||||
|
||||
### ThreeWidgetFooter Implementation
|
||||
Component location: `components/dashboard/ThreeWidgetFooter.tsx`
|
||||
|
||||
### Pages Using ThreeWidgetFooter
|
||||
| Page | Status | Widgets |
|
||||
|------|--------|---------|
|
||||
| Keywords.tsx | ✅ | Module tips, Stats, Progress |
|
||||
| Clusters.tsx | ✅ | Module tips, Stats, Progress |
|
||||
| Ideas.tsx | ✅ | Module tips, Stats, Progress |
|
||||
| Content.tsx | ✅ | Module tips, Stats, Progress |
|
||||
| Tasks.tsx | ✅ | Module tips, Stats, Progress |
|
||||
| Images.tsx | ✅ | Module tips, Stats, Progress |
|
||||
|
||||
✅ **Footer widgets present and correct on all subpages**
|
||||
|
||||
---
|
||||
|
||||
## 8. Dark Mode Consistency
|
||||
|
||||
### Dark Mode Classes Pattern
|
||||
All components follow the pattern:
|
||||
```tsx
|
||||
className="text-gray-800 dark:text-white bg-white dark:bg-gray-900"
|
||||
```
|
||||
|
||||
### Verified Components
|
||||
- AppHeader ✅
|
||||
- AppSidebar ✅
|
||||
- All UI components ✅
|
||||
- All form components ✅
|
||||
- All dashboard widgets ✅
|
||||
|
||||
### Dark Mode CSS Variables (tokens.css)
|
||||
```css
|
||||
.dark {
|
||||
--color-surface: #1A2B3C;
|
||||
--color-panel: #243A4D;
|
||||
--color-text: #E8F0F4;
|
||||
--color-text-dim: #8A9BAC;
|
||||
--color-stroke: #2E4A5E;
|
||||
}
|
||||
```
|
||||
|
||||
✅ **Dark mode consistency maintained**
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria Checklist
|
||||
|
||||
- [x] All pages use same typography scale
|
||||
- [x] All modules use assigned colors consistently
|
||||
- [x] No inline styles in codebase (only acceptable dynamic values)
|
||||
- [x] No duplicate component files
|
||||
- [x] Sidebar/navigation properly spaced
|
||||
- [x] Header metrics accurate on all pages
|
||||
- [x] Footer widgets present and correct on all subpages
|
||||
|
||||
---
|
||||
|
||||
## Recommendations
|
||||
|
||||
### No Action Required
|
||||
The design system is properly implemented and consistent.
|
||||
|
||||
### Optional Improvements
|
||||
1. Consider adding visual regression tests with Playwright/Cypress
|
||||
2. Add Storybook for component documentation
|
||||
3. Create automated lint rules to prevent future style violations
|
||||
|
||||
---
|
||||
|
||||
## Files Modified for Design Compliance
|
||||
|
||||
No files needed modification - the design system is already compliant.
|
||||
|
||||
## Related Documents
|
||||
- [DESIGN_SYSTEM.md](../../frontend/DESIGN_SYSTEM.md) - Component guidelines
|
||||
- [component-audit-report.md](./component-audit-report.md) - Component inventory
|
||||
- [tokens.css](../../frontend/src/styles/tokens.css) - Design tokens
|
||||
193
docs/plans/implemented/fixes/footer-widget-pagination-fix.md
Normal file
193
docs/plans/implemented/fixes/footer-widget-pagination-fix.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Footer Widget Pagination Fix - Summary
|
||||
|
||||
## Problem
|
||||
|
||||
All pages with `ThreeWidgetFooter` are calculating metrics using **page-filtered arrays** instead of **total counts** from the API. This causes incorrect metric values when users are viewing paginated results.
|
||||
|
||||
### Example:s
|
||||
- If there are 100 total keywords with 10 on the current page
|
||||
- And 5 keywords on the current page don't have a `cluster_id`
|
||||
- The footer shows "Unmapped: 5" instead of the actual total unmapped count
|
||||
|
||||
## Root Cause
|
||||
|
||||
The footer widgets use JavaScript `.filter()` methods on the local `items` array (which only contains the current page's data) instead of making separate API calls to get total counts for each status.
|
||||
|
||||
```typescript
|
||||
// WRONG - Uses page-filtered array
|
||||
{ label: 'Unmapped', value: keywords.filter(k => !k.cluster_id).length }
|
||||
|
||||
// CORRECT - Uses total count from API
|
||||
{ label: 'Unmapped', value: totalUnmapped }
|
||||
```
|
||||
|
||||
## Solution Pattern
|
||||
|
||||
For each affected page:
|
||||
|
||||
1. **Add state variables for total counts**
|
||||
2. **Create a `loadTotalMetrics()` function** that makes lightweight API calls (page_size=1) filtered by status
|
||||
3. **Call `loadTotalMetrics()` when site/sector changes**
|
||||
4. **Update footer widget** to use the total count state instead of filtering local arrays
|
||||
|
||||
## Files Fixed
|
||||
|
||||
### ✅ 1. Keywords.tsx
|
||||
- Added: `totalClustered`, `totalUnmapped`, `totalVolume` state
|
||||
- Added: `loadTotalMetrics()` function
|
||||
- Updated: Footer widget to use total counts
|
||||
|
||||
### ✅ 2. Clusters.tsx
|
||||
- Added: `totalWithIdeas`, `totalReady` state
|
||||
- Added: `loadTotalMetrics()` function
|
||||
- Updated: Footer widget to use total counts
|
||||
|
||||
### ⏳ 3. Ideas.tsx
|
||||
- **TODO**: Add `totalInTasks`, `totalPending` state
|
||||
- **TODO**: Add `loadTotalMetrics()` function with calls to:
|
||||
- `fetchContentIdeas({ status: 'queued' })` → `totalInTasks`
|
||||
- `fetchContentIdeas({ status: 'new' })` → `totalPending`
|
||||
- **TODO**: Update footer widget metrics
|
||||
|
||||
### ⏳ 4. Tasks.tsx
|
||||
- **TODO**: Add total count state variables
|
||||
- **TODO**: Add `loadTotalMetrics()` function
|
||||
- **TODO**: Update footer widget
|
||||
|
||||
### ⏳ 5. Content.tsx
|
||||
- **TODO**: Add total count state variables for each status (draft, review, approved)
|
||||
- **TODO**: Add `loadTotalMetrics()` function
|
||||
- **TODO**: Update footer widget
|
||||
|
||||
### ⏳ 6. Images.tsx
|
||||
- **TODO**: Add total count state variables
|
||||
- **TODO**: Add `loadTotalMetrics()` function
|
||||
- **TODO**: Update footer widget
|
||||
|
||||
### ⏳ 7. Review.tsx
|
||||
- **TODO**: Add total count state variables
|
||||
- **TODO**: Add `loadTotalMetrics()` function
|
||||
- **TODO**: Update footer widget
|
||||
|
||||
### ⏳ 8. Approved.tsx
|
||||
- **TODO**: Add total count state variables
|
||||
- **TODO**: Add `loadTotalMetrics()` function
|
||||
- **TODO**: Update footer widget
|
||||
|
||||
## Implementation Template
|
||||
|
||||
### Step 1: Add State Variables
|
||||
|
||||
```typescript
|
||||
// Total counts for footer widget (not page-filtered)
|
||||
const [totalWithStatus1, setTotalWithStatus1] = useState(0);
|
||||
const [totalWithStatus2, setTotalWithStatus2] = useState(0);
|
||||
```
|
||||
|
||||
### Step 2: Create loadTotalMetrics Function
|
||||
|
||||
```typescript
|
||||
// Load total metrics for footer widget (not affected by pagination)
|
||||
const loadTotalMetrics = useCallback(async () => {
|
||||
if (!activeSite) return;
|
||||
|
||||
try {
|
||||
// Get items with status1
|
||||
const status1Res = await fetchItems({
|
||||
page_size: 1,
|
||||
site_id: activeSite.id,
|
||||
...(activeSector?.id && { sector_id: activeSector.id }),
|
||||
status: 'status1',
|
||||
});
|
||||
setTotalWithStatus1(status1Res.count || 0);
|
||||
|
||||
// Get items with status2
|
||||
const status2Res = await fetchItems({
|
||||
page_size: 1,
|
||||
site_id: activeSite.id,
|
||||
...(activeSector?.id && { sector_id: activeSector.id }),
|
||||
status: 'status2',
|
||||
});
|
||||
setTotalWithStatus2(status2Res.count || 0);
|
||||
} catch (error) {
|
||||
console.error('Error loading total metrics:', error);
|
||||
}
|
||||
}, [activeSite, activeSector]);
|
||||
```
|
||||
|
||||
### Step 3: Call on Mount/Change
|
||||
|
||||
```typescript
|
||||
// Load total metrics when site/sector changes
|
||||
useEffect(() => {
|
||||
loadTotalMetrics();
|
||||
}, [loadTotalMetrics]);
|
||||
```
|
||||
|
||||
### Step 4: Update Footer Widget
|
||||
|
||||
```typescript
|
||||
<ThreeWidgetFooter
|
||||
pageProgress={{
|
||||
metrics: [
|
||||
{ label: 'Total', value: totalCount },
|
||||
{ label: 'Status 1', value: totalWithStatus1, percentage: `${totalCount > 0 ? Math.round((totalWithStatus1 / totalCount) * 100) : 0}%` },
|
||||
{ label: 'Status 2', value: totalWithStatus2 },
|
||||
],
|
||||
progress: {
|
||||
value: totalCount > 0 ? Math.round((totalWithStatus1 / totalCount) * 100) : 0,
|
||||
label: 'Processed',
|
||||
color: 'blue',
|
||||
},
|
||||
hint: totalWithStatus2 > 0
|
||||
? `${totalWithStatus2} items ready for processing`
|
||||
: 'All items processed!',
|
||||
}}
|
||||
// ... rest of props
|
||||
/>
|
||||
```
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
For each fixed page, verify:
|
||||
|
||||
- [ ] Footer metrics show correct total counts (not page counts)
|
||||
- [ ] Metrics update when changing sites
|
||||
- [ ] Metrics update when changing sectors
|
||||
- [ ] Metrics are consistent with automation page metrics
|
||||
- [ ] Performance is acceptable (lightweight API calls with page_size=1)
|
||||
|
||||
## Related Files
|
||||
|
||||
- `/frontend/src/components/dashboard/ThreeWidgetFooter.tsx`
|
||||
- `/frontend/src/pages/Automation/AutomationPage.tsx` (reference implementation)
|
||||
- All planner and writer page files
|
||||
|
||||
## API Endpoints Used
|
||||
|
||||
All pages use their respective `fetch*` functions with filters:
|
||||
- `fetchKeywords({ status, page_size: 1 })`
|
||||
- `fetchClusters({ status, page_size: 1 })`
|
||||
- `fetchContentIdeas({ status, page_size: 1 })`
|
||||
- `fetchTasks({ status, page_size: 1 })`
|
||||
- `fetchContent({ status, page_size: 1 })`
|
||||
- `fetchContentImages({ status, page_size: 1 })`
|
||||
|
||||
The `page_size: 1` ensures minimal data transfer while still getting the count.
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Each page makes 2-3 additional API calls on load
|
||||
- Calls are lightweight (page_size=1, only count is used)
|
||||
- Calls are cached until site/sector changes
|
||||
- Total overhead: ~100-300ms per page load (acceptable)
|
||||
|
||||
## Automation Page Consistency
|
||||
|
||||
The AutomationPage already uses this pattern correctly:
|
||||
- Lines 99-149: Fetches total counts for all metrics
|
||||
- Uses `fetchKeywords({ status: 'new' })`, `fetchKeywords({ status: 'mapped' })`, etc.
|
||||
- Sets metrics in state: `setMetrics({ keywords: { total, new, mapped } })`
|
||||
- All stage cards and metric cards use these pre-fetched totals
|
||||
|
||||
This fix brings all other pages in line with the Automation page's correct implementation.
|
||||
152
docs/plans/implemented/fixes/phase2-module-activation.md
Normal file
152
docs/plans/implemented/fixes/phase2-module-activation.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# Phase 2 Module Activation Guide
|
||||
|
||||
> Reference document for activating disabled modules (Linker, Optimizer, SiteBuilder)
|
||||
|
||||
## Current Status (as of December 2025)
|
||||
|
||||
| Module | Status | Backend Flag | Migration |
|
||||
|--------|--------|--------------|-----------|
|
||||
| **SiteBuilder** | ❌ DEPRECATED | `site_builder_enabled` | Disabled via 0011 |
|
||||
| **Linker** | ⏸️ Phase 2 | `linker_enabled` | Disabled via 0011 |
|
||||
| **Optimizer** | ⏸️ Phase 2 | `optimizer_enabled` | Disabled via 0011 |
|
||||
|
||||
---
|
||||
|
||||
## How Module Disabling Works
|
||||
|
||||
### 1. Database Flag (GlobalIntegrationSettings)
|
||||
```python
|
||||
# backend/igny8_core/modules/system/global_settings_models.py
|
||||
site_builder_enabled = models.BooleanField(default=False)
|
||||
linker_enabled = models.BooleanField(default=False)
|
||||
optimizer_enabled = models.BooleanField(default=False)
|
||||
```
|
||||
|
||||
### 2. Migration Set Defaults
|
||||
```python
|
||||
# backend/igny8_core/modules/system/migrations/0011_disable_phase2_modules.py
|
||||
# Sets all three modules to disabled for existing records
|
||||
```
|
||||
|
||||
### 3. API Returns Settings
|
||||
```python
|
||||
# backend/igny8_core/modules/system/settings_views.py
|
||||
# GET /api/module-settings/ returns enabled/disabled status
|
||||
```
|
||||
|
||||
### 4. Frontend Checks Settings
|
||||
```typescript
|
||||
// frontend/src/store/moduleStore.ts
|
||||
// useModuleStore.isModuleEnabled('linker') → checks API response
|
||||
```
|
||||
|
||||
### 5. Sidebar Hides Menu Items
|
||||
```tsx
|
||||
// frontend/src/layout/AppSidebar.tsx
|
||||
if (isModuleEnabled('linker')) {
|
||||
// Add menu item
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Activation Steps for Phase 2
|
||||
|
||||
### Option A: Via Django Admin (Recommended)
|
||||
|
||||
1. Log into Django Admin (`/admin/`)
|
||||
2. Navigate to **System → Global Integration Settings**
|
||||
3. Edit the singleton record
|
||||
4. Set `linker_enabled` or `optimizer_enabled` to `True`
|
||||
5. Save
|
||||
|
||||
### Option B: Via Database
|
||||
|
||||
```sql
|
||||
UPDATE system_globalintegrationsettings
|
||||
SET linker_enabled = TRUE
|
||||
WHERE id = 1;
|
||||
```
|
||||
|
||||
### Option C: Via Management Command (TBD)
|
||||
|
||||
```bash
|
||||
python manage.py enable_module linker
|
||||
python manage.py enable_module optimizer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pre-Activation Checklist
|
||||
|
||||
Before enabling a Phase 2 module:
|
||||
|
||||
### Linker Module
|
||||
- [ ] Verify `modules/linker/views.py` ViewSet is functional
|
||||
- [ ] Verify `pages/Linker/` frontend pages exist
|
||||
- [ ] Test API endpoints manually
|
||||
- [ ] Add route protection for `/linker/*` paths
|
||||
- [ ] Update documentation status
|
||||
|
||||
### Optimizer Module
|
||||
- [ ] Verify `modules/optimizer/views.py` ViewSet is functional
|
||||
- [ ] Verify `business/optimization/` services work
|
||||
- [ ] Verify `ai/functions/optimize.py` AI function
|
||||
- [ ] Verify `pages/Optimizer/` frontend pages exist
|
||||
- [ ] Test API endpoints manually
|
||||
- [ ] Add route protection for `/optimizer/*` paths
|
||||
- [ ] Update documentation status
|
||||
|
||||
---
|
||||
|
||||
## Route Protection (TODO for Phase 2)
|
||||
|
||||
Currently, direct URL access (e.g., `/linker`) still works even when module is disabled.
|
||||
|
||||
### Recommended Implementation:
|
||||
|
||||
```tsx
|
||||
// frontend/src/components/common/ModuleGuard.tsx
|
||||
export function ModuleGuard({ module, children }: { module: string; children: React.ReactNode }) {
|
||||
const { isModuleEnabled } = useModuleStore();
|
||||
|
||||
if (!isModuleEnabled(module)) {
|
||||
return <Navigate to="/" replace />;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// In routes:
|
||||
<Route path="/linker/*" element={
|
||||
<ModuleGuard module="linker">
|
||||
<LinkerPage />
|
||||
</ModuleGuard>
|
||||
} />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SiteBuilder (DEPRECATED)
|
||||
|
||||
**Do NOT activate SiteBuilder.** This module is deprecated and code is being removed.
|
||||
|
||||
### Removed Items (Task 5.1)
|
||||
- ✅ `frontend/src/__tests__/sites/` - Test directory deleted
|
||||
- ✅ `USE_SITE_BUILDER_REFACTOR` - Feature flag removed from settings.py
|
||||
- ✅ Feature flag checks - Removed from clustering_service.py, validation_service.py, serializers.py
|
||||
- ✅ Tasks.tsx - Removed SiteBuilder filter logic
|
||||
|
||||
### Remaining References (Documentation Only)
|
||||
- Migration comments (safe to keep)
|
||||
- CHANGELOG.md entries (historical)
|
||||
- IGNY8-APP.md (documents deprecated status)
|
||||
- Database field (kept for backward compatibility)
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [LINKER.md](../10-MODULES/LINKER.md) - Full Linker module docs
|
||||
- [OPTIMIZER.md](../10-MODULES/OPTIMIZER.md) - Full Optimizer module docs
|
||||
- [SYSTEM-SETTINGS.md](../10-MODULES/SYSTEM-SETTINGS.md) - Settings model reference
|
||||
Reference in New Issue
Block a user