Skip to content

Commit 98cb441

Browse files
KevenWMarkhamclaude
andcommitted
feat(ui): add version tracking and on-screen version badge
- Enhance src/version.ts with comprehensive version info - APP_VERSION, BUILD_INFO, FEATURES exports - getFullVersion() and getVersionInfo() helpers - logVersionBanner() for console output - Create VersionBadge component in UI package - Fixed position bottom-right display - Expandable details panel showing build info - Environment-aware color coding - Add version badge to App.tsx - Displays version in bottom-right corner - Click to expand for full build details - Update NAMING_CONVENTIONS.md with versioning standards - Semantic versioning format - Version update process - Release tag format - Bump version to 1.1.0 Sprint: epic-01/sprint-01 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 5666666 commit 98cb441

File tree

6 files changed

+528
-103
lines changed

6 files changed

+528
-103
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "transcript-parser",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "React TypeScript application",
55
"main": "electron/main.cjs",
66
"type": "module",
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { useState } from 'react'
2+
import { Info } from 'lucide-react'
3+
4+
export interface VersionInfo {
5+
version: string
6+
fullVersion: string
7+
build: {
8+
date: string
9+
time: string
10+
environment: string
11+
branch: string
12+
commit: string
13+
}
14+
features?: Record<string, boolean | string>
15+
}
16+
17+
interface VersionBadgeProps {
18+
versionInfo: VersionInfo
19+
position?: 'bottom-right' | 'bottom-left' | 'inline'
20+
showDetails?: boolean
21+
}
22+
23+
export function VersionBadge({
24+
versionInfo,
25+
position = 'bottom-right',
26+
showDetails = false,
27+
}: VersionBadgeProps) {
28+
const [isExpanded, setIsExpanded] = useState(false)
29+
30+
const positionClasses = {
31+
'bottom-right': 'fixed bottom-4 right-4 z-50',
32+
'bottom-left': 'fixed bottom-4 left-4 z-50',
33+
inline: 'relative',
34+
}
35+
36+
const envColors: Record<string, string> = {
37+
production: 'bg-emerald-500',
38+
development: 'bg-amber-500',
39+
staging: 'bg-blue-500',
40+
test: 'bg-purple-500',
41+
}
42+
43+
const envColor = envColors[versionInfo.build.environment] || 'bg-slate-500'
44+
45+
return (
46+
<div className={positionClasses[position]}>
47+
{/* Collapsed Badge */}
48+
<button
49+
onClick={() => setIsExpanded(!isExpanded)}
50+
className={`
51+
flex items-center gap-2 px-3 py-1.5 rounded-full
52+
bg-slate-800/90 backdrop-blur-sm text-white text-xs font-medium
53+
shadow-lg hover:bg-slate-700/90 transition-all
54+
border border-slate-700/50
55+
`}
56+
title="Click for version details"
57+
>
58+
<span className={`w-2 h-2 rounded-full ${envColor}`} />
59+
<span>{versionInfo.fullVersion}</span>
60+
{showDetails && <Info className="w-3 h-3 opacity-60" />}
61+
</button>
62+
63+
{/* Expanded Details Panel */}
64+
{isExpanded && showDetails && (
65+
<div
66+
className={`
67+
absolute ${position === 'bottom-left' ? 'left-0' : 'right-0'} bottom-full mb-2
68+
bg-slate-800/95 backdrop-blur-sm rounded-lg shadow-xl
69+
border border-slate-700/50 p-4 min-w-[280px]
70+
text-white text-xs
71+
`}
72+
>
73+
<div className="flex items-center justify-between mb-3">
74+
<h4 className="font-semibold text-sm">Version Info</h4>
75+
<button
76+
onClick={() => setIsExpanded(false)}
77+
className="text-slate-400 hover:text-white"
78+
>
79+
80+
</button>
81+
</div>
82+
83+
<div className="space-y-2">
84+
<div className="flex justify-between">
85+
<span className="text-slate-400">Version:</span>
86+
<span className="font-mono">{versionInfo.version}</span>
87+
</div>
88+
<div className="flex justify-between">
89+
<span className="text-slate-400">Environment:</span>
90+
<span className={`px-2 py-0.5 rounded ${envColor}`}>
91+
{versionInfo.build.environment}
92+
</span>
93+
</div>
94+
<div className="flex justify-between">
95+
<span className="text-slate-400">Build Date:</span>
96+
<span className="font-mono">{versionInfo.build.date}</span>
97+
</div>
98+
<div className="flex justify-between">
99+
<span className="text-slate-400">Branch:</span>
100+
<span className="font-mono">{versionInfo.build.branch}</span>
101+
</div>
102+
{versionInfo.build.commit !== 'local' && (
103+
<div className="flex justify-between">
104+
<span className="text-slate-400">Commit:</span>
105+
<span className="font-mono">{versionInfo.build.commit}</span>
106+
</div>
107+
)}
108+
</div>
109+
110+
{versionInfo.features &&
111+
Object.keys(versionInfo.features).length > 0 && (
112+
<>
113+
<div className="border-t border-slate-700 my-3" />
114+
<h5 className="text-slate-400 mb-2">Features</h5>
115+
<div className="space-y-1">
116+
{Object.entries(versionInfo.features).map(([key, value]) => (
117+
<div key={key} className="flex justify-between">
118+
<span className="text-slate-400">{key}:</span>
119+
<span>
120+
{typeof value === 'boolean' ? (
121+
value ? (
122+
<span className="text-emerald-400"></span>
123+
) : (
124+
<span className="text-red-400"></span>
125+
)
126+
) : (
127+
<span className="font-mono">{value}</span>
128+
)}
129+
</span>
130+
</div>
131+
))}
132+
</div>
133+
</>
134+
)}
135+
136+
<div className="border-t border-slate-700 mt-3 pt-3 text-center text-slate-500">
137+
SmartHaven AI Platform
138+
</div>
139+
</div>
140+
)}
141+
</div>
142+
)
143+
}

packages/ui/src/index.ts

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,81 @@
11
// shadcn/ui components
2-
export { Badge } from './components/ui/badge';
3-
export { Button } from './components/ui/button';
4-
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } from './components/ui/card';
5-
export { Checkbox } from './components/ui/checkbox';
6-
export { Dialog, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription } from './components/ui/dialog';
7-
export { Input } from './components/ui/input';
8-
export { Progress } from './components/ui/progress';
9-
export { Skeleton } from './components/ui/skeleton';
10-
export { Slider } from './components/ui/slider';
11-
export { Textarea } from './components/ui/textarea';
12-
export { ToastProvider, useToast } from './components/ui/toast';
2+
export { Badge } from './components/ui/badge'
3+
export { Button } from './components/ui/button'
4+
export {
5+
Card,
6+
CardHeader,
7+
CardFooter,
8+
CardTitle,
9+
CardDescription,
10+
CardContent,
11+
} from './components/ui/card'
12+
export { Checkbox } from './components/ui/checkbox'
13+
export {
14+
Dialog,
15+
DialogPortal,
16+
DialogOverlay,
17+
DialogTrigger,
18+
DialogClose,
19+
DialogContent,
20+
DialogHeader,
21+
DialogFooter,
22+
DialogTitle,
23+
DialogDescription,
24+
} from './components/ui/dialog'
25+
export { Input } from './components/ui/input'
26+
export { Progress } from './components/ui/progress'
27+
export { Skeleton } from './components/ui/skeleton'
28+
export { Slider } from './components/ui/slider'
29+
export { Textarea } from './components/ui/textarea'
30+
export { ToastProvider, useToast } from './components/ui/toast'
1331

1432
// Main components
15-
export { AdvancedExportPanel } from './components/AdvancedExportPanel';
16-
export { ApiKeySettings, loadApiConfig, getCurrentApiKey, type ApiKeyConfig } from './components/ApiKeySettings';
17-
export { BalanceAlert, shouldShowBalanceAlert } from './components/BalanceAlert';
18-
export { CostSummaryModal } from './components/CostSummaryModal';
19-
export { ExportDialog } from './components/ExportDialog';
20-
export { Header } from './components/Header';
21-
export { KeyboardShortcuts } from './components/KeyboardShortcuts';
22-
export { Login } from './components/Login';
23-
export { PaymentModal } from './components/PaymentModal';
24-
export { ProcessingStatus } from './components/ProcessingStatus';
25-
export { Register } from './components/Register';
26-
export { SpeakerAnalytics } from './components/SpeakerAnalytics';
27-
export { SpeakerNameSuggestions } from './components/SpeakerNameSuggestions';
28-
export { SpeakerSummary } from './components/SpeakerSummary';
29-
export { TranscriptEntry } from './components/TranscriptEntry';
30-
export { TranscriptEntrySkeleton } from './components/TranscriptEntrySkeleton';
31-
export { TranscriptFilters, type TranscriptFilterOptions } from './components/TranscriptFilters';
32-
export { TranscriptLibrary } from './components/TranscriptLibrary';
33-
export { TranscriptList } from './components/TranscriptList';
34-
export { TranscriptListSkeleton } from './components/TranscriptListSkeleton';
35-
export { TranscriptSearch } from './components/TranscriptSearch';
36-
export { TranscriptView } from './components/TranscriptView';
37-
export { UploadVideo } from './components/UploadVideo';
38-
export { UsageStats } from './components/UsageStats';
39-
export { VideoPlayerModal } from './components/VideoPlayerModal';
40-
export { VideoPreview } from './components/VideoPreview';
33+
export { AdvancedExportPanel } from './components/AdvancedExportPanel'
34+
export {
35+
ApiKeySettings,
36+
loadApiConfig,
37+
getCurrentApiKey,
38+
type ApiKeyConfig,
39+
} from './components/ApiKeySettings'
40+
export { BalanceAlert, shouldShowBalanceAlert } from './components/BalanceAlert'
41+
export { CostSummaryModal } from './components/CostSummaryModal'
42+
export { ExportDialog } from './components/ExportDialog'
43+
export { Header } from './components/Header'
44+
export { KeyboardShortcuts } from './components/KeyboardShortcuts'
45+
export { Login } from './components/Login'
46+
export { PaymentModal } from './components/PaymentModal'
47+
export { ProcessingStatus } from './components/ProcessingStatus'
48+
export { Register } from './components/Register'
49+
export { SpeakerAnalytics } from './components/SpeakerAnalytics'
50+
export { SpeakerNameSuggestions } from './components/SpeakerNameSuggestions'
51+
export { SpeakerSummary } from './components/SpeakerSummary'
52+
export { TranscriptEntry } from './components/TranscriptEntry'
53+
export { TranscriptEntrySkeleton } from './components/TranscriptEntrySkeleton'
54+
export {
55+
TranscriptFilters,
56+
type TranscriptFilterOptions,
57+
} from './components/TranscriptFilters'
58+
export { TranscriptLibrary } from './components/TranscriptLibrary'
59+
export { TranscriptList } from './components/TranscriptList'
60+
export { TranscriptListSkeleton } from './components/TranscriptListSkeleton'
61+
export { TranscriptSearch } from './components/TranscriptSearch'
62+
export { TranscriptView } from './components/TranscriptView'
63+
export { UploadVideo } from './components/UploadVideo'
64+
export { UsageStats } from './components/UsageStats'
65+
export { VersionBadge, type VersionInfo } from './components/VersionBadge'
66+
export { VideoPlayerModal } from './components/VideoPlayerModal'
67+
export { VideoPreview } from './components/VideoPreview'
4168

