refactor: improve KanbanCard styling and enhance path normalization in worktree routes

- Updated the button variant in KanbanCard for better visual consistency.
- Adjusted CSS classes for improved styling of shortcut keys.
- Introduced a normalizePath function to ensure consistent path formatting across platforms.
- Updated worktree routes to utilize normalizePath for path handling, enhancing cross-platform compatibility.
This commit is contained in:
Cody Seibert
2025-12-16 13:09:20 -05:00
parent 064a395c4c
commit 8482cdab87
5 changed files with 23 additions and 18 deletions

View File

@@ -866,9 +866,9 @@ export const KanbanCard = memo(function KanbanCard({
<> <>
{onViewOutput && ( {onViewOutput && (
<Button <Button
variant="default" variant="secondary"
size="sm" size="sm"
className="flex-1 h-7 text-[11px] bg-[var(--status-info)] hover:bg-[var(--status-info)]/90" className="flex-1 h-7 text-[11px]"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
onViewOutput(); onViewOutput();
@@ -880,7 +880,7 @@ export const KanbanCard = memo(function KanbanCard({
Logs Logs
{shortcutKey && ( {shortcutKey && (
<span <span
className="ml-1.5 px-1 py-0.5 text-[9px] font-mono rounded bg-white/20" className="ml-1.5 px-1 py-0.5 text-[9px] font-mono rounded bg-foreground/10"
data-testid={`shortcut-key-${feature.id}`} data-testid={`shortcut-key-${feature.id}`}
> >
{shortcutKey} {shortcutKey}
@@ -972,7 +972,7 @@ export const KanbanCard = memo(function KanbanCard({
)} )}
{!isCurrentAutoTask && feature.status === "verified" && ( {!isCurrentAutoTask && feature.status === "verified" && (
<> <>
{/* Logs button - styled like Refine */} {/* Logs button */}
{onViewOutput && ( {onViewOutput && (
<Button <Button
variant="secondary" variant="secondary"

View File

@@ -13,6 +13,15 @@ import {
const logger = createLogger("Worktree"); const logger = createLogger("Worktree");
const execAsync = promisify(exec); const execAsync = promisify(exec);
/**
* Normalize path separators to forward slashes for cross-platform consistency.
* This ensures paths from `path.join()` (backslashes on Windows) match paths
* from git commands (which may use forward slashes).
*/
export function normalizePath(p: string): string {
return p.replace(/\\/g, "/");
}
/** /**
* Check if a path is a git repo * Check if a path is a git repo
*/ */

View File

@@ -7,7 +7,7 @@ import { exec } from "child_process";
import { promisify } from "util"; import { promisify } from "util";
import path from "path"; import path from "path";
import { mkdir, access } from "fs/promises"; import { mkdir, access } from "fs/promises";
import { isGitRepo, getErrorMessage, logError } from "../common.js"; import { isGitRepo, getErrorMessage, logError, normalizePath } from "../common.js";
import { trackBranch } from "./branch-tracking.js"; import { trackBranch } from "./branch-tracking.js";
const execAsync = promisify(exec); const execAsync = promisify(exec);
@@ -48,14 +48,10 @@ export function createCreateHandler() {
// Check if worktree already exists // Check if worktree already exists
try { try {
await access(worktreePath); await access(worktreePath);
// Worktree already exists, return it instead of error // Worktree already exists, return error
res.json({ res.status(400).json({
success: true, success: false,
worktree: { error: `Worktree "${branchName}" already exists`,
path: worktreePath,
branch: branchName,
isNew: false,
},
}); });
return; return;
} catch { } catch {
@@ -96,7 +92,7 @@ export function createCreateHandler() {
res.json({ res.json({
success: true, success: true,
worktree: { worktree: {
path: worktreePath, path: normalizePath(worktreePath),
branch: branchName, branch: branchName,
isNew: !branchExists, isNew: !branchExists,
}, },

View File

@@ -7,7 +7,7 @@ import { exec } from "child_process";
import { promisify } from "util"; import { promisify } from "util";
import path from "path"; import path from "path";
import fs from "fs/promises"; import fs from "fs/promises";
import { getErrorMessage, logError } from "../common.js"; import { getErrorMessage, logError, normalizePath } from "../common.js";
const execAsync = promisify(exec); const execAsync = promisify(exec);
@@ -38,7 +38,7 @@ export function createInfoHandler() {
}); });
res.json({ res.json({
success: true, success: true,
worktreePath, worktreePath: normalizePath(worktreePath),
branchName: stdout.trim(), branchName: stdout.trim(),
}); });
} catch { } catch {

View File

@@ -8,7 +8,7 @@
import type { Request, Response } from "express"; import type { Request, Response } from "express";
import { exec } from "child_process"; import { exec } from "child_process";
import { promisify } from "util"; import { promisify } from "util";
import { isGitRepo, getErrorMessage, logError } from "../common.js"; import { isGitRepo, getErrorMessage, logError, normalizePath } from "../common.js";
const execAsync = promisify(exec); const execAsync = promisify(exec);
@@ -64,7 +64,7 @@ export function createListHandler() {
for (const line of lines) { for (const line of lines) {
if (line.startsWith("worktree ")) { if (line.startsWith("worktree ")) {
current.path = line.slice(9); current.path = normalizePath(line.slice(9));
} else if (line.startsWith("branch ")) { } else if (line.startsWith("branch ")) {
current.branch = line.slice(7).replace("refs/heads/", ""); current.branch = line.slice(7).replace("refs/heads/", "");
} else if (line === "") { } else if (line === "") {