feat(admin): Show version info at top of sidebar

- Add package.json version to /api/version endpoint
- Move version display from footer to top (next to logo)
- Show format: v1.5.1 (abc1234) - 12/9/2024

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Kelly
2025-12-09 13:58:36 -07:00
parent 75315ed91e
commit 7f65598332
2 changed files with 24 additions and 10 deletions

View File

@@ -1,7 +1,18 @@
import { Router, Request, Response } from 'express';
import { readFileSync } from 'fs';
import { join } from 'path';
const router = Router();
// Read package.json version at startup
let packageVersion = 'unknown';
try {
const packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
packageVersion = packageJson.version || 'unknown';
} catch {
// Fallback if package.json not found
}
/**
* GET /api/version
* Returns build version information for display in admin UI
@@ -10,10 +21,11 @@ router.get('/', async (req: Request, res: Response) => {
try {
const gitSha = process.env.APP_GIT_SHA || 'unknown';
const versionInfo = {
version: packageVersion,
build_version: process.env.APP_BUILD_VERSION?.slice(0, 8) || 'dev',
git_sha: gitSha.slice(0, 8) || 'unknown',
git_sha_full: gitSha,
build_time: process.env.APP_BUILD_TIME || new Date().toISOString(),
build_time: process.env.APP_BUILD_TIME || 'unknown',
image_tag: process.env.CONTAINER_IMAGE_TAG?.slice(0, 8) || 'local',
};

View File

@@ -20,6 +20,7 @@ import {
Menu,
X,
Users,
UserCog,
ListOrdered,
Key,
Bot
@@ -30,6 +31,7 @@ interface LayoutProps {
}
interface VersionInfo {
version: string;
build_version: string;
git_sha: string;
build_time: string;
@@ -124,7 +126,14 @@ export function Layout({ children }: LayoutProps) {
<path d="M3.5 6C2 8 1 10.5 1 13C1 18.5 6 22 12 22C18 22 23 18.5 23 13C23 10.5 22 8 20.5 6L12 12L3.5 6Z" opacity="0.7" />
</svg>
</div>
<span className="text-lg font-bold text-gray-900">CannaIQ</span>
<div>
<span className="text-lg font-bold text-gray-900">CannaIQ</span>
{versionInfo && (
<p className="text-xs text-gray-400">
v{versionInfo.version} ({versionInfo.git_sha}) {versionInfo.build_time !== 'unknown' && `- ${new Date(versionInfo.build_time).toLocaleDateString()}`}
</p>
)}
</div>
</div>
<p className="text-xs text-gray-500 mt-2 truncate">{user?.email}</p>
</div>
@@ -152,6 +161,7 @@ export function Layout({ children }: LayoutProps) {
<NavSection title="Admin">
<NavLink to="/admin/orchestrator" icon={<Activity className="w-4 h-4" />} label="Orchestrator" isActive={isActive('/admin/orchestrator')} />
<NavLink to="/users" icon={<UserCog className="w-4 h-4" />} label="Users" isActive={isActive('/users')} />
<NavLink to="/workers" icon={<Users className="w-4 h-4" />} label="Workers" isActive={isActive('/workers')} />
<NavLink to="/job-queue" icon={<ListOrdered className="w-4 h-4" />} label="Job Queue" isActive={isActive('/job-queue')} />
<NavLink to="/admin/seo" icon={<FileText className="w-4 h-4" />} label="SEO Pages" isActive={isActive('/admin/seo')} />
@@ -169,14 +179,6 @@ export function Layout({ children }: LayoutProps) {
<span>Logout</span>
</button>
</div>
{/* Version Footer */}
{versionInfo && (
<div className="px-3 py-2 border-t border-gray-200 bg-gray-50">
<p className="text-xs text-gray-500 text-center">{versionInfo.build_version} ({versionInfo.git_sha.slice(0, 7)})</p>
<p className="text-xs text-gray-400 text-center mt-0.5">{versionInfo.image_tag}</p>
</div>
)}
</>
);