Frontend (Unit 2 completion): dual dev-server tooling (pnpm dev:slave, pnpm dev:all), per-instance browser tab titles, and a backend capability check (SystemController + useSystemCapabilities + ModuleGuard) so a Master-only page is hidden on a slave instance instead of assuming every backend has every module. Master/slave protocol fixes surfaced by actually running master and slave side by side locally: - Deactivating a CMS instance (Inactive) now releases the slave's master gate instead of leaving it stuck on its last pushed status. - The periodic integrity check now also re-pushes status to every reachable slave (previously URL-verification only) and runs once immediately on startup. - Added the originally-specified (but never implemented) slave-pull path: a slave now periodically polls its own status from the master (GET /api/v1/SlaveStatus) and fails open to Available if the master is unreachable for too long, complementing the existing push. - The slave's own Settings page can no longer "successfully" change local availability while the master controls it; it's now locked with an explanatory banner and the backend rejects the write with 409 instead of silently no-op'ing it. - CMS instance status badges now match the dashboard's color/icon styling instead of a plain grey badge. Also corrected the master-cms-module design docs to match this as-built behavior, and flagged (without a full rewrite) a larger, pre-existing divergence between its inception-stage application design and what construction actually built. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
72 lines
2.1 KiB
JSON
72 lines
2.1 KiB
JSON
{
|
|
"name": "frontend",
|
|
"private": true,
|
|
"version": "0.0.0",
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"dev:slave": "vite --mode slave --port 5174",
|
|
"dev:all": "concurrently -n master,slave -c blue,magenta \"pnpm dev\" \"pnpm dev:slave\"",
|
|
"build": "tsc -b && vite build",
|
|
"lint": "eslint .",
|
|
"format": "prettier --write \"src/**/*.{ts,tsx,css}\"",
|
|
"format:check": "prettier --check \"src/**/*.{ts,tsx,css}\"",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"test:coverage": "vitest run --coverage",
|
|
"preview": "vite preview"
|
|
},
|
|
"dependencies": {
|
|
"@hookform/resolvers": "^5.4.0",
|
|
"@radix-ui/react-dialog": "^1.1.17",
|
|
"@radix-ui/react-dropdown-menu": "^2.1.18",
|
|
"@radix-ui/react-label": "^2.1.10",
|
|
"@radix-ui/react-select": "^2.3.1",
|
|
"@radix-ui/react-slot": "^1.3.0",
|
|
"@tanstack/react-query": "^5.101.0",
|
|
"@tanstack/react-router": "^1.170.16",
|
|
"class-variance-authority": "^0.7.1",
|
|
"clsx": "^2.1.1",
|
|
"i18next": "^26.3.1",
|
|
"i18next-browser-languagedetector": "^8.2.1",
|
|
"lucide-react": "^1.21.0",
|
|
"react": "^19.2.6",
|
|
"react-dom": "^19.2.6",
|
|
"react-hook-form": "^7.79.0",
|
|
"react-i18next": "^17.0.8",
|
|
"sonner": "^2.0.7",
|
|
"tailwind-merge": "^3.6.0",
|
|
"zod": "^4.4.3"
|
|
},
|
|
"devDependencies": {
|
|
"@eslint/js": "^10.0.1",
|
|
"@tailwindcss/vite": "^4.3.1",
|
|
"@testing-library/jest-dom": "^6.9.1",
|
|
"@testing-library/react": "^16.3.2",
|
|
"@testing-library/user-event": "^14.6.1",
|
|
"@types/node": "^24.12.3",
|
|
"@types/react": "^19.2.14",
|
|
"@types/react-dom": "^19.2.3",
|
|
"@vitejs/plugin-react": "^6.0.1",
|
|
"@vitest/coverage-v8": "^4.1.9",
|
|
"concurrently": "^9.1.2",
|
|
"eslint": "^10.3.0",
|
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
"eslint-plugin-react-refresh": "^0.5.2",
|
|
"globals": "^17.6.0",
|
|
"jsdom": "^29.1.1",
|
|
"msw": "^2.14.6",
|
|
"prettier": "^3.8.4",
|
|
"tailwindcss": "^4.3.1",
|
|
"typescript": "~6.0.2",
|
|
"typescript-eslint": "^8.59.2",
|
|
"vite": "^8.0.12",
|
|
"vitest": "^4.1.9"
|
|
},
|
|
"msw": {
|
|
"workerDirectory": [
|
|
"public"
|
|
]
|
|
}
|
|
}
|