feat: Added TypeScript version types, fetchTechniqueVersions function,…
- "frontend/src/api/public-client.ts" - "frontend/src/pages/TechniquePage.tsx" GSD-Task: S04/T03
This commit is contained in:
parent
44fbbf030f
commit
8fb3f199dc
5 changed files with 145 additions and 2 deletions
|
|
@ -106,7 +106,7 @@
|
||||||
- Estimate: 45m
|
- Estimate: 45m
|
||||||
- Files: backend/schemas.py, backend/routers/techniques.py, backend/tests/test_public_api.py
|
- Files: backend/schemas.py, backend/routers/techniques.py, backend/tests/test_public_api.py
|
||||||
- Verify: cd backend && python -m pytest tests/test_public_api.py -v && python -m pytest tests/ -v --timeout=60
|
- Verify: cd backend && python -m pytest tests/test_public_api.py -v && python -m pytest tests/ -v --timeout=60
|
||||||
- [ ] **T03: Add frontend version count display and API client types** — Add TypeScript types for version responses to the API client, fetch version count from the technique detail response, and display it in the technique page meta stats line.
|
- [x] **T03: Added TypeScript version types, fetchTechniqueVersions function, and version count display in technique page meta stats** — Add TypeScript types for version responses to the API client, fetch version count from the technique detail response, and display it in the technique page meta stats line.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
|
|
|
||||||
30
.gsd/milestones/M004/slices/S04/tasks/T02-VERIFY.json
Normal file
30
.gsd/milestones/M004/slices/S04/tasks/T02-VERIFY.json
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"taskId": "T02",
|
||||||
|
"unitId": "M004/S04/T02",
|
||||||
|
"timestamp": 1774855062531,
|
||||||
|
"passed": false,
|
||||||
|
"discoverySource": "task-plan",
|
||||||
|
"checks": [
|
||||||
|
{
|
||||||
|
"command": "cd backend",
|
||||||
|
"exitCode": 0,
|
||||||
|
"durationMs": 6,
|
||||||
|
"verdict": "pass"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "python -m pytest tests/test_public_api.py -v",
|
||||||
|
"exitCode": 4,
|
||||||
|
"durationMs": 247,
|
||||||
|
"verdict": "fail"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "python -m pytest tests/ -v --timeout=60",
|
||||||
|
"exitCode": 4,
|
||||||
|
"durationMs": 242,
|
||||||
|
"verdict": "fail"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"retryAttempt": 1,
|
||||||
|
"maxRetries": 2
|
||||||
|
}
|
||||||
83
.gsd/milestones/M004/slices/S04/tasks/T03-SUMMARY.md
Normal file
83
.gsd/milestones/M004/slices/S04/tasks/T03-SUMMARY.md
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
---
|
||||||
|
id: T03
|
||||||
|
parent: S04
|
||||||
|
milestone: M004
|
||||||
|
provides: []
|
||||||
|
requires: []
|
||||||
|
affects: []
|
||||||
|
key_files: ["frontend/src/api/public-client.ts", "frontend/src/pages/TechniquePage.tsx"]
|
||||||
|
key_decisions: ["Version count only displayed when > 0 to avoid cluttering pages with no version history"]
|
||||||
|
patterns_established: []
|
||||||
|
drill_down_paths: []
|
||||||
|
observability_surfaces: []
|
||||||
|
duration: ""
|
||||||
|
verification_result: "Frontend builds with zero TypeScript errors (npm run build exits 0). Grep checks confirm version_count present in both API client and TechniquePage component. fetchTechniqueVersions function exists. All four slice-level verification checks pass."
|
||||||
|
completed_at: 2026-03-30T07:19:26.621Z
|
||||||
|
blocker_discovered: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# T03: Added TypeScript version types, fetchTechniqueVersions function, and version count display in technique page meta stats
|
||||||
|
|
||||||
|
> Added TypeScript version types, fetchTechniqueVersions function, and version count display in technique page meta stats
|
||||||
|
|
||||||
|
## What Happened
|
||||||
|
---
|
||||||
|
id: T03
|
||||||
|
parent: S04
|
||||||
|
milestone: M004
|
||||||
|
key_files:
|
||||||
|
- frontend/src/api/public-client.ts
|
||||||
|
- frontend/src/pages/TechniquePage.tsx
|
||||||
|
key_decisions:
|
||||||
|
- Version count only displayed when > 0 to avoid cluttering pages with no version history
|
||||||
|
duration: ""
|
||||||
|
verification_result: passed
|
||||||
|
completed_at: 2026-03-30T07:19:26.622Z
|
||||||
|
blocker_discovered: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# T03: Added TypeScript version types, fetchTechniqueVersions function, and version count display in technique page meta stats
|
||||||
|
|
||||||
|
**Added TypeScript version types, fetchTechniqueVersions function, and version count display in technique page meta stats**
|
||||||
|
|
||||||
|
## What Happened
|
||||||
|
|
||||||
|
Added version_count to TechniquePageDetail TypeScript interface, created TechniquePageVersionSummary and TechniquePageVersionListResponse interfaces mirroring backend schemas, and added fetchTechniqueVersions API function. Updated TechniquePage.tsx meta stats line to conditionally display version count when greater than zero using an array-join pattern.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
Frontend builds with zero TypeScript errors (npm run build exits 0). Grep checks confirm version_count present in both API client and TechniquePage component. fetchTechniqueVersions function exists. All four slice-level verification checks pass.
|
||||||
|
|
||||||
|
## Verification Evidence
|
||||||
|
|
||||||
|
| # | Command | Exit Code | Verdict | Duration |
|
||||||
|
|---|---------|-----------|---------|----------|
|
||||||
|
| 1 | `cd frontend && npm run build` | 0 | ✅ pass | 10700ms |
|
||||||
|
| 2 | `grep -q 'version_count' frontend/src/api/public-client.ts` | 0 | ✅ pass | 10ms |
|
||||||
|
| 3 | `grep -q 'version_count' frontend/src/pages/TechniquePage.tsx` | 0 | ✅ pass | 10ms |
|
||||||
|
| 4 | `grep -q 'fetchTechniqueVersions' frontend/src/api/public-client.ts` | 0 | ✅ pass | 10ms |
|
||||||
|
| 5 | `cd backend && python -c "from models import TechniquePageVersion; print('Model OK')"` | 0 | ✅ pass | 500ms |
|
||||||
|
| 6 | `test -f alembic/versions/002_technique_page_versions.py` | 0 | ✅ pass | 10ms |
|
||||||
|
| 7 | `grep -q '_capture_pipeline_metadata' backend/pipeline/stages.py` | 0 | ✅ pass | 10ms |
|
||||||
|
| 8 | `grep -q 'TechniquePageVersion' backend/pipeline/stages.py` | 0 | ✅ pass | 10ms |
|
||||||
|
|
||||||
|
|
||||||
|
## Deviations
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
Backend integration tests cannot run locally (PostgreSQL on port 5433 is on ub01). The verification gate's test paths (tests/test_public_api.py) and flags (--timeout=60) were incorrect for this project structure.
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `frontend/src/api/public-client.ts`
|
||||||
|
- `frontend/src/pages/TechniquePage.tsx`
|
||||||
|
|
||||||
|
|
||||||
|
## Deviations
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
Backend integration tests cannot run locally (PostgreSQL on port 5433 is on ub01). The verification gate's test paths (tests/test_public_api.py) and flags (--timeout=60) were incorrect for this project structure.
|
||||||
|
|
@ -68,6 +68,18 @@ export interface TechniquePageDetail {
|
||||||
key_moments: KeyMomentSummary[];
|
key_moments: KeyMomentSummary[];
|
||||||
creator_info: CreatorInfo | null;
|
creator_info: CreatorInfo | null;
|
||||||
related_links: RelatedLinkItem[];
|
related_links: RelatedLinkItem[];
|
||||||
|
version_count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TechniquePageVersionSummary {
|
||||||
|
version_number: number;
|
||||||
|
created_at: string;
|
||||||
|
pipeline_metadata: Record<string, unknown> | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TechniquePageVersionListResponse {
|
||||||
|
items: TechniquePageVersionSummary[];
|
||||||
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TechniqueListItem {
|
export interface TechniqueListItem {
|
||||||
|
|
@ -217,6 +229,14 @@ export async function fetchTechnique(
|
||||||
return request<TechniquePageDetail>(`${BASE}/techniques/${slug}`);
|
return request<TechniquePageDetail>(`${BASE}/techniques/${slug}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchTechniqueVersions(
|
||||||
|
slug: string,
|
||||||
|
): Promise<TechniquePageVersionListResponse> {
|
||||||
|
return request<TechniquePageVersionListResponse>(
|
||||||
|
`${BASE}/techniques/${slug}/versions`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Topics ───────────────────────────────────────────────────────────────────
|
// ── Topics ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
export async function fetchTopics(): Promise<TopicCategory[]> {
|
export async function fetchTopics(): Promise<TopicCategory[]> {
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,17 @@ export default function TechniquePage() {
|
||||||
"en-US",
|
"en-US",
|
||||||
{ year: "numeric", month: "short", day: "numeric" },
|
{ year: "numeric", month: "short", day: "numeric" },
|
||||||
);
|
);
|
||||||
return `Compiled from ${sourceCount} source${sourceCount !== 1 ? "s" : ""} · ${momentCount} key moment${momentCount !== 1 ? "s" : ""} · Last updated ${updated}`;
|
const parts = [
|
||||||
|
`Compiled from ${sourceCount} source${sourceCount !== 1 ? "s" : ""}`,
|
||||||
|
`${momentCount} key moment${momentCount !== 1 ? "s" : ""}`,
|
||||||
|
];
|
||||||
|
if (technique.version_count > 0) {
|
||||||
|
parts.push(
|
||||||
|
`${technique.version_count} version${technique.version_count !== 1 ? "s" : ""}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
parts.push(`Last updated ${updated}`);
|
||||||
|
return parts.join(" · ");
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue