mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
feat: remove old vanilla JS/CSS frontend, make React SPA the sole entry for ccw view
Remove the entire old template-based frontend (~106K lines) and make the React SPA the only way to access the ccw dashboard via `ccw view`. Key changes: - Delete all old frontend files: dashboard-css/ (37 CSS), dashboard-js/ (59 JS), assets/, dashboard.html, and legacy HTML templates - Delete dashboard-generator.ts and dashboard-generator-patch.ts - Simplify server.ts: remove ~234 lines of old frontend code (template constants, MODULE_CSS_FILES/MODULE_FILES arrays, generateServerDashboard(), /assets/* serving) - Rebase React frontend from /react/ to root / (vite.config.ts, react-frontend.ts) - Add /react/* -> /* 301 redirect for backward compatibility - Remove --frontend and --new CLI flags from view and serve commands - Remove generateDashboard export from public API (index.ts) - Simplify serve.ts and view.ts to always use React without conditional branching - Update all affected tests (unit, e2e) for React-only architecture BREAKING CHANGE: --frontend and --new CLI flags removed; generateDashboard export removed from ccw package; /react/ base path changed to /
This commit is contained in:
@@ -1,17 +1,14 @@
|
||||
import { startServer } from '../core/server.js';
|
||||
import { launchBrowser } from '../utils/browser-launcher.js';
|
||||
import { resolvePath, validatePath } from '../utils/path-resolver.js';
|
||||
import { validatePath } from '../utils/path-resolver.js';
|
||||
import { startReactFrontend, stopReactFrontend } from '../utils/react-frontend.js';
|
||||
import chalk from 'chalk';
|
||||
import type { Server } from 'http';
|
||||
|
||||
interface ServeOptions {
|
||||
port?: number;
|
||||
path?: string;
|
||||
host?: string;
|
||||
browser?: boolean;
|
||||
frontend?: 'js' | 'react' | 'both';
|
||||
new?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,11 +18,8 @@ interface ServeOptions {
|
||||
export async function serveCommand(options: ServeOptions): Promise<void> {
|
||||
const port = Number(options.port) || 3456;
|
||||
const host = options.host || '127.0.0.1';
|
||||
// --new flag is shorthand for --frontend react
|
||||
const frontend = options.new ? 'react' : (options.frontend || 'js');
|
||||
|
||||
// Keep Vite dev-server proxy aligned with the dashboard server port for direct access
|
||||
// (e.g. when opening http://localhost:{reactPort} instead of the proxied /react/ path).
|
||||
// Keep Vite dev-server proxy aligned with the dashboard server port.
|
||||
process.env.VITE_BACKEND_PORT = port.toString();
|
||||
|
||||
// Validate project path
|
||||
@@ -42,19 +36,15 @@ export async function serveCommand(options: ServeOptions): Promise<void> {
|
||||
console.log(chalk.blue.bold('\n CCW Dashboard Server\n'));
|
||||
console.log(chalk.gray(` Initial project: ${initialPath}`));
|
||||
console.log(chalk.gray(` Host: ${host}`));
|
||||
console.log(chalk.gray(` Port: ${port}`));
|
||||
console.log(chalk.gray(` Frontend: ${frontend}\n`));
|
||||
console.log(chalk.gray(` Port: ${port}\n`));
|
||||
|
||||
// Start React frontend if needed
|
||||
let reactPort: number | undefined;
|
||||
if (frontend === 'react' || frontend === 'both') {
|
||||
reactPort = port + 1;
|
||||
try {
|
||||
await startReactFrontend(reactPort);
|
||||
} catch (error) {
|
||||
console.error(chalk.red(`\n Failed to start React frontend: ${error}\n`));
|
||||
process.exit(1);
|
||||
}
|
||||
// Start React frontend
|
||||
const reactPort = port + 1;
|
||||
try {
|
||||
await startReactFrontend(reactPort);
|
||||
} catch (error) {
|
||||
console.error(chalk.red(`\n Failed to start React frontend: ${error}\n`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -64,7 +54,6 @@ export async function serveCommand(options: ServeOptions): Promise<void> {
|
||||
port,
|
||||
host,
|
||||
initialPath,
|
||||
frontend,
|
||||
reactPort
|
||||
});
|
||||
|
||||
@@ -78,31 +67,12 @@ export async function serveCommand(options: ServeOptions): Promise<void> {
|
||||
|
||||
console.log(chalk.green(` Server running at ${boundUrl}`));
|
||||
|
||||
// Display frontend URLs
|
||||
if (frontend === 'both') {
|
||||
console.log(chalk.gray(` JS Frontend: ${boundUrl}`));
|
||||
console.log(chalk.gray(` React Frontend: http://${host}:${reactPort}`));
|
||||
} else if (frontend === 'react') {
|
||||
console.log(chalk.gray(` React Frontend: http://${host}:${reactPort}`));
|
||||
}
|
||||
|
||||
// Open browser
|
||||
if (options.browser !== false) {
|
||||
console.log(chalk.cyan(' Opening in browser...'));
|
||||
try {
|
||||
// Determine which URL to open based on frontend setting
|
||||
let openUrl = browserUrl;
|
||||
if (frontend === 'react' && reactPort) {
|
||||
// React frontend: access via proxy path /react/
|
||||
openUrl = `http://${host}:${port}/react/`;
|
||||
} else if (frontend === 'both') {
|
||||
// Both frontends: default to JS frontend at root
|
||||
openUrl = browserUrl;
|
||||
}
|
||||
|
||||
// Add path query parameter for workspace switching
|
||||
const pathParam = initialPath ? `?path=${encodeURIComponent(initialPath)}` : '';
|
||||
await launchBrowser(openUrl + pathParam);
|
||||
await launchBrowser(browserUrl + pathParam);
|
||||
console.log(chalk.green.bold('\n Dashboard opened in browser!'));
|
||||
} catch (err) {
|
||||
const error = err as Error;
|
||||
|
||||
@@ -9,8 +9,6 @@ interface ViewOptions {
|
||||
path?: string;
|
||||
host?: string;
|
||||
browser?: boolean;
|
||||
frontend?: 'js' | 'react' | 'both';
|
||||
new?: boolean;
|
||||
}
|
||||
|
||||
interface SwitchWorkspaceResult {
|
||||
@@ -77,8 +75,6 @@ export async function viewCommand(options: ViewOptions): Promise<void> {
|
||||
const port = Number(options.port) || 3456;
|
||||
const host = options.host || '127.0.0.1';
|
||||
const browserHost = host === '0.0.0.0' || host === '::' ? 'localhost' : host;
|
||||
// --new flag is shorthand for --frontend react
|
||||
const frontend = options.new ? 'react' : (options.frontend || 'js');
|
||||
|
||||
// Resolve workspace path
|
||||
let workspacePath = process.cwd();
|
||||
@@ -105,12 +101,7 @@ export async function viewCommand(options: ViewOptions): Promise<void> {
|
||||
if (result.success) {
|
||||
console.log(chalk.green(` Workspace switched successfully`));
|
||||
|
||||
// Determine URL based on frontend type
|
||||
let urlPath = '';
|
||||
if (frontend === 'react') {
|
||||
urlPath = '/react';
|
||||
}
|
||||
const url = `http://${browserHost}:${port}${urlPath}/?path=${encodeURIComponent(workspacePath)}`;
|
||||
const url = `http://${browserHost}:${port}/?path=${encodeURIComponent(workspacePath)}`;
|
||||
|
||||
if (options.browser !== false) {
|
||||
console.log(chalk.cyan(' Opening in browser...'));
|
||||
@@ -135,8 +126,7 @@ export async function viewCommand(options: ViewOptions): Promise<void> {
|
||||
path: workspacePath,
|
||||
port: port,
|
||||
host,
|
||||
browser: options.browser,
|
||||
frontend: frontend
|
||||
browser: options.browser
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user