4269
// Hooks
43-
export { useDebounce } from './hooks/useDebounce';
44-
export { useEditHistory } from './hooks/useEditHistory';
45-
export { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
46-
export { useStreamingTranscript } from './hooks/useStreamingTranscript';
47-
export { useTranscription, type ProcessingState } from './hooks/useTranscription';
70+
export { useDebounce } from './hooks/useDebounce'
71+
export { useEditHistory } from './hooks/useEditHistory'
72+
export { useKeyboardNavigation } from './hooks/useKeyboardNavigation'
73+
export { useStreamingTranscript } from './hooks/useStreamingTranscript'
74+
export {
75+
useTranscription,
76+
getDebugMessage,
77+
type ProcessingState,
78+
} from './hooks/useTranscription'
4879

4980
// Utilities
50-
export { cn } from './lib/utils';
81+
export { cn } from './lib/utils'

specs/NAMING_CONVENTIONS.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,67 @@ services:
406406

407407
---
408408

409+
## Versioning
410+
411+
### Semantic Versioning
412+
413+
All applications follow Semantic Versioning (SemVer):
414+
415+
```
416+
MAJOR.MINOR.PATCH[-label]
417+
```
418+
419+
| Component | When to Increment | Example |
420+
| --------- | ---------------------------------- | ------------------------- |
421+
| **MAJOR** | Breaking changes | `2.0.0` |
422+
| **MINOR** | New features (backward compatible) | `1.1.0` |
423+
| **PATCH** | Bug fixes | `1.0.1` |
424+
| **label** | Pre-release or environment | `1.0.0-beta`, `1.0.0-vps` |
425+
426+
### Version File Location
427+
428+
```
429+
src/version.ts # Single source of truth
430+
package.json # Keep in sync with version.ts
431+
```
432+
433+
### Version Display Requirements
434+
435+
- **On-Screen**: Version badge visible in bottom-right corner
436+
- **Console**: Version banner logged on app start
437+
- **Deployments**: Version included in deployment archives
438+
- **API**: Version exposed via `/api/v1/health` endpoint
439+
440+
### Version Update Process
441+
442+
1. Update `APP_VERSION` in `src/version.ts`
443+
2. Update `version` in `package.json`
444+
3. Update `BUILD_INFO.date` to current date
445+
4. Commit with message: `chore(release): bump version to X.Y.Z`
446+
5. Tag release: `git tag vX.Y.Z`
447+
448+
### Build Information
449+
450+
```typescript
451+
BUILD_INFO = {
452+
date: '2024-12-23', // Build date
453+
environment: 'production', // production | development | staging
454+
branch: 'master', // Git branch
455+
commit: 'abc1234', // Git commit short SHA
456+
}
457+
```
458+
459+
### Release Tags
460+
461+
```bash
462+
# Format: vMAJOR.MINOR.PATCH
463+
git tag v1.0.0
464+
git tag v1.1.0-beta.1
465+
git tag v2.0.0-rc.1
466+
```
467+
468+
---
469+
409470
## Summary Checklist
410471

411472
- [ ] Epic folders: `epic-XX-kebab-case/`
@@ -419,6 +480,8 @@ services:
419480
- [ ] Constants: `SCREAMING_SNAKE_CASE`
420481
- [ ] Tables: `snake_case`
421482
- [ ] API endpoints: `/api/v1/kebab-case`
483+
- [ ] Version format: `MAJOR.MINOR.PATCH[-label]`
484+
- [ ] Version badge visible on screen
422485

423486
---
424487

0 commit comments

Comments
 (0)