diff --git a/.husky/pre-commit b/.husky/pre-commit index 54333a0..f314350 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,18 +1,23 @@ #!/bin/sh -# Run lint-staged for frontend files (Biome) -cd app -npx lint-staged -cd .. +# Run lint-staged for frontend files (Biome) only if there are relevant files staged +STAGED_FRONTEND_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^app/.*\.(js|ts|tsx|json)$' || true) +if [ -n "$STAGED_FRONTEND_FILES" ]; then + echo "Running Biome on staged frontend files..." + cd app + npx lint-staged || exit 1 + cd .. +fi # Run Ruff for Python backend files -if command -v ruff >/dev/null 2>&1; then - # Get staged Python files in api directory - STAGED_PY_FILES=$(git diff --cached --name-only --diff-filter=ACM -- '*.py' | grep '^api/') - if [ -n "$STAGED_PY_FILES" ]; then +STAGED_PY_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^api/.*\.py$' || true) +if [ -n "$STAGED_PY_FILES" ]; then + if command -v ruff >/dev/null 2>&1; then echo "Running Ruff on staged Python files..." echo "$STAGED_PY_FILES" | xargs ruff check --fix # Re-add fixed files to staging echo "$STAGED_PY_FILES" | xargs git add fi fi + +exit 0 diff --git a/README.md b/README.md index 186afad..f96d9a7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # PrintQue - 3D Printer Management System +[![Discord](https://img.shields.io/badge/Discord-PrintQue-5865F2?logo=discord&logoColor=white)](https://discord.gg/UhFBCKdq) + PrintQue is a powerful and easy-to-use management system designed for 3D print farms. It provides centralized control, monitoring, and queue management for multiple 3D printers, helping you maximize efficiency and productivity. ## Quick Start @@ -258,8 +260,7 @@ Logs are stored in your user directory: ### Support For assistance with PrintQue: -- **Email**: zhartley@hotmail.ca -- **Website**: www.printque.ca +- **Discord**: [Join our community](https://discord.gg/UhFBCKdq) ## Development diff --git a/api/services/state.py b/api/services/state.py index ebaaa15..ddf37c0 100644 --- a/api/services/state.py +++ b/api/services/state.py @@ -13,7 +13,8 @@ from flask import current_app # Set up logging directory -LOG_DIR = os.path.join(os.path.expanduser("~"), "PrintQueData") +# Support DATA_DIR environment variable for test isolation +LOG_DIR = os.path.join(os.getenv('DATA_DIR', os.path.expanduser("~")), "PrintQueData") os.makedirs(LOG_DIR, exist_ok=True) LOG_FILE = os.path.join(LOG_DIR, "app.log") diff --git a/app/src/__tests__/components/PrinterCard.test.tsx b/app/src/__tests__/components/PrinterCard.test.tsx index 7e403e0..0596887 100644 --- a/app/src/__tests__/components/PrinterCard.test.tsx +++ b/app/src/__tests__/components/PrinterCard.test.tsx @@ -15,6 +15,15 @@ vi.mock('../../hooks', () => ({ useResumePrint: () => ({ mutate: vi.fn(), isPending: false }), useMarkReady: () => ({ mutate: vi.fn(), isPending: false }), useClearError: () => ({ mutate: vi.fn(), isPending: false }), + useDeletePrinter: () => ({ mutate: vi.fn(), mutateAsync: vi.fn(), isPending: false }), +})) + +// Mock sonner toast +vi.mock('sonner', () => ({ + toast: { + success: vi.fn(), + error: vi.fn(), + }, })) const createWrapper = () => { diff --git a/app/src/components/printers/PrinterCard.tsx b/app/src/components/printers/PrinterCard.tsx index b5f5dd6..d55001f 100644 --- a/app/src/components/printers/PrinterCard.tsx +++ b/app/src/components/printers/PrinterCard.tsx @@ -9,6 +9,7 @@ import { Square, Thermometer, } from 'lucide-react' +import { toast } from 'sonner' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' @@ -19,7 +20,14 @@ import { DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { Progress } from '@/components/ui/progress' -import { useClearError, useMarkReady, usePausePrint, useResumePrint, useStopPrint } from '@/hooks' +import { + useClearError, + useDeletePrinter, + useMarkReady, + usePausePrint, + useResumePrint, + useStopPrint, +} from '@/hooks' import type { Printer } from '@/types' interface PrinterCardProps { @@ -56,12 +64,23 @@ export function PrinterCard({ printer }: PrinterCardProps) { const resumePrint = useResumePrint() const markReady = useMarkReady() const clearError = useClearError() + const deletePrinter = useDeletePrinter() const handleStop = () => stopPrint.mutate(printer.name) const handlePause = () => pausePrint.mutate(printer.name) const handleResume = () => resumePrint.mutate(printer.name) const handleMarkReady = () => markReady.mutate(printer.name) const handleClearError = () => clearError.mutate(printer.name) + const handleDelete = async () => { + if (confirm(`Are you sure you want to delete printer "${printer.name}"?`)) { + try { + await deletePrinter.mutateAsync(printer.name) + toast.success('Printer deleted') + } catch (_error) { + toast.error('Failed to delete printer') + } + } + } const isPrinting = printer.status === 'PRINTING' const isPaused = printer.status === 'PAUSED' @@ -237,7 +256,9 @@ export function PrinterCard({ printer }: PrinterCardProps) { Edit - Delete + + Delete +