Refactor code structure for improved readability and maintainability
This commit is contained in:
parent
fb72ef6dc4
commit
b37c7d0bf4
5 changed files with 831 additions and 0 deletions
831
ROADMAP.md
Normal file
831
ROADMAP.md
Normal file
|
|
@ -0,0 +1,831 @@
|
|||
# HP CG Production Tracker — Roadmap
|
||||
|
||||
> Single source of truth for project status and remaining work.
|
||||
> Previous planning documents (IMPLEMENTATION_PLAN.md, UPGRADE_PLAN.md) are archived in `docs/archive/`.
|
||||
|
||||
*Last updated: 2026-03-14*
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [What's Built](#whats-built)
|
||||
2. [Remaining Work — Priority Order](#remaining-work--priority-order)
|
||||
- [A. Image Comparison & Visual Review](#a-image-comparison--visual-review)
|
||||
- [B. Collaboration Enhancements](#b-collaboration-enhancements)
|
||||
- [C. Reporting Completions](#c-reporting-completions)
|
||||
- [D. Automation Completions](#d-automation-completions)
|
||||
- [E. Asset Intelligence](#e-asset-intelligence)
|
||||
- [F. Quality of Life](#f-quality-of-life)
|
||||
- [G. Docker Deployment](#g-docker-deployment)
|
||||
3. [Data Model Status](#data-model-status)
|
||||
4. [Architecture Reference](#architecture-reference)
|
||||
|
||||
---
|
||||
|
||||
## What's Built
|
||||
|
||||
### Core Foundation (Phases 1–4)
|
||||
|
||||
| Feature | Status |
|
||||
|---|---|
|
||||
| Project scaffold (Next.js, TS, Tailwind, Prisma, Auth.js) | ✅ Complete |
|
||||
| Design system (Oliver Agency palette, Montserrat + Inter, light/dark) | ✅ Complete |
|
||||
| Auth — SSO (Google + Microsoft Entra ID) + dev bypass | ✅ Complete |
|
||||
| Project CRUD + deliverable CRUD with auto-pipeline | ✅ Complete |
|
||||
| User management + role assignment | ✅ Complete |
|
||||
| Dependency engine + stage state machine | ✅ Complete |
|
||||
| Artist assignments + My Work page | ✅ Complete |
|
||||
| Table view (TanStack Table, filters, sort, column visibility) | ✅ Complete |
|
||||
| Board view (Kanban drag-and-drop) | ✅ Complete |
|
||||
| Timeline view (Gantt with dependencies) | ✅ Complete |
|
||||
| Dashboard (KPIs, charts, overdue alerts) | ✅ Complete |
|
||||
| Revision tracking (rounds, feedback notes, history) | ✅ Complete |
|
||||
| Threaded comment system | ✅ Complete |
|
||||
| Notification system (in-app bell + full page) | ✅ Complete |
|
||||
| Excel import (bulk upload from Master CG Tracker) | ✅ Complete |
|
||||
| Excel export | ✅ Complete |
|
||||
| Deadline tracking (approaching/overdue + notifications) | ✅ Complete |
|
||||
| Command palette (Cmd+K) | ✅ Complete |
|
||||
| Bulk operations (multi-select → batch status/assignment/priority) | ✅ Complete |
|
||||
| Loading skeletons, error boundaries, empty states | ✅ Complete |
|
||||
| Responsive design + mobile sidebar | ✅ Complete |
|
||||
| Accessibility (skip-to-content, ARIA, focus-visible) | ✅ Complete |
|
||||
| Stage date override + scheduling features | ✅ Complete |
|
||||
|
||||
### Beyond Phase 4 (implemented opportunistically)
|
||||
|
||||
| Feature | Notes |
|
||||
|---|---|
|
||||
| **Workload capacity grid** | Artist × Week grid with status bars, overallocation warnings, 4/8/12-week projections |
|
||||
| **Utilization heatmap** | Color-coded heatmap on calendar + workload page, toggle between views |
|
||||
| **Calendar view** | Monthly calendar with event pills, filters, day detail, heatmap overlay. *Not in original plan.* |
|
||||
| **Automation rule engine** | Full trigger/action engine with event bus, rule evaluator, action executor, execution log |
|
||||
| **Semantic search (pgvector + Ollama)** | Embedding service, hybrid search, pgvector columns on Project + Deliverable |
|
||||
| **AI Chat panel** | SSE streaming chat with tool calls (search_entities), entity cards, project/deliverable context. *Not in original plan.* |
|
||||
| **Weekly executive report** | Full report page at `/reports/weekly/[date]` with KPI strip, completed, deadlines, at-risk, upcoming sections |
|
||||
| **Skill data model** | `Skill`, `UserSkill`, `StageSkillRequirement` in schema with seed data — **no assignment UI yet** |
|
||||
|
||||
---
|
||||
|
||||
## Remaining Work — Priority Order
|
||||
|
||||
---
|
||||
|
||||
### A. Image Comparison & Visual Review
|
||||
|
||||
The highest-impact remaining feature area. CG production review is fundamentally visual — everything else supports this core workflow.
|
||||
|
||||
---
|
||||
|
||||
#### A1 — Reference Image Comparison (Lightweight, in Stage Detail)
|
||||
|
||||
**What:** A-B comparison tools embedded in the existing stage detail sheet. Producers and artists compare the reference/approved image against the current WIP render without leaving the deliverable page.
|
||||
|
||||
**Why first:** Lower complexity than the full review viewer (A2). Directly improves the daily review loop for existing users and unblocks meaningful visual feedback on revision rounds.
|
||||
|
||||
**Implementation:**
|
||||
- New "Compare" tab in the stage detail sheet (alongside Revisions and Comments tabs)
|
||||
- Upload zones for reference image + current render per revision round
|
||||
- Three comparison modes:
|
||||
- **A-B Slider** — draggable vertical divider (CSS clip-path + pointer events, no dependency)
|
||||
- **Toggle** — click/Space to crossfade between images
|
||||
- **Side-by-side** — synced zoom/pan on wide screens
|
||||
- Scroll-to-zoom + click-drag pan, synced across both images in all modes
|
||||
- Image gallery: thumbnails of all uploaded images across all revision rounds with round labels
|
||||
- **PNG alpha compositing on upload** — flatten transparent PNGs onto white background server-side using `sharp`, so CG renders with transparent drop shadows compare correctly
|
||||
- Extend `Revision.attachments` JSON schema: `{ referenceImage?: {...}, currentImage?: {...}, annotations?: [...] }`
|
||||
- Lightweight markup overlay (optional): arrow, rectangle, freehand, text pin drawn on top of current image
|
||||
|
||||
**New API endpoints:**
|
||||
- `POST /api/stages/[stageId]/revisions/[revisionId]/upload` — multipart, reference or current image
|
||||
- `DELETE /api/stages/[stageId]/revisions/[revisionId]/upload` — remove image
|
||||
|
||||
**Key files:**
|
||||
- `src/components/revisions/image-compare-slider.tsx` — A-B slider with drag handle
|
||||
- `src/components/revisions/image-toggle.tsx` — Toggle/crossfade
|
||||
- `src/components/revisions/image-side-by-side.tsx` — Synced side-by-side with zoom/pan
|
||||
- `src/components/revisions/image-upload-zone.tsx` — Drag-and-drop upload
|
||||
- `src/components/revisions/revision-image-gallery.tsx` — Browse images across revision rounds
|
||||
- `src/components/revisions/compare-tab.tsx` — Orchestrator: mode selector + comparison view
|
||||
- `src/components/revisions/markup-overlay.tsx` — Lightweight annotation layer
|
||||
|
||||
**New dependency:** `sharp` (server-side PNG alpha compositing on upload)
|
||||
|
||||
---
|
||||
|
||||
#### A2 — Full-Screen Image Viewer
|
||||
|
||||
**What:** Dedicated full-screen viewer with high-fidelity zoom (up to 200%+) for pixel-level inspection of CG renders.
|
||||
|
||||
**Implementation:**
|
||||
- Canvas-based viewer with WebGL acceleration for large images
|
||||
- Zoom: scroll wheel, pinch, keyboard (+/-), toolbar buttons (fit, 50%, 100%, 150%, 200%, free)
|
||||
- Pan via click-drag when zoomed; minimap overlay showing viewport position
|
||||
- Pixel coordinate + color value readout (RGB/Hex) in status bar
|
||||
- High-DPI display support (retina)
|
||||
|
||||
**Key files:**
|
||||
- `src/components/review/image-viewer.tsx`
|
||||
- `src/components/review/zoom-controls.tsx`
|
||||
- `src/components/review/minimap.tsx`
|
||||
- `src/hooks/use-image-viewer.ts`
|
||||
|
||||
---
|
||||
|
||||
#### A3 — Pixel-Accurate Annotations
|
||||
|
||||
**What:** Draw annotations directly on images — circles, rectangles, arrows, freehand, text labels, pins. Anchored to image coordinates so they stay accurate at any zoom level.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model Annotation {
|
||||
id String @id @default(cuid())
|
||||
commentId String
|
||||
comment Comment @relation(fields: [commentId], references: [id], onDelete: Cascade)
|
||||
revisionId String
|
||||
revision Revision @relation(fields: [revisionId], references: [id], onDelete: Cascade)
|
||||
type AnnotationType
|
||||
data Json // { x, y, width, height, points[], text, color, strokeWidth }
|
||||
imageX Float
|
||||
imageY Float
|
||||
createdById String
|
||||
createdBy User @relation(fields: [createdById], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
enum AnnotationType { RECTANGLE ELLIPSE ARROW FREEHAND TEXT PIN }
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/components/review/annotation-layer.tsx`
|
||||
- `src/components/review/annotation-tools.tsx`
|
||||
- `src/components/review/annotation-renderer.tsx`
|
||||
- `src/lib/services/annotation-service.ts`
|
||||
- `src/lib/validators/annotation.ts`
|
||||
- `src/hooks/use-annotations.ts`
|
||||
|
||||
**Dependencies:** Requires A2 (Image Viewer)
|
||||
|
||||
---
|
||||
|
||||
#### A4 — Side-by-Side Version Comparison (Full Viewer)
|
||||
|
||||
**What:** Compare two revisions in the full-screen viewer using side-by-side, overlay (opacity slider), wipe (draggable divider), or onion skin modes.
|
||||
|
||||
**Key files:**
|
||||
- `src/components/review/comparison-viewer.tsx`
|
||||
- `src/components/review/wipe-divider.tsx`
|
||||
- `src/components/review/overlay-controls.tsx`
|
||||
- `src/app/(app)/projects/[projectId]/deliverables/[deliverableId]/review/page.tsx`
|
||||
|
||||
**Dependencies:** Requires A2
|
||||
|
||||
---
|
||||
|
||||
#### A5 — Revision History Timeline
|
||||
|
||||
**What:** Collapsible panel in the review viewer showing all revision rounds as a vertical timeline. Each node shows thumbnail, status badge, submitter, annotation count, comment summary, and decision record.
|
||||
|
||||
**No new data model** — aggregation over existing `Revision`, `Comment`, and `Annotation` records.
|
||||
|
||||
**Key files:**
|
||||
- `src/components/review/revision-timeline.tsx`
|
||||
- `src/components/review/revision-node.tsx`
|
||||
- `src/components/review/revision-comments.tsx`
|
||||
- `src/components/review/revision-annotations-summary.tsx`
|
||||
- `src/hooks/use-revision-history.ts`
|
||||
|
||||
**Dependencies:** Requires A2 + A3
|
||||
|
||||
---
|
||||
|
||||
#### A6 — Feedback Action Items (Artist Checklist)
|
||||
|
||||
**What:** Every annotation and actionable comment auto-creates a FeedbackItem on a structured checklist. Artists work through items (Critical / Major / Minor / Suggestion), check them off with resolution notes. Unresolved critical items block resubmission. Checklist appears in three places: review viewer panel, My Work page, and stage card badge.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model FeedbackItem {
|
||||
id String @id @default(cuid())
|
||||
deliverableStageId String
|
||||
deliverableStage DeliverableStage @relation(...)
|
||||
revisionId String
|
||||
revision Revision @relation(...)
|
||||
annotationId String?
|
||||
annotation Annotation? @relation(...)
|
||||
commentId String?
|
||||
comment Comment? @relation(...)
|
||||
summary String
|
||||
severity FeedbackSeverity @default(MAJOR)
|
||||
status FeedbackStatus @default(OPEN)
|
||||
sortOrder Int @default(0)
|
||||
assignedToId String?
|
||||
createdById String
|
||||
resolvedById String?
|
||||
resolvedAt DateTime?
|
||||
resolutionNote String?
|
||||
verifiedById String?
|
||||
verifiedAt DateTime?
|
||||
carriedFromId String? // carried forward from prior round
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@map("feedback_items")
|
||||
}
|
||||
|
||||
enum FeedbackSeverity { CRITICAL MAJOR MINOR SUGGESTION }
|
||||
enum FeedbackStatus { OPEN IN_PROGRESS RESOLVED VERIFIED REOPENED }
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/components/review/feedback-checklist.tsx`
|
||||
- `src/components/review/feedback-item.tsx`
|
||||
- `src/components/review/feedback-progress-bar.tsx`
|
||||
- `src/components/my-work/feedback-summary.tsx`
|
||||
- `src/components/stages/feedback-indicator.tsx`
|
||||
- `src/lib/services/feedback-service.ts`
|
||||
- `src/hooks/use-feedback-items.ts`
|
||||
|
||||
**Dependencies:** Requires A3 + A5
|
||||
|
||||
---
|
||||
|
||||
#### A7 — Review Sessions & Playlists
|
||||
|
||||
**What:** Curate an ordered set of deliverables into a review session. Walk through them in presenter mode with per-item approve/request-changes/reject decisions. Shareable via link.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model ReviewSession {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
status ReviewSessionStatus @default(DRAFT)
|
||||
createdById String
|
||||
organizationId String
|
||||
shareToken String? @unique
|
||||
expiresAt DateTime?
|
||||
items ReviewSessionItem[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model ReviewSessionItem {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
deliverableStageId String
|
||||
revisionId String?
|
||||
sortOrder Int
|
||||
decision ReviewDecision?
|
||||
decisionNote String?
|
||||
decidedById String?
|
||||
decidedAt DateTime?
|
||||
}
|
||||
|
||||
enum ReviewSessionStatus { DRAFT IN_PROGRESS COMPLETED }
|
||||
enum ReviewDecision { APPROVED CHANGES_REQUESTED REJECTED }
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(app)/reviews/page.tsx`
|
||||
- `src/app/(app)/reviews/[sessionId]/page.tsx`
|
||||
- `src/components/review/session-builder.tsx`
|
||||
- `src/components/review/session-presenter.tsx`
|
||||
- `src/components/review/session-summary.tsx`
|
||||
- `src/lib/services/review-session-service.ts`
|
||||
|
||||
**Dependencies:** Requires A2 + A3
|
||||
|
||||
---
|
||||
|
||||
### B. Collaboration Enhancements
|
||||
|
||||
---
|
||||
|
||||
#### B1 — Rich @Mentions with Deep Linking
|
||||
|
||||
**What:** `@` trigger in comment input opens user autocomplete. Mentioned users get a notification with a direct link to the comment.
|
||||
|
||||
**Key files:**
|
||||
- `src/components/comments/mention-input.tsx`
|
||||
- `src/components/comments/mention-renderer.tsx`
|
||||
- Update `src/lib/services/comment-service.ts` — extract mentions + create notifications
|
||||
|
||||
---
|
||||
|
||||
#### B2 — Project Activity Feed
|
||||
|
||||
**What:** Unified chronological stream of all activity on a project — status changes, comments, uploads, assignments, approvals.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model ActivityEntry {
|
||||
id String @id @default(cuid())
|
||||
projectId String
|
||||
deliverableId String?
|
||||
stageId String?
|
||||
userId String
|
||||
type ActivityType
|
||||
summary String
|
||||
metadata Json?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
enum ActivityType {
|
||||
STATUS_CHANGE COMMENT_ADDED REVISION_SUBMITTED ASSIGNMENT_CHANGED
|
||||
APPROVAL_DECISION FILE_UPLOADED DEADLINE_CHANGED PRIORITY_CHANGED
|
||||
PROJECT_CREATED DELIVERABLE_CREATED
|
||||
}
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/components/activity/activity-feed.tsx`
|
||||
- `src/components/activity/activity-entry.tsx`
|
||||
- `src/lib/services/activity-service.ts`
|
||||
- `src/app/api/projects/[projectId]/activity/route.ts`
|
||||
|
||||
---
|
||||
|
||||
#### B3 — External Review Links
|
||||
|
||||
**What:** Token-based URLs for external HP stakeholders to view specific deliverables without an account. Optional watermark (reviewer name, date, CONFIDENTIAL), configurable expiry, access logging, revoke capability.
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(external)/review/[token]/page.tsx`
|
||||
- `src/components/review/watermark-overlay.tsx`
|
||||
- `src/lib/services/external-link-service.ts`
|
||||
|
||||
---
|
||||
|
||||
### C. Reporting Completions
|
||||
|
||||
---
|
||||
|
||||
#### C1 — Velocity & Throughput Metrics
|
||||
|
||||
**What:** Deliverables completed per week, average time per stage, bottleneck detection. Trend charts over 4/8/12/26-week windows.
|
||||
|
||||
**Key files:**
|
||||
- `src/components/dashboard/velocity-chart.tsx`
|
||||
- `src/components/dashboard/cycle-time-chart.tsx`
|
||||
- `src/components/dashboard/bottleneck-chart.tsx`
|
||||
- `src/lib/services/analytics-service.ts`
|
||||
|
||||
---
|
||||
|
||||
#### C2 — Burndown Charts
|
||||
|
||||
**What:** Per-project burndown with ideal line, actual line, and velocity-based projection with confidence interval. Warning when projection exceeds deadline.
|
||||
|
||||
**Key files:**
|
||||
- `src/components/dashboard/burndown-chart.tsx`
|
||||
- `src/components/dashboard/projection-engine.ts`
|
||||
|
||||
---
|
||||
|
||||
#### C3 — Client-Facing Dashboard (Read-Only Portal)
|
||||
|
||||
**What:** Simplified read-only view for HP stakeholders via secure share link. No account required. Configurable visibility, optional password + expiry.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model PortalLink {
|
||||
id String @id @default(cuid())
|
||||
token String @unique
|
||||
organizationId String
|
||||
projectIds String[]
|
||||
createdById String
|
||||
password String?
|
||||
expiresAt DateTime?
|
||||
lastAccessedAt DateTime?
|
||||
accessCount Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(portal)/[token]/page.tsx`
|
||||
- `src/app/(portal)/[token]/projects/[projectId]/page.tsx`
|
||||
- `src/components/portal/portal-header.tsx`
|
||||
- `src/lib/services/portal-service.ts`
|
||||
|
||||
**New dependency:** `bcryptjs` (password hashing for portal links)
|
||||
|
||||
---
|
||||
|
||||
#### C4 — SLA Tracking
|
||||
|
||||
**What:** Target turnaround times per stage type. Real-time on-track / at-risk / breached status. Business-hours-aware calculation. Compliance dashboard widget.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model SLATarget {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
stageType String
|
||||
targetHours Int
|
||||
warningThreshold Float @default(0.75)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(app)/settings/sla/page.tsx`
|
||||
- `src/components/dashboard/sla-compliance-chart.tsx`
|
||||
- `src/components/stages/sla-indicator.tsx`
|
||||
- `src/lib/services/sla-service.ts`
|
||||
|
||||
---
|
||||
|
||||
### D. Automation Completions
|
||||
|
||||
The automation rule engine (Phase 7.1) is fully built. These features extend it.
|
||||
|
||||
---
|
||||
|
||||
#### D1 — Automation Rules UI
|
||||
|
||||
**What:** Admin interface to create, edit, enable/disable automation rules. The engine exists — this is the management UI it's missing.
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(app)/settings/automations/page.tsx`
|
||||
- `src/components/automations/rule-builder.tsx`
|
||||
- `src/components/automations/execution-log.tsx`
|
||||
|
||||
---
|
||||
|
||||
#### D2 — Multi-Level Approval Chains
|
||||
|
||||
**What:** Approval workflows requiring sign-off from multiple stakeholders in sequence. Each step: approver role/user, required/optional, auto-advance on approve. Visual progress indicator.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model ApprovalChain {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
organizationId String
|
||||
stageType String?
|
||||
steps ApprovalStep[]
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model ApprovalStep {
|
||||
id String @id @default(cuid())
|
||||
chainId String
|
||||
stepOrder Int
|
||||
approverRole Role?
|
||||
approverUserId String?
|
||||
isRequired Boolean @default(true)
|
||||
autoAdvance Boolean @default(true)
|
||||
approvalRecords ApprovalRecord[]
|
||||
}
|
||||
|
||||
model ApprovalRecord {
|
||||
id String @id @default(cuid())
|
||||
deliverableStageId String
|
||||
stepId String
|
||||
decision ReviewDecision
|
||||
note String?
|
||||
decidedById String
|
||||
decidedAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(app)/settings/approvals/page.tsx`
|
||||
- `src/components/approvals/chain-builder.tsx`
|
||||
- `src/components/approvals/approval-progress.tsx`
|
||||
- `src/lib/services/approval-service.ts`
|
||||
|
||||
---
|
||||
|
||||
#### D3 — Project Templates
|
||||
|
||||
**What:** Save a full project configuration (deliverables, stage settings, default assignments) as a reusable template. One-click project creation for repeat HP SKU types.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model ProjectTemplate {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
description String?
|
||||
organizationId String
|
||||
createdById String
|
||||
isShared Boolean @default(true)
|
||||
configuration Json
|
||||
deliverables ProjectTemplateDeliverable[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model ProjectTemplateDeliverable {
|
||||
id String @id @default(cuid())
|
||||
templateId String
|
||||
name String
|
||||
type String?
|
||||
priority Priority @default(MEDIUM)
|
||||
defaultAssignments Json?
|
||||
sortOrder Int
|
||||
}
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(app)/templates/page.tsx`
|
||||
- `src/components/templates/template-card.tsx`
|
||||
- `src/components/templates/template-builder.tsx`
|
||||
- `src/lib/services/template-service.ts`
|
||||
|
||||
---
|
||||
|
||||
### E. Asset Intelligence
|
||||
|
||||
---
|
||||
|
||||
#### E1 — File Validation on Upload
|
||||
|
||||
**What:** Automatically validate uploaded files against spec requirements (resolution, color space, format, file size, aspect ratio). Reject non-conforming files with clear error messages. Override option for producers.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model AssetSpec {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
stageType String
|
||||
name String
|
||||
rules Json // { minWidth, minHeight, maxFileSize, allowedFormats[], colorSpace, dpi }
|
||||
isActive Boolean @default(true)
|
||||
validationResults AssetValidationResult[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model AssetValidationResult {
|
||||
id String @id @default(cuid())
|
||||
revisionId String
|
||||
specId String
|
||||
passed Boolean
|
||||
results Json // [{ check, expected, actual, passed }]
|
||||
overrideById String?
|
||||
overrideReason String?
|
||||
validatedAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(app)/settings/asset-specs/page.tsx`
|
||||
- `src/components/upload/file-validator.tsx`
|
||||
- `src/lib/services/asset-validation-service.ts`
|
||||
|
||||
**New dependency:** `sharp` (already needed for A1 PNG compositing)
|
||||
|
||||
---
|
||||
|
||||
#### E2 — Thumbnail & Preview Generation
|
||||
|
||||
**What:** Auto-generate web-optimized thumbnails (200px), previews (1200px), and full copies from uploaded high-res assets. Background processing queue.
|
||||
|
||||
**Key files:**
|
||||
- `src/lib/services/preview-service.ts`
|
||||
- `src/lib/jobs/generate-previews.ts`
|
||||
- `src/components/common/optimized-image.tsx`
|
||||
|
||||
---
|
||||
|
||||
#### E3 — AI Review Engine Integration Point
|
||||
|
||||
**What:** Webhook endpoint for an external AI Review Engine to post structured quality analysis results. AI-flagged regions rendered as dashed-border annotations in the viewer. Configuration per stage type.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model AIReviewResult {
|
||||
id String @id @default(cuid())
|
||||
revisionId String
|
||||
overallScore Float
|
||||
passed Boolean
|
||||
checks Json
|
||||
flaggedRegions Json
|
||||
engineVersion String
|
||||
processingTimeMs Int
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/app/api/webhooks/ai-review/route.ts`
|
||||
- `src/components/review/ai-review-overlay.tsx`
|
||||
- `src/components/review/ai-review-summary.tsx`
|
||||
- `src/lib/services/ai-review-service.ts`
|
||||
|
||||
---
|
||||
|
||||
### F. Quality of Life
|
||||
|
||||
---
|
||||
|
||||
#### F1 — Saved Filters & Custom Views
|
||||
|
||||
**What:** Save current filter/sort/column config as a named view. Personal and shared views. URL-encodable for link sharing.
|
||||
|
||||
**New data model:**
|
||||
```prisma
|
||||
model SavedView {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
userId String
|
||||
organizationId String
|
||||
projectId String?
|
||||
viewType ViewType
|
||||
configuration Json
|
||||
isShared Boolean @default(false)
|
||||
isPinned Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
enum ViewType { TABLE BOARD TIMELINE }
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `src/components/views/saved-view-picker.tsx`
|
||||
- `src/components/views/save-view-dialog.tsx`
|
||||
- `src/lib/services/saved-view-service.ts`
|
||||
|
||||
---
|
||||
|
||||
#### F2 — Skill-Based Assignment UI
|
||||
|
||||
**What:** The Skill / UserSkill / StageSkillRequirement data models already exist. This adds the UI: skill tags on user profiles, skill requirements on stage templates, and best-fit artist suggestions in the assignment dialog (sorted by skill match + lowest current load).
|
||||
|
||||
**Key files:**
|
||||
- `src/app/(app)/settings/skills/page.tsx`
|
||||
- `src/components/assignments/skill-match-suggestions.tsx`
|
||||
- `src/lib/services/skill-service.ts` — matching algorithm
|
||||
|
||||
---
|
||||
|
||||
#### F3 — Batch Upload with Auto-Matching
|
||||
|
||||
**What:** Drop multiple files onto a project; auto-match to deliverables by file naming convention (configurable regex). Preview table shows match confidence, manual override available.
|
||||
|
||||
**Key files:**
|
||||
- `src/components/upload/batch-upload-zone.tsx`
|
||||
- `src/components/upload/file-matcher.tsx`
|
||||
- `src/lib/services/file-matching-service.ts`
|
||||
|
||||
---
|
||||
|
||||
#### F4 — Extended Command Palette Actions
|
||||
|
||||
**What:** Add quick-action commands to the existing Cmd+K palette: "approve and advance," "assign to me," "mark blocked," "start review session." Context-aware based on current page.
|
||||
|
||||
**Key files:**
|
||||
- Update `src/components/layout/command-palette.tsx`
|
||||
- `src/lib/commands/action-registry.ts`
|
||||
|
||||
---
|
||||
|
||||
### G. Docker Deployment
|
||||
|
||||
---
|
||||
|
||||
#### G1 — Docker Compose Stack
|
||||
|
||||
**What:** `docker-compose.yml` with three services — Next.js app, PostgreSQL + pgvector, Ollama with pre-configured models. One `docker compose up` starts everything.
|
||||
|
||||
Note: `Dockerfile` and `docker-compose.yml` already exist in the repo root — review and complete as needed.
|
||||
|
||||
**Services:**
|
||||
|
||||
| Service | Image | Purpose |
|
||||
|---|---|---|
|
||||
| `app` | Custom Dockerfile | Next.js production build |
|
||||
| `db` | `pgvector/pgvector:pg17` | PostgreSQL with pgvector |
|
||||
| `ollama` | `ollama/ollama:latest` | Local AI (nomic-embed-text + qwen3.5:9b) |
|
||||
|
||||
**Key files:**
|
||||
- `Dockerfile` — multi-stage Next.js build (review existing)
|
||||
- `docker-compose.yml` — full stack (review existing)
|
||||
- `docker/ollama-entrypoint.sh` — model bootstrap script
|
||||
- `docker/db-init.sql` — `CREATE EXTENSION IF NOT EXISTS vector;`
|
||||
- `.env.example` — environment template
|
||||
|
||||
---
|
||||
|
||||
#### G2 — Health Checks & Startup Orchestration
|
||||
|
||||
**What:** `pg_isready` health check on `db`, Ollama API health check, `prisma migrate deploy` runs on app startup before `next start`. `depends_on: condition: service_healthy` ensures correct start order.
|
||||
|
||||
---
|
||||
|
||||
#### G3 — Dev Environment Override
|
||||
|
||||
**What:** `docker-compose.dev.yml` that mounts source code and runs `next dev` for hot reloading, while keeping database and Ollama in containers.
|
||||
|
||||
**Key files:**
|
||||
- `docker-compose.dev.yml`
|
||||
|
||||
---
|
||||
|
||||
## Data Model Status
|
||||
|
||||
### Models Currently in Schema
|
||||
|
||||
| Model | Status |
|
||||
|---|---|
|
||||
| Organization, User, Account, Session | ✅ |
|
||||
| PipelineStageTemplate, PipelineStageDependency | ✅ |
|
||||
| Project, Deliverable, DeliverableStage | ✅ (with pgvector embedding columns) |
|
||||
| StageAssignment, Revision, Comment | ✅ |
|
||||
| Notification | ✅ |
|
||||
| AutomationRule, AutomationExecution | ✅ |
|
||||
| Skill, UserSkill, StageSkillRequirement | ✅ |
|
||||
| SearchLog | ✅ |
|
||||
| ChatMessage | ✅ |
|
||||
|
||||
### Models Needed (not yet in schema)
|
||||
|
||||
| Model | Feature |
|
||||
|---|---|
|
||||
| Annotation, FeedbackItem | A3, A6 |
|
||||
| ReviewSession, ReviewSessionItem | A7 |
|
||||
| ApprovalChain, ApprovalStep, ApprovalRecord | D2 |
|
||||
| ProjectTemplate, ProjectTemplateDeliverable | D3 |
|
||||
| AssetSpec, AssetValidationResult | E1 |
|
||||
| AIReviewResult | E3 |
|
||||
| PortalLink | C3 |
|
||||
| SLATarget | C4 |
|
||||
| ActivityEntry | B2 |
|
||||
| SavedView | F1 |
|
||||
|
||||
---
|
||||
|
||||
## Architecture Reference
|
||||
|
||||
```
|
||||
src/
|
||||
├── app/
|
||||
│ ├── (auth)/login/ # SSO login
|
||||
│ ├── (app)/ # Authenticated routes
|
||||
│ │ ├── dashboard/
|
||||
│ │ ├── projects/[projectId]/
|
||||
│ │ │ ├── table/ board/ timeline/
|
||||
│ │ │ └── deliverables/[deliverableId]/
|
||||
│ │ ├── my-work/
|
||||
│ │ ├── workload/ # ✅ Capacity grid + heatmap
|
||||
│ │ ├── calendar/ # ✅ Calendar view
|
||||
│ │ ├── reports/weekly/ # ✅ Weekly executive report
|
||||
│ │ ├── reviews/ # A7 Review sessions
|
||||
│ │ ├── templates/ # D3 Project templates
|
||||
│ │ └── settings/
|
||||
│ ├── (portal)/[token]/ # C3 Client portal (external)
|
||||
│ ├── (external)/review/ # B3 External review links
|
||||
│ └── api/
|
||||
├── components/
|
||||
│ ├── ui/ # shadcn/ui primitives
|
||||
│ ├── layout/ # Sidebar, topbar, command palette
|
||||
│ ├── views/ # Table, Board, Timeline, Dashboard
|
||||
│ ├── workload/ # ✅ Capacity grid + heatmap components
|
||||
│ ├── calendar/ # ✅ Calendar components
|
||||
│ ├── reports/weekly/ # ✅ Weekly report components
|
||||
│ ├── revisions/ # A1 Image comparison (to build)
|
||||
│ ├── review/ # A2-A7 Full review viewer (to build)
|
||||
│ ├── automations/ # D1 Automation UI (to build)
|
||||
│ └── search/ # ✅ Smart search panel
|
||||
├── lib/
|
||||
│ ├── pipeline/ # ✅ Dependency engine + stage machine
|
||||
│ ├── automation/ # ✅ Event bus + rule engine + executor
|
||||
│ ├── services/ # Business logic per entity
|
||||
│ └── validators/ # Zod schemas
|
||||
├── hooks/ # TanStack Query hooks
|
||||
└── stores/ # Zustand (UI state, filters)
|
||||
```
|
||||
|
||||
### Key Patterns
|
||||
- **Thin API routes** → delegate to `lib/services/` for all business logic
|
||||
- **Service layer** → Prisma queries + business rules (testable, reusable)
|
||||
- **URL-synced filters** via `nuqs` — views are shareable/bookmarkable
|
||||
- **Server Components** for initial fetch, **TanStack Query** for mutations/cache
|
||||
- **`npx prisma db push`** for schema changes (no migrations dir — use db push)
|
||||
|
||||
### Local Dev
|
||||
```bash
|
||||
# Start DB
|
||||
brew services start postgresql@17
|
||||
|
||||
# Start app (must source nvm)
|
||||
export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && npm run dev
|
||||
```
|
||||
|
||||
### Third-Party Libraries Needed for Remaining Work
|
||||
|
||||
| Library | Purpose | Feature |
|
||||
|---|---|---|
|
||||
| `sharp` | PNG alpha compositing + image validation + thumbnail generation | A1, E1, E2 |
|
||||
| `bcryptjs` | Password hashing for portal links | C3 |
|
||||
| `@react-pdf/renderer` | PDF export for weekly report download button | C — weekly report enhancement |
|
||||
|
||||
---
|
||||
|
||||
*Document version: 1.0 — Created 2026-03-14*
|
||||
*To be updated as features are built and priorities shift.*
|
||||
Loading…
Add table
Reference in a new issue